diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 8a7fb3f998a..edf0aa019ea 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -192,9 +192,9 @@ konanArtifacts { } } -task installTestLibrary(type: KlibInstall) { - dependsOn compileKonanTestLibraryHost - klib = konanArtifacts.testLibrary.getArtifactByTarget('host') +def installTestLib = tasks.register("installTestLibrary", KlibInstall) { + dependsOn "compileKonanTestLibraryHost" + klib = project.provider { konanArtifacts.testLibrary.getArtifactByTarget('host') } repo = rootProject.file(testLibraryDir) doLast { @@ -2165,7 +2165,7 @@ standaloneTest("link_testLib_explicitly") { // there are no testLibrary for cross targets yet. enabled = project.target.name == project.hostName - dependsOn 'installTestLibrary' + dependsOn installTestLib goldValue = "This is a side effect of a test library linked into the binary.\nYou should not be seeing this.\n\nHello\n" source = "link/omit/hello.kt" // We force library inclusion, so need to see the warning banner. @@ -3535,12 +3535,12 @@ standaloneTest("testing_stacktrace") { } // Just check that the driver is able to produce runnable binaries. -task driver0(type: KonanDriverTest) { +tasks.register("driver0", KonanDriverTest) { goldValue = "Hello, world!\n" source = "runtime/basic/driver0.kt" } -task driver_opt(type: KonanDriverTest) { +tasks.register("driver_opt", KonanDriverTest) { disabled = (cacheTesting != null) // Cache is not compatible with -opt. goldValue = "Hello, world!\n" source = "runtime/basic/driver0.kt" @@ -3728,14 +3728,16 @@ createInterop("embedStaticLibraries") { // Note: also hardcoded in def file. final String libDir = "$buildDir/embedStaticLibraries/" - it.getByTarget(target.name).doFirst { - 1.upto(4) { - UtilsKt.buildStaticLibrary( - project, - [file("$projectDir/interop/embedStaticLibraries/${it}.c")], - file("$libDir/${it}.a"), - file("$libDir/${it}.objs"), - ) + it.getByTarget(target.name).configure { + doFirst { + 1.upto(4) { + UtilsKt.buildStaticLibrary( + project, + [file("$projectDir/interop/embedStaticLibraries/${it}.c")], + file("$libDir/${it}.a"), + file("$libDir/${it}.objs"), + ) + } } } @@ -4437,7 +4439,7 @@ dynamicTest("interop_memory_leaks") { outputChecker = { s -> s.contains("Memory leaks detected, 1 objects leaked!") } } -task library_mismatch(type: KonanDriverTest) { +tasks.register("library_mismatch", KonanDriverTest) { // Does not work for cross targets yet. enabled = !(project.testTarget != null && project.target.name != project.hostName) @@ -4475,7 +4477,7 @@ task library_mismatch(type: KonanDriverTest) { } } -task library_ir_provider_mismatch(type: KonanDriverTest) { +tasks.register("library_ir_provider_mismatch", KonanDriverTest) { def dir = buildDir.absolutePath def lib = "$projectDir/link/ir_providers/library/empty.kt" def invalidManifest = "$projectDir/link/ir_providers/library/manifest.properties" @@ -4861,12 +4863,14 @@ if (UtilsKt.getTestTargetSupportsCodeCoverage(project)) { } } -task metadata_compare_typedefs(type: MetadataComparisonTest) { +tasks.register("metadata_compare_typedefs", MetadataComparisonTest) { + UtilsKt.dependsOnDist(it) enabled = (project.testTarget != 'wasm32') defFile = "interop/basics/typedefs.def" } -task metadata_compare_unable_to_import(type: MetadataComparisonTest) { +tasks.register("metadata_compare_unable_to_import", MetadataComparisonTest) { + UtilsKt.dependsOnDist(it) enabled = (project.testTarget != 'wasm32') defFile = "interop/basics/unable_to_import.def" } @@ -4883,8 +4887,7 @@ standaloneTest("local_ea_arraysfieldwrite") { source = "codegen/localEscapeAnalysis/arraysFieldWrite.kt" } -task override_konan_properties0(type: KonanDriverTest) { - +tasks.register("override_konan_properties0", KonanDriverTest) { def overrides = PlatformInfo.isWindows() ? '-Xoverride-konan-properties="llvmInlineThreshold=76"' : '-Xoverride-konan-properties=llvmInlineThreshold=76' @@ -4989,7 +4992,7 @@ task buildKonanTests { t -> project.tasks .withType(KonanLocalTest.class) .matching { !(it instanceof KonanStandaloneTest) } - .forEach { it.dependsOn(t) } + .configureEach { it.dependsOn(t) } } @@ -5007,7 +5010,7 @@ sourceSets { } Task pluginTest(String name, String pluginName, Closure configureClosure) { - def jarTask = project.tasks.create("jar-$pluginName", Jar).configure { + def jarTask = project.tasks.register("jar-$pluginName", Jar) { it.dependsOn("compile${pluginName.capitalize()}Kotlin") from { sourceSets[pluginName].output @@ -5062,7 +5065,7 @@ project.tasks.register("debugger_test", Test.class) { if (target.family == Family.IOS && (target.architecture == ARM32 || target.architecture == ARM64)) { project.tasks .withType(KonanTestExecutable.class) - .forEach { + .configureEach { ExecutorServiceKt.configureXcodeBuild((KonanTestExecutable) it) } // Exclude tasks that cannot be run on device @@ -5074,5 +5077,5 @@ if (target.family == Family.IOS && (target.architecture == ARM32 || target.archi it instanceof KonanDynamicTest || it instanceof KonanLinkTest } - .forEach { it.enabled = false } + .configureEach { it.enabled = false } } diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt index faea66b2134..ab1092f0d6b 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlin import groovy.lang.Closure import org.gradle.api.Task +import org.gradle.api.provider.Provider import org.gradle.api.tasks.Exec import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile @@ -12,17 +13,17 @@ import java.io.File // TODO: Implement as a part of the gradle plugin open class KlibInstall: Exec() { - @InputFile - lateinit var klib: File + @Input + lateinit var klib: Provider @Input var repo: File = project.rootDir - val installDir: File + val installDir: Provider @OutputDirectory - get() { - val klibName = klib.name.take(klib.name.lastIndexOf('.')) - return project.file("${repo.absolutePath}/$klibName") + get() = project.provider { + val klibName = klib.get().nameWithoutExtension + project.file("${repo.absolutePath}/$klibName") } @Input @@ -38,7 +39,7 @@ open class KlibInstall: Exec() { repo.mkdirs() commandLine(klibProgram, - "install", klib.absolutePath, + "install", klib.get().absolutePath, "-target", target, "-repository", repo.absolutePath ) diff --git a/kotlin-native/platformLibs/build.gradle b/kotlin-native/platformLibs/build.gradle index 387df4de4e1..4f27fa92f1a 100644 --- a/kotlin-native/platformLibs/build.gradle +++ b/kotlin-native/platformLibs/build.gradle @@ -58,16 +58,16 @@ project.rootProject.ext.platformManager.enabled.each { target -> def targetName = target.visibleName - ArrayList installTasks = [] - ArrayList cacheTasks = [] + ArrayList installTasks = [] + ArrayList cacheTasks = [] if (target in cacheableTargets) { - task "${targetName}StdlibCache"(type: KonanCacheTask) { + tasks.register("${targetName}StdlibCache", KonanCacheTask) { it.target = targetName - originalKlib = file("$konanHome/klib/common/stdlib") - cacheRoot = file("$konanHome/klib/cache") + it.originalKlib = file("$konanHome/klib/common/stdlib") + it.cacheRoot = file("$konanHome/klib/cache") - dependsOn ":${targetName}CrossDistRuntime" + it.dependsOn ":${targetName}CrossDistRuntime" } } @@ -76,7 +76,7 @@ project.rootProject.ext.platformManager.enabled.each { target -> def fileNamePrefix = PlatformLibsInfo.namePrefix konanArtifacts { - interop (libName, targets: [targetName]) { + interop(libName, targets: [targetName]) { defFile df.file artifactName "${fileNamePrefix}${df.name}" noDefaultLibs true @@ -92,60 +92,60 @@ project.rootProject.ext.platformManager.enabled.each { target -> } def libTask = konanArtifacts."$libName"."$targetName" - libTask.dependsOn df.config.depends.collect{ defFileToLibName(targetName, it) } - libTask.dependsOn ":${targetName}CrossDist" - libTask.enableParallel = true - - task "$libName"(type: KlibInstall) { - klib = libTask.artifact - repo = file("$konanHome/klib/platform/$targetName") - it.target = targetName - dependsOn libTask - + libTask.configure { + it.dependsOn df.config.depends.collect { defFileToLibName(targetName, it) } + it.dependsOn ":${targetName}CrossDist" + it.enableParallel = true } - installTasks.add(tasks[libName]) + + def klibInstallTask = tasks.register("$libName", KlibInstall) { + it.klib = project.provider { libTask.get().artifact } + it.repo = file("$konanHome/klib/platform/$targetName") + it.target = targetName + it.dependsOn libTask + } + installTasks.add(klibInstallTask) if (target in cacheableTargets) { - task "${libName}Cache"(type: KonanCacheTask) { + def cacheTask = tasks.register("${libName}Cache", KonanCacheTask) { it.target = targetName - originalKlib = tasks[libName].installDir - cacheRoot = file("$konanHome/klib/cache") + it.originalKlib = tasks[libName].installDir.get() + it.cacheRoot = file("$konanHome/klib/cache") - dependsOn ":${targetName}StdlibCache" - dependsOn tasks[libName] - dependsOn df.config.depends.collect { + it.dependsOn ":${targetName}StdlibCache" + it.dependsOn tasks[libName] + it.dependsOn df.config.depends.collect { def depName = defFileToLibName(targetName, it) "${depName}Cache" } - - cacheTasks.add(it) } + cacheTasks.add(cacheTask) } } - task "${targetName}Install" { - dependsOn installTasks + tasks.register("${targetName}Install") { + it.dependsOn installTasks } if (target in cacheableTargets) { - task "${targetName}Cache" { - dependsOn cacheTasks + tasks.register("${targetName}Cache") { + it.dependsOn cacheTasks - group = BasePlugin.BUILD_GROUP - description = "Builds the compilation cache for platform: ${targetName}" + it.group = BasePlugin.BUILD_GROUP + it.description = "Builds the compilation cache for platform: ${targetName}" } } } // TODO: Don't install libraries here - copy them in the distPlatformLibs task task hostInstall { - dependsOn tasks.withType(KlibInstall.class).findAll { + dependsOn tasks.withType(KlibInstall.class).matching { it.target == HostManager.hostName } } task hostCache { - dependsOn tasks.withType(KonanCacheTask.class).findAll { + dependsOn tasks.withType(KonanCacheTask.class).matching { it.target == HostManager.hostName } } diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanBuildingConfig.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanBuildingConfig.kt index a015407eceb..9159e317c56 100644 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanBuildingConfig.kt +++ b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanBuildingConfig.kt @@ -17,30 +17,36 @@ package org.jetbrains.kotlin.gradle.plugin.konan import groovy.lang.Closure -import org.gradle.api.* +import org.gradle.api.Action +import org.gradle.api.InvalidUserDataException +import org.gradle.api.Named +import org.gradle.api.Task import org.gradle.api.internal.project.ProjectInternal import org.gradle.api.plugins.BasePlugin import org.gradle.api.plugins.ExtensionAware import org.gradle.api.publish.maven.MavenPom +import org.gradle.api.tasks.TaskProvider import org.gradle.util.ConfigureUtil -import org.gradle.util.WrapUtil import org.jetbrains.kotlin.gradle.plugin.tasks.KonanBuildingTask import org.jetbrains.kotlin.konan.target.KonanTarget import java.io.File /** Base class for all Kotlin/Native artifacts. */ -abstract class KonanBuildingConfig(private val name_: String, - val type: Class, - val project: ProjectInternal, - val targets: Iterable) - : KonanBuildingSpec, Named, DomainObjectSet by WrapUtil.toDomainObjectSet(type) { +abstract class KonanBuildingConfig( + private val name_: String, + val type: Class, + val project: ProjectInternal, + val targets: Iterable +) : KonanBuildingSpec, Named { internal val mainVariant = KonanSoftwareComponent(project) override fun getName() = name_ - protected val targetToTask = mutableMapOf() + protected val targetToTask = mutableMapOf>() - internal val aggregateBuildTask: Task + fun tasks() = targetToTask.values + + private val aggregateBuildTask: TaskProvider internal var pomActions = mutableListOf>() @@ -56,12 +62,11 @@ abstract class KonanBuildingConfig(private val name_: Stri continue } if (!targetIsSupported(konanTarget)) { - project.logger.info("The target ${targetName} is not supported by the artifact $name") + project.logger.info("The target $targetName is not supported by the artifact $name") continue } if (this[konanTarget] == null) { val task = createTask(konanTarget) - add(task) targetToTask[konanTarget] = task // Allow accessing targets just by their names in Groovy DSL. (this as? ExtensionAware)?.extensions?.add(konanTarget.visibleName, task) @@ -75,13 +80,13 @@ abstract class KonanBuildingConfig(private val name_: Stri } protected open fun generateTaskName(target: KonanTarget) = - "compileKonan${name.capitalize()}${target.visibleName.capitalize()}" + "compileKonan${name.capitalize()}${target.visibleName.capitalize()}" protected open fun generateAggregateTaskName() = - "compileKonan${name.capitalize()}" + "compileKonan${name.capitalize()}" protected open fun generateTargetAliasTaskName(targetName: String) = - "compileKonan${name.capitalize()}${targetName.capitalize()}" + "compileKonan${name.capitalize()}${targetName.capitalize()}" protected abstract fun generateTaskDescription(task: T): String protected abstract fun generateAggregateTaskDescription(task: Task): String @@ -109,31 +114,33 @@ abstract class KonanBuildingConfig(private val name_: Stri } } - protected fun createTask(target: KonanTarget): T = - project.tasks.create(generateTaskName(target), type) { - val outputDescription = determineOutputPlacement(target) - it.init(this, outputDescription.destinationDir, outputDescription.artifactName, target) - it.group = BasePlugin.BUILD_GROUP - it.description = generateTaskDescription(it) - } ?: throw Exception("Cannot create task for target: ${target.visibleName}") + private fun createTask(target: KonanTarget): TaskProvider = + project.tasks.register(generateTaskName(target), type) { + val outputDescription = determineOutputPlacement(target) + it.init(this, outputDescription.destinationDir, outputDescription.artifactName, target) + it.group = BasePlugin.BUILD_GROUP + it.description = generateTaskDescription(it) + } ?: throw Exception("Cannot create task for target: ${target.visibleName}") - protected fun createAggregateTask(): Task = - project.tasks.create(generateAggregateTaskName()) { task -> - task.group = BasePlugin.BUILD_GROUP - task.description = generateAggregateTaskDescription(task) - this.filter { - project.targetIsRequested(it.konanTarget) - }.forEach { - task.dependsOn(it) - } - project.compileAllTask.dependsOn(task) + private fun createAggregateTask(): TaskProvider = + project.tasks.register(generateAggregateTaskName()) { task -> + task.group = BasePlugin.BUILD_GROUP + task.description = generateAggregateTaskDescription(task) + + targetToTask.filter { + project.targetIsRequested(it.key) + }.forEach { + task.dependsOn(it.value) } + }.also { + project.compileAllTask.dependsOn(it) + } - protected fun createTargetAliasTaskIfDeclared(targetName: String): Task? { + protected fun createTargetAliasTaskIfDeclared(targetName: String): TaskProvider? { val canonicalTarget = project.hostManager.targetByName(targetName) return this[canonicalTarget]?.let { canonicalBuild -> - project.tasks.create(generateTargetAliasTaskName(targetName)) { + project.tasks.register(generateTargetAliasTaskName(targetName)) { it.group = BasePlugin.BUILD_GROUP it.description = generateTargetAliasTaskDescription(it, targetName) it.dependsOn(canonicalBuild) @@ -143,31 +150,53 @@ abstract class KonanBuildingConfig(private val name_: Stri internal operator fun get(target: KonanTarget) = targetToTask[target] - fun getByTarget(target: String) = findByTarget(target) ?: throw NoSuchElementException("No such target for artifact $name: ${target}") + fun getByTarget(target: String) = + findByTarget(target) ?: throw NoSuchElementException("No such target for artifact $name: $target") + fun findByTarget(target: String) = this[project.hostManager.targetByName(target)] - fun getArtifactByTarget(target: String) = getByTarget(target).artifact - fun findArtifactByTarget(target: String) = findByTarget(target)?.artifact + fun getArtifactByTarget(target: String) = getByTarget(target).get().artifact + fun findArtifactByTarget(target: String) = findByTarget(target)?.get()?.artifact // Common building DSL. - override fun artifactName(name: String) = forEach { it.artifactName(name) } + override fun artifactName(name: String) = tasks().forEach { it.configure { t -> t.artifactName(name) } } - fun baseDir(dir: Any) = forEach { it.destinationDir(project.file(dir).targetSubdir(it.konanTarget)) } + fun baseDir(dir: Any) = + tasks().forEach { + it.configure { t -> + t.destinationDir( + project.file(dir).targetSubdir(t.konanTarget) + ) + } + } - override fun libraries(closure: Closure) = forEach { it.libraries(closure) } - override fun libraries(action: Action) = forEach { it.libraries(action) } - override fun libraries(configure: KonanLibrariesSpec.() -> Unit) = forEach { it.libraries(configure) } + override fun libraries(closure: Closure) = + tasks().forEach { it.configure { t -> t.libraries(closure) } } - override fun noDefaultLibs(flag: Boolean) = forEach { it.noDefaultLibs(flag) } - override fun noEndorsedLibs(flag: Boolean) = forEach { it.noEndorsedLibs(flag) } + override fun libraries(action: Action) = + tasks().forEach { it.configure { t -> t.libraries(action) } } - override fun dumpParameters(flag: Boolean) = forEach { it.dumpParameters(flag) } + override fun libraries(configure: KonanLibrariesSpec.() -> Unit) = + tasks().forEach { it.configure { t -> t.libraries(configure) } } - override fun extraOpts(vararg values: Any) = forEach { it.extraOpts(*values) } - override fun extraOpts(values: List) = forEach { it.extraOpts(values) } + override fun noDefaultLibs(flag: Boolean) = + tasks().forEach { it.configure { t -> t.noDefaultLibs(flag) } } - fun dependsOn(vararg dependencies: Any?) = forEach { it.dependsOn(*dependencies) } + override fun noEndorsedLibs(flag: Boolean) = + tasks().forEach { it.configure { t -> t.noEndorsedLibs(flag) } } + + override fun dumpParameters(flag: Boolean) = + tasks().forEach { it.configure { t -> t.dumpParameters(flag) } } + + override fun extraOpts(vararg values: Any) = + tasks().forEach { it.configure { t -> t.extraOpts(*values) } } + + override fun extraOpts(values: List) = + tasks().forEach { it.configure { t -> t.extraOpts(values) } } + + fun dependsOn(vararg dependencies: Any?) = + tasks().forEach { it.configure { t -> t.dependsOn(*dependencies) } } fun target(targetString: String, configureAction: T.() -> Unit) { val target = project.hostManager.targetByName(targetString) @@ -177,14 +206,16 @@ abstract class KonanBuildingConfig(private val name_: Stri return } - val task = this[target] ?: - throw InvalidUserDataException("Target '$targetString' is not declared. Please add it into project.konanTasks list") - task.configureAction() + val task = this[target] + ?: throw InvalidUserDataException("Target '$targetString' is not declared. Please add it into project.konanTasks list") + task.configure(configureAction) } + fun target(targetString: String, configureAction: Action) = - target(targetString) { configureAction.execute(this) } + target(targetString) { configureAction.execute(this) } + fun target(targetString: String, configureAction: Closure) = - target(targetString, ConfigureUtil.configureUsing(configureAction)) + target(targetString, ConfigureUtil.configureUsing(configureAction)) fun pom(action: Action) = pomActions + action } diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanCompileConfig.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanCompileConfig.kt index 925f555dd85..1de7d799950 100644 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanCompileConfig.kt +++ b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanCompileConfig.kt @@ -43,33 +43,33 @@ abstract class KonanCompileConfig(name: String, override fun generateTargetAliasTaskDescription(task: Task, targetName: String) = "Build the Kotlin/Native $typeForDescription '${task.name}' for target '$targetName'" - override fun srcDir(dir: Any) = forEach { it.srcDir(dir) } - override fun srcFiles(vararg files: Any) = forEach { it.srcFiles(*files) } - override fun srcFiles(files: Collection) = forEach { it.srcFiles(files) } + override fun srcDir(dir: Any) = tasks().forEach { it.configure { t -> t.srcDir(dir) } } + override fun srcFiles(vararg files: Any) = tasks().forEach { it.configure { t -> t.srcFiles(*files) } } + override fun srcFiles(files: Collection) = tasks().forEach { it.configure { t -> t.srcFiles(files) } } - override fun nativeLibrary(lib: Any) = forEach { it.nativeLibrary(lib) } - override fun nativeLibraries(vararg libs: Any) = forEach { it.nativeLibraries(*libs) } - override fun nativeLibraries(libs: FileCollection) = forEach { it.nativeLibraries(libs) } + override fun nativeLibrary(lib: Any) = tasks().forEach { it.configure { t -> t.nativeLibrary(lib) } } + override fun nativeLibraries(vararg libs: Any) = tasks().forEach { it.configure { t -> t.nativeLibraries(*libs) } } + override fun nativeLibraries(libs: FileCollection) = tasks().forEach { it.configure { t -> t.nativeLibraries(libs) } } @Deprecated("Use commonSourceSets instead", ReplaceWith("commonSourceSets(sourceSetName)")) - override fun commonSourceSet(sourceSetName: String) = forEach { it.commonSourceSets(sourceSetName) } - override fun commonSourceSets(vararg sourceSetNames: String) = forEach { it.commonSourceSets(*sourceSetNames) } - override fun enableMultiplatform(flag: Boolean) = forEach { it.enableMultiplatform(flag) } + override fun commonSourceSet(sourceSetName: String) = tasks().forEach { it.configure { t -> t.commonSourceSets(sourceSetName) } } + override fun commonSourceSets(vararg sourceSetNames: String) = tasks().forEach { it.configure { t -> t.commonSourceSets(*sourceSetNames) } } + override fun enableMultiplatform(flag: Boolean) = tasks().forEach { it.configure { t -> t.enableMultiplatform(flag) } } - override fun linkerOpts(values: List) = forEach { it.linkerOpts(values) } - override fun linkerOpts(vararg values: String) = forEach { it.linkerOpts(*values) } + override fun linkerOpts(values: List) = tasks().forEach { it.configure { t -> t.linkerOpts(values) } } + override fun linkerOpts(vararg values: String) = tasks().forEach { it.configure { t -> t.linkerOpts(*values) } } - override fun enableDebug(flag: Boolean) = forEach { it.enableDebug(flag) } - override fun noStdLib(flag: Boolean) = forEach { it.noStdLib(flag) } - override fun noMain(flag: Boolean) = forEach { it.noMain(flag) } - override fun enableOptimizations(flag: Boolean) = forEach { it.enableOptimizations(flag) } - override fun enableAssertions(flag: Boolean) = forEach { it.enableAssertions(flag) } + override fun enableDebug(flag: Boolean) = tasks().forEach { it.configure { t -> t.enableDebug(flag) } } + override fun noStdLib(flag: Boolean) = tasks().forEach { it.configure { t -> t.noStdLib(flag) } } + override fun noMain(flag: Boolean) = tasks().forEach { it.configure { t -> t.noMain(flag) } } + override fun enableOptimizations(flag: Boolean) = tasks().forEach { it.configure { t -> t.enableOptimizations(flag) } } + override fun enableAssertions(flag: Boolean) = tasks().forEach { it.configure { t -> t.enableAssertions(flag) } } - override fun entryPoint(entryPoint: String) = forEach { it.entryPoint(entryPoint) } + override fun entryPoint(entryPoint: String) = tasks().forEach { it.configure { t -> t.entryPoint(entryPoint) } } - override fun measureTime(flag: Boolean) = forEach { it.measureTime(flag) } + override fun measureTime(flag: Boolean) = tasks().forEach { it.configure { t -> t.measureTime(flag) } } - override fun dependencies(closure: Closure) = forEach { it.dependencies(closure) } + override fun dependencies(closure: Closure) = tasks().forEach { it.configure { t -> t.dependencies(closure) } } } open class KonanProgram(name: String, diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanInteropLibrary.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanInteropLibrary.kt index f5b87da03f1..2160efffc04 100644 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanInteropLibrary.kt +++ b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanInteropLibrary.kt @@ -49,38 +49,37 @@ open class KonanInteropLibrary(name: String, inner class IncludeDirectoriesSpecImpl: IncludeDirectoriesSpec { override fun allHeaders(vararg includeDirs: Any) = allHeaders(includeDirs.toList()) - override fun allHeaders(includeDirs: Collection) = forEach { - it.includeDirs.allHeaders(includeDirs) + override fun allHeaders(includeDirs: Collection) = tasks().forEach { + it.configure { t -> t.includeDirs.allHeaders(includeDirs) } } override fun headerFilterOnly(vararg includeDirs: Any) = headerFilterOnly(includeDirs.toList()) - override fun headerFilterOnly(includeDirs: Collection) = forEach { - it.includeDirs.headerFilterOnly(includeDirs) + override fun headerFilterOnly(includeDirs: Collection) = tasks().forEach { + it.configure { t -> t.includeDirs.headerFilterOnly(includeDirs) } } } val includeDirs = IncludeDirectoriesSpecImpl() - override fun defFile(file: Any) = forEach { it.defFile(file) } + override fun defFile(file: Any) = tasks().forEach { it.configure { t -> t.defFile(file) } } - override fun packageName(value: String) = forEach { it.packageName(value) } + override fun packageName(value: String) = tasks().forEach { it.configure { t -> t.packageName(value) } } - override fun compilerOpts(vararg values: String) = forEach { it.compilerOpts(*values) } + override fun compilerOpts(vararg values: String) = tasks().forEach { it.configure { t -> t.compilerOpts(*values) } } - override fun headers(vararg files: Any) = forEach { it.headers(*files) } + override fun headers(vararg files: Any) = tasks().forEach { it.configure { t -> t.headers(*files) } } - override fun headers(files: FileCollection) = forEach { it.headers(files) } + override fun headers(files: FileCollection) = tasks().forEach { it.configure { t -> t.headers(files) } } - override fun includeDirs(vararg values: Any) = forEach { it.includeDirs(*values) } + override fun includeDirs(vararg values: Any) = tasks().forEach { it.configure { t -> t.includeDirs(*values) } } override fun includeDirs(closure: Closure) = includeDirs(ConfigureUtil.configureUsing(closure)) override fun includeDirs(action: Action) = includeDirs { action.execute(this) } override fun includeDirs(configure: IncludeDirectoriesSpec.() -> Unit) = includeDirs.configure() - override fun linkerOpts(values: List) = forEach { it.linkerOpts(values) } + override fun linkerOpts(values: List) = tasks().forEach { it.configure { t -> t.linkerOpts(values) } } override fun linkerOpts(vararg values: String) = linkerOpts(values.toList()) - override fun link(vararg files: Any) = forEach { it.link(*files) } - override fun link(files: FileCollection) = forEach { it.link(files) } - override fun dependencies(closure: Closure) = forEach { it.dependencies(closure) } - + override fun link(vararg files: Any) = tasks().forEach { it.configure { t -> t.link(*files) } } + override fun link(files: FileCollection) = tasks().forEach { it.configure { t -> t.link(files) } } + override fun dependencies(closure: Closure) = tasks().forEach { it.configure { t -> t.dependencies(closure) }} } \ No newline at end of file diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanLibrariesSpec.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanLibrariesSpec.kt index 968a61185b3..3d9475ac536 100644 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanLibrariesSpec.kt +++ b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanLibrariesSpec.kt @@ -86,7 +86,7 @@ open class KonanLibrariesSpec( throw InvalidUserDataException("Config ${lib.name} is not a library") } - val libraryTask = lib[target] ?: + val libraryTask = lib[target]?.get() ?: throw InvalidUserDataException("Library ${lib.name} has no target ${target.visibleName}") if (libraryTask == task) { diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt index b58bbe2448f..5bc0d6f364e 100644 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt +++ b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt @@ -16,6 +16,8 @@ package org.jetbrains.kotlin.gradle.plugin.konan +import groovy.lang.Closure +import org.codehaus.groovy.runtime.GStringImpl import org.gradle.api.* import org.gradle.api.component.ComponentWithVariants import org.gradle.api.component.SoftwareComponent @@ -28,11 +30,11 @@ import org.gradle.api.plugins.BasePlugin import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal +import org.gradle.api.tasks.Exec import org.gradle.language.cpp.internal.NativeVariantIdentity import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.plugin.konan.KonanPlugin.Companion.COMPILE_ALL_TASK_NAME -import org.jetbrains.kotlin.gradle.plugin.model.KonanToolingModelBuilder import org.jetbrains.kotlin.gradle.plugin.tasks.* import org.jetbrains.kotlin.konan.CURRENT import org.jetbrains.kotlin.konan.CompilerVersion @@ -330,11 +332,9 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR return } checkGradleVersion() - registry.register(KonanToolingModelBuilder) project.plugins.apply("base") // Create necessary tasks and extensions. project.tasks.create(KONAN_DOWNLOAD_TASK_NAME, KonanCompilerDownloadTask::class.java) - project.tasks.create(KONAN_GENERATE_CMAKE_TASK_NAME, KonanGenerateCMakeTask::class.java) project.extensions.create(KONAN_EXTENSION_NAME, KonanExtension::class.java) val container = project.extensions.create( KonanArtifactContainer::class.java, @@ -363,15 +363,36 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR doLast { project.cleanKonan() } } + project.afterEvaluate { + project.tasks + .withType(KonanCompileProgramTask::class.java) + .forEach { task -> + val isCrossCompile = (task.target != HostManager.host.visibleName) + if (!isCrossCompile && !project.hasProperty("konanNoRun")) + task.runTask = project.tasks.register("run${task.artifactName.capitalize()}", Exec::class.java) { + it.group= "run" + it.dependsOn(task) + val artifactPathClosure = object : Closure(this) { + override fun call() = task.artifactPath + } + // Use GString to evaluate a path to the artifact lazily thus allow changing it at configuration phase. + val lazyArtifactPath = GStringImpl(arrayOf(artifactPathClosure), arrayOf("")) + it.executable(lazyArtifactPath) + // Add values passed in the runArgs project property as arguments. + it.argumentProviders.add(task.RunArgumentProvider()) + } + } + } + val runTask = project.getOrCreateTask("run") project.afterEvaluate { project.konanArtifactsContainer - .filterIsInstance(KonanProgram::class.java) - .forEach { program -> - program.forEach { compile -> - compile.runTask?.let { runTask.dependsOn(it) } - } + .filterIsInstance(KonanProgram::class.java) + .forEach { program -> + program.tasks().forEach { compile -> + compile.configure { it.runTask?.let { runTask.dependsOn(it) } } } + } } // Enable multiplatform support diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanBuildingTask.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanBuildingTask.kt index 50e9518649b..d03b77c0a5b 100644 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanBuildingTask.kt +++ b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanBuildingTask.kt @@ -21,7 +21,6 @@ import org.gradle.api.tasks.Input import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.jetbrains.kotlin.gradle.plugin.konan.* -import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact import org.jetbrains.kotlin.konan.target.KonanTarget import java.io.File @@ -30,7 +29,6 @@ abstract class KonanBuildingTask: KonanArtifactWithLibrariesTask(), KonanBuildin @get:Internal internal abstract val toolRunner: KonanToolRunner - internal abstract fun toModelArtifact(): KonanModelArtifact override fun init(config: KonanBuildingConfig<*>, destinationDir: File, artifactName: String, target: KonanTarget) { dependsOn(project.konanCompilerDownloadTask) diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt index 800ee821e2e..775d6937024 100644 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt +++ b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt @@ -18,13 +18,12 @@ package org.jetbrains.kotlin.gradle.plugin.tasks import groovy.lang.Closure import org.codehaus.groovy.runtime.GStringImpl +import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileTree import org.gradle.api.file.FileCollection import org.gradle.api.tasks.* import org.gradle.process.CommandLineArgumentProvider import org.jetbrains.kotlin.gradle.plugin.konan.* -import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact -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 @@ -323,29 +322,6 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec { } // endregion - // region IDE model - override fun toModelArtifact(): KonanModelArtifact { - val repos = libraries.repos - val resolver = defaultResolver( - repos.map { it.absolutePath }, - konanTarget, - Distribution(project.konanHome) - ) - - return KonanModelArtifactImpl( - artifactName, - artifact, - produce, - konanTarget.name, - name, - allSources.filterIsInstance(ConfigurableFileTree::class.java).map { it.dir }, - allSourceFiles, - libraries.asFiles(resolver), - repos.toList() - ) - } - // endregion - override fun run() { destinationDir.mkdirs() if (dumpParameters) { @@ -379,33 +355,13 @@ open class KonanCompileProgramTask: KonanCompileNativeBinary() { override val produce: CompilerOutputKind get() = CompilerOutputKind.PROGRAM @Internal - var runTask: Exec? = null + var runTask: TaskProvider? = null - inner class RunArgumentProvider(): CommandLineArgumentProvider { + inner class RunArgumentProvider: CommandLineArgumentProvider { override fun asArguments() = project.findProperty("runArgs")?.let { it.toString().split(' ') } ?: emptyList() } - - // Create tasks to run supported executables. - override fun init(config: KonanBuildingConfig<*>, destinationDir: File, artifactName: String, target: KonanTarget) { - super.init(config, destinationDir, artifactName, target) - if (!isCrossCompile && !project.hasProperty("konanNoRun")) { - runTask = project.tasks.create("run${artifactName.capitalize()}", Exec::class.java).apply { - group = "run" - dependsOn(this@KonanCompileProgramTask) - val artifactPathClosure = object : Closure(this) { - override fun call() = artifactPath - } - // Use GString to evaluate a path to the artifact lazily thus allow changing it at configuration phase. - val lazyArtifactPath = GStringImpl(arrayOf(artifactPathClosure), arrayOf("")) - executable(lazyArtifactPath) - // Add values passed in the runArgs project property as arguments. - argumentProviders.add(RunArgumentProvider()) - } - } - } - } open class KonanCompileDynamicTask: KonanCompileNativeBinary() { diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanGenerateCMakeTask.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanGenerateCMakeTask.kt deleted file mode 100644 index 94351bf15f9..00000000000 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanGenerateCMakeTask.kt +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2010-2017 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.tasks - -import org.gradle.api.DefaultTask -import org.gradle.api.file.FileCollection -import org.gradle.api.tasks.TaskAction -import org.jetbrains.kotlin.gradle.plugin.konan.KonanInteropLibrary -import org.jetbrains.kotlin.gradle.plugin.konan.KonanLibrary -import org.jetbrains.kotlin.gradle.plugin.konan.KonanProgram -import org.jetbrains.kotlin.gradle.plugin.konan.konanArtifactsContainer -import org.jetbrains.kotlin.konan.target.Family -import org.jetbrains.kotlin.konan.target.HostManager -import java.io.File - -open class KonanGenerateCMakeTask : DefaultTask() { - @Suppress("unused") - @TaskAction - fun generateCMake() { - val interops = project.konanArtifactsContainer.toList().filterIsInstance() - val libraries = project.konanArtifactsContainer.toList().filterIsInstance() - val programs = project.konanArtifactsContainer.toList().filterIsInstance() - val cMakeLists = generateCMakeLists( - project.name, - interops, - libraries, - programs - ) - File(project.projectDir, "CMakeLists.txt") - .writeText(cMakeLists) - - // This directory is filled out by the IDE - File(project.projectDir, "KotlinCMakeModule") - .mkdir() - } - - private val host = HostManager.host - - private fun generateCMakeLists( - projectName: String, - interops: List, - libraries: List, - programs: List - ): String { - val cMakeCurrentListDir = "$" + "{CMAKE_CURRENT_LIST_DIR}" - - return buildString { - appendln(""" - cmake_minimum_required(VERSION 3.8) - - set(CMAKE_MODULE_PATH $cMakeCurrentListDir/KotlinCMakeModule) - - project($projectName Kotlin) - """.trimIndent()) - appendln() - - for (interop in interops) { - val task = interop[host] ?: continue - appendln( - Call("cinterop") - .arg("NAME", interop.name) - .arg("DEF_FILE", task.defFile.relativePath.toString().crossPlatformPath) - .arg("COMPILER_OPTS", task.cMakeCompilerOpts) - ) - } - - for (library in libraries) { - val task = library[host] ?: continue - appendln( - Call("konanc_library") - .arg("NAME", library.name) - .arg("SOURCES", task.cMakeSources) - .arg("LIBRARIES", task.cMakeLibraries) - .arg("LINKER_OPTS", task.cMakeLinkerOpts)) - } - - for (program in programs) { - val task = program[host] ?: continue - appendln( - Call("konanc_executable") - .arg("NAME", program.name) - .arg("SOURCES", task.cMakeSources) - .arg("LIBRARIES", task.cMakeLibraries) - .arg("LINKER_OPTS", task.cMakeLinkerOpts)) - } - } - } - - private val File.relativePath get() = relativeTo(project.projectDir) - - private val String.crossPlatformPath get() = - if (host.family == Family.MINGW) replace('\\', '/') else this - - private val FileCollection.asCMakeSourceList: List - get() = files.map { it.relativePath.toString().crossPlatformPath } - - private val KonanInteropTask.cMakeCompilerOpts: String - get() = (compilerOpts + includeDirs.allHeadersDirs.map { "-I${it.absolutePath.crossPlatformPath}" }) - .joinToString(" ") - - private val KonanCompileTask.cMakeSources: String - get() = allSources.flatMap { it.asCMakeSourceList }.joinToString(" ") - - private val KonanCompileTask.cMakeLibraries: String - get() = mutableListOf().apply { - addAll(libraries.artifacts.map { it.artifactName }) - addAll(libraries.namedKlibs) - addAll(libraries.files.flatMap { it.files }.map { it.canonicalPath.crossPlatformPath }) - }.joinToString(" ") - - private val KonanCompileTask.cMakeLinkerOpts: String - get() = linkerOpts.joinToString(" ").replace('\\', '/') -} - -private class Call(val name: String) { - private val args: MutableList> = mutableListOf() - - fun arg(key: String, value: String?): Call { - if (value != null && value.isNotBlank()) args += key to value - return this - } - - override fun toString(): String = - buildString { - append(name) - append("(") - for ((key, value) in args) { - appendln() - append(" $key $value") - } - appendln(")") - } -} diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanInteropTask.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanInteropTask.kt index a0080060abf..12119d2623d 100644 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanInteropTask.kt +++ b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanInteropTask.kt @@ -27,8 +27,6 @@ import org.gradle.workers.WorkParameters import org.gradle.workers.WorkerExecutor import org.jetbrains.kotlin.gradle.plugin.konan.* import org.jetbrains.kotlin.gradle.plugin.konan.KonanInteropSpec.IncludeDirectoriesSpec -import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact -import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifactImpl import org.jetbrains.kotlin.konan.CURRENT import org.jetbrains.kotlin.konan.CompilerVersion import org.jetbrains.kotlin.konan.library.defaultResolver @@ -170,29 +168,6 @@ open class KonanInteropTask @Inject constructor(@Internal val workerExecutor: Wo // endregion - // region IDE model - override fun toModelArtifact(): KonanModelArtifact { - val repos = libraries.repos - val resolver = defaultResolver( - repos.map { it.absolutePath }, - konanTarget, - Distribution(project.konanHome) - ) - - return KonanModelArtifactImpl( - artifactName, - artifact, - CompilerOutputKind.LIBRARY, - konanTarget.name, - name, - listOfNotNull(defFile.parentFile), - listOf(defFile), - libraries.asFiles(resolver), - repos.toList() - ) - } - // endregion - internal interface RunToolParameters: WorkParameters { var taskName: String var args: List diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/model/KonanModel.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/model/KonanModel.kt deleted file mode 100644 index cb3ff3e0318..00000000000 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/model/KonanModel.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2010-2017 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.model - -import org.jetbrains.kotlin.konan.CompilerVersion -import org.jetbrains.kotlin.konan.target.CompilerOutputKind -import java.io.File -import java.io.Serializable - -/** - * An immutable representation of Konan's project model for gradle tooling API. - * This model is shared with the client processes such as an IDE. - */ -interface KonanModel : Serializable { - val konanHome: File - val konanVersion: CompilerVersion - val languageVersion: String? - val apiVersion: String? - - val artifacts: List -} - -/** - * A representation of a single binary produced by Kotlin/Native for a cetrain target. - */ -interface KonanModelArtifact : Serializable { - val name: String - val type: CompilerOutputKind - val targetPlatform: String - val file: File - val buildTaskName: String - val srcDirs: List - val srcFiles: List - val libraries: List - val searchPaths: List -} diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/model/KonanModelImpl.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/model/KonanModelImpl.kt deleted file mode 100644 index ce6a2c419cf..00000000000 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/model/KonanModelImpl.kt +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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.model - -import org.gradle.api.Project -import org.gradle.tooling.provider.model.ToolingModelBuilder -import org.jetbrains.kotlin.gradle.plugin.konan.konanArtifactsContainer -import org.jetbrains.kotlin.gradle.plugin.konan.konanExtension -import org.jetbrains.kotlin.gradle.plugin.konan.konanHome -import org.jetbrains.kotlin.gradle.plugin.konan.konanVersion -import org.jetbrains.kotlin.konan.CURRENT -import org.jetbrains.kotlin.konan.CompilerVersion -import org.jetbrains.kotlin.konan.target.CompilerOutputKind -import java.io.File - - -object KonanToolingModelBuilder : ToolingModelBuilder { - - override fun canBuild(modelName: String) = KonanModel::class.java.name == modelName - - private fun buildModelKonan(project: Project): KonanModel { - val artifacts = project.konanArtifactsContainer.flatten().toList().map { it.toModelArtifact() } - return KonanModelImpl( - artifacts, - project.file(project.konanHome), - project.konanVersion, - // TODO: Provide defaults for these versions. - project.konanExtension.languageVersion, - project.konanExtension.apiVersion - ) - } - - private val Project.hasKonanPlugin: Boolean - get() = with(pluginManager) { - hasPlugin("konan") || - hasPlugin("org.jetbrains.kotlin.konan") - } - - - override fun buildAll(modelName: String, project: Project): KonanModel = - when { - project.hasKonanPlugin -> buildModelKonan(project) - else -> throw IllegalStateException("The project '${project.path}' has no Kotlin/Native plugin") - } -} - -internal data class KonanModelImpl( - override val artifacts: List, - override val konanHome: File, - override val konanVersion: CompilerVersion, - override val languageVersion: String?, - override val apiVersion: String? -) : KonanModel - -internal data class KonanModelArtifactImpl( - override val name: String, - override val file: File, - override val type: CompilerOutputKind, - override val targetPlatform: String, - override val buildTaskName: String, - override val srcDirs: List, - override val srcFiles: List, - override val libraries: List, - override val searchPaths: List -) : KonanModelArtifact diff --git a/kotlin-native/tools/kotlin-native-gradle-plugin/src/test/kotlin/ToolingModelTests.kt b/kotlin-native/tools/kotlin-native-gradle-plugin/src/test/kotlin/ToolingModelTests.kt deleted file mode 100644 index 14b1a85be55..00000000000 --- a/kotlin-native/tools/kotlin-native-gradle-plugin/src/test/kotlin/ToolingModelTests.kt +++ /dev/null @@ -1,267 +0,0 @@ -/* - * 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.gradle.api.internal.project.ProjectInternal -import org.gradle.testfixtures.ProjectBuilder -import org.jetbrains.kotlin.gradle.plugin.konan.KonanPlugin -import org.jetbrains.kotlin.gradle.plugin.konan.konanArtifactsContainer -import org.jetbrains.kotlin.gradle.plugin.model.KonanToolingModelBuilder -import org.jetbrains.kotlin.konan.CURRENT -import org.jetbrains.kotlin.konan.CompilerVersion -import org.junit.Ignore -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import java.io.File -import java.nio.file.Paths -import kotlin.test.Test -import kotlin.test.assertEquals - -open class ToolingModelTests { - val tmpFolder = TemporaryFolder() - @Rule get - - val projectDirectory: File - get() = tmpFolder.root - - fun String.escapeBackSlashes() = KonanProject.escapeBackSlashes(this) - - @Ignore - @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() - } - - @Ignore - @Test - fun `The model should contain the same data as the Gradle tasks`() { - val project = KonanProject.createEmpty(projectDirectory, listOf("host", "wasm32")).apply { - val konanVersion = CompilerVersion.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 shadow.org.jetbrains.kotlin.konan.target.CompilerOutputKind - - public void assertEquals( - T actual, - T expected, - String message = "${'$'}expected expected but ${'$'}actual found") { - if (expected != actual) { - throw new AssertionError(message) - } - } - - public void assertContentEquals( - Collection actual, - Collection 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('org.jetbrains.kotlin.native.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() - } - - @Test - fun `The model should support maven libraries`() { - val repoDir = projectDirectory.resolve("repo").absolutePath.escapeBackSlashes() - val dependency = KonanProject.createEmpty(projectDirectory).apply { - buildFile.appendText(""" - group 'test' - version '1.0' - - konanArtifacts { - library('foo') - } - - apply plugin: 'maven-publish' - - publishing { - repositories { - maven { - url = '$repoDir' - } - } - } - """.trimIndent()) - generateSrcFile("main.kt") - } - dependency.createRunner().withArguments("build", "publish").build() - - val dependentDir = projectDirectory.resolve("dependent").apply { - mkdirs() - } - - - val dependent = ProjectBuilder.builder().withProjectDir(dependentDir).build() as ProjectInternal - - with(dependent) { - pluginManager.apply(KonanPlugin::class.java) - konanArtifactsContainer.library("bar") - repositories.maven { - it.setUrl(repoDir) - } - dependencies.apply { - add("artifactbar", "test:foo:1.0") - } - } - val model = KonanToolingModelBuilder.buildAll("konanModel", dependent) - assertEquals(1, model.artifacts.size, "Incorrect number of artifacts.") - val libraries = model.artifacts[0].libraries - assertEquals(1, libraries.size, "Incorrect number of libraries.") - val library = libraries[0].name - assertEquals("foo.klib", library, "Incorrect library name.") - } - -}