Improve tooling model + add Gradle version checking (#1602)
* [gradle-plugin] Add tests for IDE model * [gradle-plugin] Check Gradle version * [gradle-plugin] Provide language, api and konan version in the model * [gradle-plugin] Use String instead of KonanTarget in the IDE model * [gradle-plugin] Rename Produce -> KonanOutput * [version] Make KonanVersion an interface to allow passing it to IDE * [gradle-plugin] Replace KonanOutput with CompilerOutputKind * [gradle-plugin] Don't override usual jar with a fat one * [gradle-plugin] Fix IDE model tests * [gradle-plugin] Add library search paths in IDE model * [gradle-plugin] Use 4.7 as a required version for the plugin * [gradle-plugin] "Kotlinfy" the version check
This commit is contained in:
+7
-6
@@ -40,7 +40,8 @@ ext {
|
|||||||
kotlinReflectModule="org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"
|
kotlinReflectModule="org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"
|
||||||
kotlinScriptRuntimeModule="org.jetbrains.kotlin:kotlin-script-runtime:${kotlinVersion}"
|
kotlinScriptRuntimeModule="org.jetbrains.kotlin:kotlin-script-runtime:${kotlinVersion}"
|
||||||
|
|
||||||
gradlePluginVersion = KonanVersion.CURRENT.gradlePluginVersion
|
konanVersionFull = KonanVersion.Companion.CURRENT
|
||||||
|
gradlePluginVersion = konanVersionFull.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
@@ -345,7 +346,7 @@ task bundle(type: (isWindows()) ? Zip : Tar) {
|
|||||||
dependsOn('crossDistPlatformLibs')
|
dependsOn('crossDistPlatformLibs')
|
||||||
dependsOn('crossDist')
|
dependsOn('crossDist')
|
||||||
def simpleOsName = HostManager.simpleOsName()
|
def simpleOsName = HostManager.simpleOsName()
|
||||||
baseName = "kotlin-native-$simpleOsName-${KonanVersion.CURRENT}"
|
baseName = "kotlin-native-$simpleOsName-$konanVersionFull"
|
||||||
from("$project.rootDir/dist") {
|
from("$project.rootDir/dist") {
|
||||||
include '**'
|
include '**'
|
||||||
exclude 'dependencies'
|
exclude 'dependencies'
|
||||||
@@ -403,7 +404,7 @@ task bundle(type: (isWindows()) ? Zip : Tar) {
|
|||||||
task uploadBundle {
|
task uploadBundle {
|
||||||
dependsOn ':bundle'
|
dependsOn ':bundle'
|
||||||
doLast {
|
doLast {
|
||||||
def kind = (KonanVersion.CURRENT.meta == MetaVersion.DEV) ? "dev" : "releases"
|
def kind = (konanVersionFull.meta == MetaVersion.DEV) ? "dev" : "releases"
|
||||||
def ftpSettings = [
|
def ftpSettings = [
|
||||||
server: project.findProperty("cdnUrl") ?: System.getenv("CDN_URL"),
|
server: project.findProperty("cdnUrl") ?: System.getenv("CDN_URL"),
|
||||||
userid: project.findProperty("cdnUser") ?: System.getenv("CDN_USER"),
|
userid: project.findProperty("cdnUser") ?: System.getenv("CDN_USER"),
|
||||||
@@ -430,9 +431,9 @@ task performance {
|
|||||||
task teamcityKonanVersion {
|
task teamcityKonanVersion {
|
||||||
doLast {
|
doLast {
|
||||||
println("##teamcity[setParameter name='kotlin.native.version.base' value='$konanVersion']")
|
println("##teamcity[setParameter name='kotlin.native.version.base' value='$konanVersion']")
|
||||||
println("##teamcity[setParameter name='kotlin.native.version.full' value='$KonanVersion.CURRENT']")
|
println("##teamcity[setParameter name='kotlin.native.version.full' value='$konanVersionFull']")
|
||||||
println("##teamcity[setParameter name='kotlin.native.version.meta' value='${KonanVersion.CURRENT.meta.toString().toLowerCase()}']")
|
println("##teamcity[setParameter name='kotlin.native.version.meta' value='${konanVersionFull.meta.toString().toLowerCase()}']")
|
||||||
println("##teamcity[buildNumber '${KonanVersion.CURRENT.toString(true, true)}']")
|
println("##teamcity[buildNumber '${konanVersionFull.toString(true, true)}']")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ sourceSets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileKotlin{
|
compileKotlin {
|
||||||
dependsOn('generateCompilerVersion')
|
dependsOn('generateCompilerVersion')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,42 +42,57 @@ open class VersionGenerator: DefaultTask() {
|
|||||||
}?: -1
|
}?: -1
|
||||||
|
|
||||||
+ """
|
+ """
|
||||||
|package org.jetbrains.kotlin.konan
|
|package org.jetbrains.kotlin.konan
|
||||||
|data class KonanVersion(val meta: MetaVersion = MetaVersion.DEV,
|
|
|
||||||
| val major: Int,
|
|import java.io.Serializable
|
||||||
| val minor: Int,
|
|
|
||||||
| val maintenance: Int,
|
|interface KonanVersion : Serializable {
|
||||||
| val build:Int) {
|
| val meta: MetaVersion
|
||||||
| companion object {
|
| val major: Int
|
||||||
| val CURRENT = KonanVersion($meta, $major, $minor, $maintenance, $build)
|
| val minor: Int
|
||||||
| }
|
| val maintenance: Int
|
||||||
| fun toString(showMeta: Boolean, showBuild: Boolean) = buildString {
|
| val build: Int
|
||||||
| append(major)
|
|
|
||||||
| append('.')
|
| fun toString(showMeta: Boolean, showBuild: Boolean): String
|
||||||
| append(minor)
|
|
|
||||||
| if (maintenance != 0) {
|
| companion object {
|
||||||
| append('.')
|
| val CURRENT = KonanVersionImpl($meta, $major, $minor, $maintenance, $build)
|
||||||
| append(maintenance)
|
| }
|
||||||
| }
|
|}
|
||||||
| if (showMeta) {
|
|
|
||||||
| append('-')
|
|data class KonanVersionImpl(
|
||||||
| append(meta.metaString)
|
| override val meta: MetaVersion = MetaVersion.DEV,
|
||||||
| }
|
| override val major: Int,
|
||||||
| if (showBuild && build != -1) {
|
| override val minor: Int,
|
||||||
| append('-')
|
| override val maintenance: Int,
|
||||||
| append(build)
|
| override val build: Int
|
||||||
| }
|
|) : KonanVersion {
|
||||||
| }
|
|
|
||||||
|
|
| override fun toString(showMeta: Boolean, showBuild: Boolean) = buildString {
|
||||||
| private val isRelease: Boolean
|
| append(major)
|
||||||
| get() = meta == MetaVersion.RELEASE
|
| append('.')
|
||||||
|
|
| append(minor)
|
||||||
| private val versionString by lazy { toString(!isRelease, !isRelease) }
|
| if (maintenance != 0) {
|
||||||
|
|
| append('.')
|
||||||
| override fun toString() = versionString
|
| append(maintenance)
|
||||||
|
|
| }
|
||||||
| val gradlePluginVersion by lazy { versionString }
|
| if (showMeta) {
|
||||||
|}
|
| append('-')
|
||||||
|
| append(meta.metaString)
|
||||||
|
| }
|
||||||
|
| if (showBuild && build != -1) {
|
||||||
|
| append('-')
|
||||||
|
| append(build)
|
||||||
|
| }
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
| private val isRelease: Boolean
|
||||||
|
| get() = meta == MetaVersion.RELEASE
|
||||||
|
|
|
||||||
|
| private val versionString by lazy { toString(!isRelease, !isRelease) }
|
||||||
|
|
|
||||||
|
| override fun toString() = versionString
|
||||||
|
|}
|
||||||
""".trimMargin()
|
""".trimMargin()
|
||||||
}
|
}
|
||||||
versionFile.printWriter().use {
|
versionFile.printWriter().use {
|
||||||
|
|||||||
@@ -19,14 +19,14 @@ package org.jetbrains.kotlin.konan
|
|||||||
/**
|
/**
|
||||||
* https://en.wikipedia.org/wiki/Software_versioning
|
* https://en.wikipedia.org/wiki/Software_versioning
|
||||||
* scheme major.minor[.build[.revision]].
|
* scheme major.minor[.build[.revision]].
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum class MetaVersion(val metaString:String) {
|
enum class MetaVersion(val metaString: String) {
|
||||||
DEV("dev"),
|
DEV("dev"),
|
||||||
EAP("eap"),
|
EAP("eap"),
|
||||||
ALPHA("alpha"),
|
ALPHA("alpha"),
|
||||||
BETA("beta"),
|
BETA("beta"),
|
||||||
RC1("rc1"),
|
RC1("rc1"),
|
||||||
RC2("rc2"),
|
RC2("rc2"),
|
||||||
RELEASE("release")
|
RELEASE("release")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ enum class Architecture(val bitness: Int) {
|
|||||||
WASM32(32);
|
WASM32(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class KonanTarget(override val name: String, val family: Family, val architecture: Architecture) : Named, Serializable {
|
sealed class KonanTarget(override val name: String, val family: Family, val architecture: Architecture) : Named {
|
||||||
object ANDROID_ARM32 : KonanTarget( "android_arm32", Family.ANDROID, Architecture.ARM32)
|
object ANDROID_ARM32 : KonanTarget( "android_arm32", Family.ANDROID, Architecture.ARM32)
|
||||||
object ANDROID_ARM64 : KonanTarget( "android_arm64", Family.ANDROID, Architecture.ARM64)
|
object ANDROID_ARM64 : KonanTarget( "android_arm64", Family.ANDROID, Architecture.ARM64)
|
||||||
object IOS_ARM64 : KonanTarget( "ios_arm64", Family.IOS, Architecture.ARM64)
|
object IOS_ARM64 : KonanTarget( "ios_arm64", Family.IOS, Architecture.ARM64)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ apply plugin: 'com.jfrog.bintray'
|
|||||||
apply plugin: 'com.github.johnrengelman.shadow'
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
|
|
||||||
group = 'org.jetbrains.kotlin'
|
group = 'org.jetbrains.kotlin'
|
||||||
version = KonanVersion.CURRENT.gradlePluginVersion
|
version = KonanVersion.Companion.CURRENT.toString()
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -76,11 +76,17 @@ dependencies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
appendix = "no-shared"
|
||||||
|
}
|
||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
configurations = [project.configurations.bundleDependencies]
|
configurations = [project.configurations.bundleDependencies]
|
||||||
classifier = null
|
classifier = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assemble.dependsOn shadowJar
|
||||||
|
|
||||||
test {
|
test {
|
||||||
systemProperty("kotlin.version", buildKotlinVersion)
|
systemProperty("kotlin.version", buildKotlinVersion)
|
||||||
if (project.hasProperty("konan.home")) {
|
if (project.hasProperty("konan.home")) {
|
||||||
|
|||||||
+10
-6
@@ -24,6 +24,7 @@ import org.gradle.api.tasks.InputFiles
|
|||||||
import org.gradle.api.tasks.Internal
|
import org.gradle.api.tasks.Internal
|
||||||
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanArtifactWithLibrariesTask
|
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanArtifactWithLibrariesTask
|
||||||
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanBuildingTask
|
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanBuildingTask
|
||||||
|
import org.jetbrains.kotlin.konan.library.SearchPathResolver
|
||||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||||
import org.jetbrains.kotlin.konan.target.Distribution
|
import org.jetbrains.kotlin.konan.target.Distribution
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
@@ -132,14 +133,17 @@ open class KonanLibrariesSpec(val task: KonanArtifactWithLibrariesTask, val proj
|
|||||||
if (this != another) { evaluationDependsOn(another.path) }
|
if (this != another) { evaluationDependsOn(another.path) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun asFiles(): List<File> = mutableListOf<File>().apply {
|
fun asFiles(): List<File> = asFiles(
|
||||||
|
defaultResolver(
|
||||||
|
repos.map { it.absolutePath },
|
||||||
|
task.konanTarget,
|
||||||
|
Distribution(konanHomeOverride = project.konanHome)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun asFiles(resolver: SearchPathResolver): List<File> = mutableListOf<File>().apply {
|
||||||
files.flatMapTo(this) { it.files }
|
files.flatMapTo(this) { it.files }
|
||||||
addAll(artifactFiles)
|
addAll(artifactFiles)
|
||||||
val resolver = defaultResolver(
|
|
||||||
repos.map { it.absolutePath },
|
|
||||||
task.konanTarget,
|
|
||||||
Distribution(konanHomeOverride = project.konanHome)
|
|
||||||
)
|
|
||||||
namedKlibs.mapTo(this) { project.file(resolver.resolve(it).absolutePath) }
|
namedKlibs.mapTo(this) { project.file(resolver.resolve(it).absolutePath) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-1
@@ -29,7 +29,9 @@ import org.gradle.api.publish.PublishingExtension
|
|||||||
import org.gradle.api.publish.maven.MavenPublication
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
|
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
|
||||||
import org.gradle.language.cpp.internal.NativeVariantIdentity
|
import org.gradle.language.cpp.internal.NativeVariantIdentity
|
||||||
|
import org.gradle.tooling.UnsupportedVersionException
|
||||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||||
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KonanPlugin.Companion.COMPILE_ALL_TASK_NAME
|
import org.jetbrains.kotlin.gradle.plugin.KonanPlugin.Companion.COMPILE_ALL_TASK_NAME
|
||||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanToolingModelBuilder
|
import org.jetbrains.kotlin.gradle.plugin.model.KonanToolingModelBuilder
|
||||||
import org.jetbrains.kotlin.gradle.plugin.tasks.*
|
import org.jetbrains.kotlin.gradle.plugin.tasks.*
|
||||||
@@ -284,21 +286,30 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
|
|||||||
internal const val KONAN_DOWNLOAD_TASK_NAME = "checkKonanCompiler"
|
internal const val KONAN_DOWNLOAD_TASK_NAME = "checkKonanCompiler"
|
||||||
internal const val KONAN_GENERATE_CMAKE_TASK_NAME = "generateCMake"
|
internal const val KONAN_GENERATE_CMAKE_TASK_NAME = "generateCMake"
|
||||||
internal const val COMPILE_ALL_TASK_NAME = "compileKonan"
|
internal const val COMPILE_ALL_TASK_NAME = "compileKonan"
|
||||||
internal const val KONAN_MAIN_VARIANT = "konan_main_variant"
|
|
||||||
|
|
||||||
internal const val KONAN_EXTENSION_NAME = "konan"
|
internal const val KONAN_EXTENSION_NAME = "konan"
|
||||||
|
|
||||||
|
internal val REQUIRED_GRADLE_VERSION = GradleVersion.version("4.7")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Project.cleanKonan() = project.tasks.withType(KonanBuildingTask::class.java).forEach {
|
private fun Project.cleanKonan() = project.tasks.withType(KonanBuildingTask::class.java).forEach {
|
||||||
project.delete(it.artifact)
|
project.delete(it.artifact)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkGradleVersion() = GradleVersion.current().let { current ->
|
||||||
|
check(current >= REQUIRED_GRADLE_VERSION) {
|
||||||
|
"Kotlin/Native Gradle plugin is incompatible with this version of Gradle.\n" +
|
||||||
|
"The minimal required version is ${REQUIRED_GRADLE_VERSION}\n" +
|
||||||
|
"Current version is ${current}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun apply(project: ProjectInternal?) {
|
override fun apply(project: ProjectInternal?) {
|
||||||
if (project == null) {
|
if (project == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
checkGradleVersion()
|
||||||
registry.register(KonanToolingModelBuilder)
|
registry.register(KonanToolingModelBuilder)
|
||||||
project.plugins.apply("base")
|
project.plugins.apply("base")
|
||||||
// Create necessary tasks and extensions.
|
// Create necessary tasks and extensions.
|
||||||
|
|||||||
+9
-6
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.plugin.model
|
package org.jetbrains.kotlin.gradle.plugin.model
|
||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.tasks.Produce
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
@@ -26,8 +26,10 @@ import java.io.Serializable
|
|||||||
* This model is shared with the client processes such as an IDE.
|
* This model is shared with the client processes such as an IDE.
|
||||||
*/
|
*/
|
||||||
interface KonanModel : Serializable {
|
interface KonanModel : Serializable {
|
||||||
val konanHome: String
|
val konanHome: File
|
||||||
val konanVersion: String
|
val konanVersion: KonanVersion
|
||||||
|
val languageVersion: String?
|
||||||
|
val apiVersion: String?
|
||||||
|
|
||||||
val artifacts: List<KonanModelArtifact>
|
val artifacts: List<KonanModelArtifact>
|
||||||
}
|
}
|
||||||
@@ -37,11 +39,12 @@ interface KonanModel : Serializable {
|
|||||||
*/
|
*/
|
||||||
interface KonanModelArtifact : Serializable {
|
interface KonanModelArtifact : Serializable {
|
||||||
val name: String
|
val name: String
|
||||||
val type: Produce
|
val type: CompilerOutputKind
|
||||||
val targetPlatform: KonanTarget
|
val targetPlatform: String
|
||||||
val file: File
|
val file: File
|
||||||
val buildTaskName: String
|
val buildTaskName: String
|
||||||
val srcDirs: List<File>
|
val srcDirs: List<File>
|
||||||
val srcFiles: List<File>
|
val srcFiles: List<File>
|
||||||
val libraries: List<File>
|
val libraries: List<File>
|
||||||
|
val searchPaths: List<File>
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-12
@@ -5,10 +5,8 @@ import org.gradle.tooling.provider.model.ToolingModelBuilder
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.konanArtifactsContainer
|
import org.jetbrains.kotlin.gradle.plugin.konanArtifactsContainer
|
||||||
import org.jetbrains.kotlin.gradle.plugin.konanExtension
|
import org.jetbrains.kotlin.gradle.plugin.konanExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.konanHome
|
import org.jetbrains.kotlin.gradle.plugin.konanHome
|
||||||
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanBuildingTask
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanCompileTask
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.gradle.plugin.tasks.Produce
|
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
@@ -20,26 +18,31 @@ object KonanToolingModelBuilder : ToolingModelBuilder {
|
|||||||
val artifacts = project.konanArtifactsContainer.flatten().toList().map { it.toModelArtifact() }
|
val artifacts = project.konanArtifactsContainer.flatten().toList().map { it.toModelArtifact() }
|
||||||
return KonanModelImpl(
|
return KonanModelImpl(
|
||||||
artifacts,
|
artifacts,
|
||||||
project.konanHome,
|
project.file(project.konanHome),
|
||||||
// TODO: Provide a better support for the default version
|
KonanVersion.CURRENT,
|
||||||
project.konanExtension.languageVersion ?: "1.2"
|
// TODO: Provide defaults for these versions.
|
||||||
|
project.konanExtension.languageVersion,
|
||||||
|
project.konanExtension.apiVersion
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal data class KonanModelImpl(
|
internal data class KonanModelImpl(
|
||||||
override val artifacts: List<KonanModelArtifact>,
|
override val artifacts: List<KonanModelArtifact>,
|
||||||
override val konanHome: String,
|
override val konanHome: File,
|
||||||
override val konanVersion: String
|
override val konanVersion: KonanVersion,
|
||||||
|
override val languageVersion: String?,
|
||||||
|
override val apiVersion: String?
|
||||||
) : KonanModel
|
) : KonanModel
|
||||||
|
|
||||||
internal data class KonanModelArtifactImpl(
|
internal data class KonanModelArtifactImpl(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val file: File,
|
override val file: File,
|
||||||
override val type: Produce,
|
override val type: CompilerOutputKind,
|
||||||
override val targetPlatform: KonanTarget,
|
override val targetPlatform: String,
|
||||||
override val buildTaskName: String,
|
override val buildTaskName: String,
|
||||||
override val srcDirs: List<File>,
|
override val srcDirs: List<File>,
|
||||||
override val srcFiles: List<File>,
|
override val srcFiles: List<File>,
|
||||||
override val libraries: List<File>
|
override val libraries: List<File>,
|
||||||
|
override val searchPaths: List<File>
|
||||||
) : KonanModelArtifact
|
) : KonanModelArtifact
|
||||||
|
|||||||
+31
-27
@@ -22,17 +22,11 @@ import org.gradle.api.tasks.*
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
|
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
|
||||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifactImpl
|
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifactImpl
|
||||||
|
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
|
import org.jetbrains.kotlin.konan.target.Distribution
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
enum class Produce(val cliOption: String, val kind: CompilerOutputKind) {
|
|
||||||
PROGRAM("program", CompilerOutputKind.PROGRAM),
|
|
||||||
DYNAMIC("dynamic", CompilerOutputKind.DYNAMIC),
|
|
||||||
FRAMEWORK("framework", CompilerOutputKind.FRAMEWORK),
|
|
||||||
LIBRARY("library", CompilerOutputKind.LIBRARY),
|
|
||||||
BITCODE("bitcode", CompilerOutputKind.BITCODE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A task compiling the target executable/library using Kotlin/Native compiler
|
* A task compiling the target executable/library using Kotlin/Native compiler
|
||||||
*/
|
*/
|
||||||
@@ -40,16 +34,16 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
|
|||||||
|
|
||||||
@Internal override val toolRunner = KonanCompilerRunner(project)
|
@Internal override val toolRunner = KonanCompilerRunner(project)
|
||||||
|
|
||||||
abstract val produce: Produce
|
abstract val produce: CompilerOutputKind
|
||||||
@Internal get
|
@Internal get
|
||||||
|
|
||||||
// Output artifact --------------------------------------------------------
|
// Output artifact --------------------------------------------------------
|
||||||
|
|
||||||
override val artifactSuffix: String
|
override val artifactSuffix: String
|
||||||
@Internal get() = produce.kind.suffix(konanTarget)
|
@Internal get() = produce.suffix(konanTarget)
|
||||||
|
|
||||||
override val artifactPrefix: String
|
override val artifactPrefix: String
|
||||||
@Internal get() = produce.kind.prefix(konanTarget)
|
@Internal get() = produce.prefix(konanTarget)
|
||||||
|
|
||||||
// Multiplatform support --------------------------------------------------
|
// Multiplatform support --------------------------------------------------
|
||||||
|
|
||||||
@@ -119,7 +113,7 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
|
|||||||
addArgs("-library", libraries.artifacts.map { it.artifact.canonicalPath })
|
addArgs("-library", libraries.artifacts.map { it.artifact.canonicalPath })
|
||||||
|
|
||||||
addFileArgs("-nativelibrary", nativeLibraries)
|
addFileArgs("-nativelibrary", nativeLibraries)
|
||||||
addArg("-produce", produce.cliOption)
|
addArg("-produce", produce.name.toLowerCase())
|
||||||
|
|
||||||
addListArg("-linkerOpts", linkerOpts)
|
addListArg("-linkerOpts", linkerOpts)
|
||||||
|
|
||||||
@@ -222,41 +216,51 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region IDE model
|
// region IDE model
|
||||||
override fun toModelArtifact(): KonanModelArtifact = KonanModelArtifactImpl(
|
override fun toModelArtifact(): KonanModelArtifact {
|
||||||
artifactName,
|
val repos = libraries.repos
|
||||||
artifact,
|
val resolver = defaultResolver(
|
||||||
produce,
|
repos.map { it.absolutePath },
|
||||||
konanTarget,
|
konanTarget,
|
||||||
name,
|
Distribution(konanHomeOverride = project.konanHome)
|
||||||
allSources.filter { it is ConfigurableFileTree }.map { (it as ConfigurableFileTree).dir },
|
)
|
||||||
allSourceFiles,
|
|
||||||
libraries.asFiles()
|
return KonanModelArtifactImpl(
|
||||||
)
|
artifactName,
|
||||||
|
artifact,
|
||||||
|
produce,
|
||||||
|
konanTarget.name,
|
||||||
|
name,
|
||||||
|
allSources.filterIsInstance(ConfigurableFileTree::class.java).map { it.dir },
|
||||||
|
allSourceFiles,
|
||||||
|
libraries.asFiles(resolver),
|
||||||
|
repos.toList()
|
||||||
|
)
|
||||||
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
open class KonanCompileProgramTask: KonanCompileTask() {
|
open class KonanCompileProgramTask: KonanCompileTask() {
|
||||||
override val produce: Produce get() = Produce.PROGRAM
|
override val produce: CompilerOutputKind get() = CompilerOutputKind.PROGRAM
|
||||||
}
|
}
|
||||||
|
|
||||||
open class KonanCompileDynamicTask: KonanCompileTask() {
|
open class KonanCompileDynamicTask: KonanCompileTask() {
|
||||||
override val produce: Produce get() = Produce.DYNAMIC
|
override val produce: CompilerOutputKind get() = CompilerOutputKind.DYNAMIC
|
||||||
|
|
||||||
val headerFile: File
|
val headerFile: File
|
||||||
@OutputFile get() = destinationDir.resolve("$artifactPrefix${artifactName}_api.h")
|
@OutputFile get() = destinationDir.resolve("$artifactPrefix${artifactName}_api.h")
|
||||||
}
|
}
|
||||||
|
|
||||||
open class KonanCompileFrameworkTask: KonanCompileTask() {
|
open class KonanCompileFrameworkTask: KonanCompileTask() {
|
||||||
override val produce: Produce get() = Produce.FRAMEWORK
|
override val produce: CompilerOutputKind get() = CompilerOutputKind.FRAMEWORK
|
||||||
|
|
||||||
override val artifact
|
override val artifact
|
||||||
@OutputDirectory get() = super.artifact
|
@OutputDirectory get() = super.artifact
|
||||||
}
|
}
|
||||||
|
|
||||||
open class KonanCompileLibraryTask: KonanCompileTask() {
|
open class KonanCompileLibraryTask: KonanCompileTask() {
|
||||||
override val produce: Produce get() = Produce.LIBRARY
|
override val produce: CompilerOutputKind get() = CompilerOutputKind.LIBRARY
|
||||||
}
|
}
|
||||||
|
|
||||||
open class KonanCompileBitcodeTask: KonanCompileTask() {
|
open class KonanCompileBitcodeTask: KonanCompileTask() {
|
||||||
override val produce: Produce get() = Produce.BITCODE
|
override val produce: CompilerOutputKind get() = CompilerOutputKind.BITCODE
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-10
@@ -25,6 +25,9 @@ import org.jetbrains.kotlin.gradle.plugin.*
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.KonanInteropSpec.IncludeDirectoriesSpec
|
import org.jetbrains.kotlin.gradle.plugin.KonanInteropSpec.IncludeDirectoriesSpec
|
||||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
|
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
|
||||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifactImpl
|
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifactImpl
|
||||||
|
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||||
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
|
import org.jetbrains.kotlin.konan.target.Distribution
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -155,16 +158,26 @@ open class KonanInteropTask: KonanBuildingTask(), KonanInteropSpec {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region IDE model
|
// region IDE model
|
||||||
override fun toModelArtifact(): KonanModelArtifact = KonanModelArtifactImpl(
|
override fun toModelArtifact(): KonanModelArtifact {
|
||||||
artifactName,
|
val repos = libraries.repos
|
||||||
artifact,
|
val resolver = defaultResolver(
|
||||||
Produce.LIBRARY,
|
repos.map { it.absolutePath },
|
||||||
konanTarget,
|
konanTarget,
|
||||||
name,
|
Distribution(konanHomeOverride = project.konanHome)
|
||||||
listOfNotNull(defFile.parentFile),
|
)
|
||||||
listOf(defFile),
|
|
||||||
libraries.asFiles()
|
return KonanModelArtifactImpl(
|
||||||
)
|
artifactName,
|
||||||
|
artifact,
|
||||||
|
CompilerOutputKind.LIBRARY,
|
||||||
|
konanTarget.name,
|
||||||
|
name,
|
||||||
|
listOfNotNull(defFile.parentFile),
|
||||||
|
listOf(defFile),
|
||||||
|
libraries.asFiles(resolver),
|
||||||
|
repos.toList()
|
||||||
|
)
|
||||||
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin.test
|
||||||
|
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.rules.TemporaryFolder
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
open class CompatibilityTests {
|
||||||
|
val tmpFolder = TemporaryFolder()
|
||||||
|
@Rule get
|
||||||
|
|
||||||
|
val projectDirectory: File
|
||||||
|
get() = tmpFolder.root
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Plugin should fail if running with Gradle prior to the required one`() {
|
||||||
|
val project = KonanProject.createEmpty(projectDirectory)
|
||||||
|
val result = project
|
||||||
|
.createRunner()
|
||||||
|
.withGradleVersion("4.5")
|
||||||
|
.withArguments("tasks")
|
||||||
|
.buildAndFail()
|
||||||
|
println(result.output)
|
||||||
|
assertTrue("Build doesn't show the warning message") {
|
||||||
|
result.output.contains("Kotlin/Native Gradle plugin is incompatible with this version of Gradle.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
-1
@@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.plugin.test
|
package org.jetbrains.kotlin.gradle.plugin.test
|
||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.test.KonanProject.escapeBackSlashes
|
import org.jetbrains.kotlin.gradle.plugin.test.KonanProject.escapeBackSlashes
|
||||||
@@ -11,7 +27,7 @@ import java.io.File
|
|||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
@RunWith(Spockito::class)
|
@RunWith(Spockito::class)
|
||||||
open class PropertiesAsEnvVariables {
|
open class PropertiesAsEnvVariablesTest {
|
||||||
|
|
||||||
val tmpFolder = TemporaryFolder()
|
val tmpFolder = TemporaryFolder()
|
||||||
@Rule get
|
@Rule get
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin.test
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.rules.TemporaryFolder
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.Paths
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
open class ToolingModelTests {
|
||||||
|
val tmpFolder = TemporaryFolder()
|
||||||
|
@Rule get
|
||||||
|
|
||||||
|
val projectDirectory: File
|
||||||
|
get() = tmpFolder.root
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `The model should be serialized without exceptions`() {
|
||||||
|
val project = KonanProject.createEmpty(projectDirectory).apply {
|
||||||
|
buildFile.appendText("""
|
||||||
|
konanArtifacts {
|
||||||
|
library('foo') {
|
||||||
|
srcDir 'src/foo/kotlin'
|
||||||
|
}
|
||||||
|
interop('bar')
|
||||||
|
|
||||||
|
program('main') {
|
||||||
|
libraries {
|
||||||
|
artifact konanArtifacts.foo
|
||||||
|
artifact konanArtifacts.bar
|
||||||
|
klib 'posix'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.model.*
|
||||||
|
|
||||||
|
task testSerialization {
|
||||||
|
doLast {
|
||||||
|
def model = KonanToolingModelBuilder.INSTANCE.buildAll("KonanModel", project)
|
||||||
|
file("model.bin").withObjectOutputStream {
|
||||||
|
it.writeObject(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
KonanModelImpl deserializedModel
|
||||||
|
file("model.bin").withObjectInputStream(model.getClass().getClassLoader()) { stream ->
|
||||||
|
deserializedModel = (KonanModelImpl) stream.readObject()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deserializedModel.equals(model)) {
|
||||||
|
throw new AssertionError("The deserialized model doesn't equal to the initial one")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent())
|
||||||
|
|
||||||
|
generateSrcFile("main.kt")
|
||||||
|
generateSrcFile(Paths.get("src", "foo", "kotlin"), "foo.kt", "fun foo() = 1")
|
||||||
|
generateSrcFile(Paths.get("src", "bar", "kotlin"), "bar.kt", "fun bar() = 1")
|
||||||
|
generateDefFile("baz.def", "")
|
||||||
|
generateDefFile("qux.def", "")
|
||||||
|
}
|
||||||
|
project.createRunner().withArguments("testSerialization").build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `The model should contain the same data as the Gradle tasks`() {
|
||||||
|
val project = KonanProject.createEmpty(projectDirectory, listOf("host", "wasm32")).apply {
|
||||||
|
val konanVersion = KonanVersion.CURRENT.toString()
|
||||||
|
generateSrcFile(listOf("src", "foo1"), "foo1.kt", "fun foo1() = 0")
|
||||||
|
generateSrcFile(listOf("src", "foo1"), "foo11.kt", "fun foo11() = 0")
|
||||||
|
generateSrcFile(listOf("src", "foo2"), "foo2.kt", "fun foo2() = 0")
|
||||||
|
generateSrcFile(listOf("defs_bar"), "bar.def", "")
|
||||||
|
generateSrcFile(listOf("src", "baz"), "baz.kt", "fun baz() = 0")
|
||||||
|
generateSrcFile("main.kt")
|
||||||
|
createSubDir("custom_repo")
|
||||||
|
buildFile.appendText("""
|
||||||
|
konanArtifacts {
|
||||||
|
library('foo') {
|
||||||
|
srcDir 'src/foo1'
|
||||||
|
srcDir 'src/foo2'
|
||||||
|
}
|
||||||
|
interop('bar') {
|
||||||
|
defFile 'defs_bar/bar.def'
|
||||||
|
}
|
||||||
|
library('baz') {
|
||||||
|
srcDir 'src/baz'
|
||||||
|
}
|
||||||
|
|
||||||
|
program('main') {
|
||||||
|
libraries {
|
||||||
|
artifact konanArtifacts.foo
|
||||||
|
artifact konanArtifacts.bar
|
||||||
|
klib 'baz'
|
||||||
|
|
||||||
|
useRepo 'custom_repo'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
konan {
|
||||||
|
languageVersion = "1.2"
|
||||||
|
apiVersion = "1.2"
|
||||||
|
}
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.model.*
|
||||||
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
|
|
||||||
|
public <T> void assertEquals(
|
||||||
|
T actual,
|
||||||
|
T expected,
|
||||||
|
String message = "${'$'}expected expected but ${'$'}actual found") {
|
||||||
|
if (expected != actual) {
|
||||||
|
throw new AssertionError(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> void assertContentEquals(
|
||||||
|
Collection<T> actual,
|
||||||
|
Collection<T> expected,
|
||||||
|
String message = "${'$'}expected\nexpected but\n${'$'}actual\nfound") {
|
||||||
|
if (actual.size() != expected.size() || !actual.containsAll(expected)) {
|
||||||
|
throw new AssertionError(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task testModelData {
|
||||||
|
dependsOn('compileKonanBaz')
|
||||||
|
doLast {
|
||||||
|
def model = KonanToolingModelBuilder.INSTANCE.buildAll("KonanModel", project)
|
||||||
|
assertEquals(model.konanHome, file(project.getProperty('konan.home')))
|
||||||
|
assertEquals(model.konanVersion.toString(), "$konanVersion")
|
||||||
|
|
||||||
|
assertEquals(model.languageVersion, "1.2")
|
||||||
|
assertEquals(model.apiVersion, "1.2")
|
||||||
|
|
||||||
|
model.artifacts.each {
|
||||||
|
|
||||||
|
def konanArtifact = konanArtifacts[it.name]
|
||||||
|
def target = it.targetPlatform
|
||||||
|
def task = konanArtifact.getByTarget(target)
|
||||||
|
|
||||||
|
assertEquals(it.file, task.artifact)
|
||||||
|
assertEquals(it.buildTaskName, task.name)
|
||||||
|
|
||||||
|
switch(it.name) {
|
||||||
|
case 'foo':
|
||||||
|
assertEquals(it.type, CompilerOutputKind.valueOf('LIBRARY'))
|
||||||
|
assertContentEquals(it.srcDirs, [file('src/foo1'), file('src/foo2')])
|
||||||
|
assertContentEquals(it.srcFiles, [
|
||||||
|
file('src/foo1/foo1.kt'),
|
||||||
|
file('src/foo1/foo11.kt'),
|
||||||
|
file('src/foo2/foo2.kt')])
|
||||||
|
assertContentEquals(it.libraries, [])
|
||||||
|
assertContentEquals(it.searchPaths, [task.artifact.parentFile])
|
||||||
|
break
|
||||||
|
case 'bar':
|
||||||
|
assertEquals(it.type, CompilerOutputKind.valueOf('LIBRARY'))
|
||||||
|
assertContentEquals(it.srcDirs, [file('defs_bar')])
|
||||||
|
assertContentEquals(it.srcFiles, [file('defs_bar/bar.def')])
|
||||||
|
assertContentEquals(it.libraries, [])
|
||||||
|
assertContentEquals(it.searchPaths, [task.artifact.parentFile])
|
||||||
|
break
|
||||||
|
case 'main':
|
||||||
|
assertEquals(it.type, CompilerOutputKind.valueOf('PROGRAM'))
|
||||||
|
assertContentEquals(it.srcDirs, [file('src/main/kotlin')])
|
||||||
|
assertContentEquals(it.srcFiles, [file('src/main/kotlin/main.kt')])
|
||||||
|
assertContentEquals(it.libraries, [
|
||||||
|
konanArtifacts['foo'].getByTarget(target).artifact,
|
||||||
|
konanArtifacts['bar'].getByTarget(target).artifact,
|
||||||
|
konanArtifacts['baz'].getByTarget(target).artifact
|
||||||
|
])
|
||||||
|
assertContentEquals(it.searchPaths, [
|
||||||
|
file('custom_repo'),
|
||||||
|
task.artifact.parentFile,
|
||||||
|
konanArtifacts.foo.getByTarget(target).artifact.parentFile
|
||||||
|
])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
|
project.createRunner().withArguments("testModelData").build()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user