From 8a48609823075dd33a10fe8010c6355533a6ac42 Mon Sep 17 00:00:00 2001 From: Pavel Punegov Date: Tue, 19 Jan 2021 13:51:46 +0300 Subject: [PATCH] Lazy task creation in konan plugin using Gradle Providers API. Removes obsolete CMake task and IDE model. Use Provider API for klib files. Replace findAll with matching to make tasks configure lazily Make some test tasks use lazy configuration Fix adding tasks to lists. Add it. to all fields to improve IDEA navigation Remove obsolete IDE model from the task Remove tooling model tests Fix aggregate task dependency Fix run tasks. Cleanup Review fixes --- .../backend.native/tests/build.gradle | 51 ++-- .../org/jetbrains/kotlin/KLibInstall.kt | 15 +- kotlin-native/platformLibs/build.gradle | 68 ++--- .../plugin/konan/KonanBuildingConfig.kt | 135 +++++---- .../gradle/plugin/konan/KonanCompileConfig.kt | 38 +-- .../plugin/konan/KonanInteropLibrary.kt | 29 +- .../gradle/plugin/konan/KonanLibrariesSpec.kt | 2 +- .../kotlin/gradle/plugin/konan/KonanPlugin.kt | 37 ++- .../plugin/konan/tasks/KonanBuildingTask.kt | 2 - .../plugin/konan/tasks/KonanCompileTask.kt | 50 +--- .../konan/tasks/KonanGenerateCMakeTask.kt | 147 ---------- .../plugin/konan/tasks/KonanInteropTask.kt | 25 -- .../kotlin/gradle/plugin/model/KonanModel.kt | 50 ---- .../gradle/plugin/model/KonanModelImpl.kt | 79 ------ .../src/test/kotlin/ToolingModelTests.kt | 267 ------------------ 15 files changed, 218 insertions(+), 777 deletions(-) delete mode 100644 kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanGenerateCMakeTask.kt delete mode 100644 kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/model/KonanModel.kt delete mode 100644 kotlin-native/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/model/KonanModelImpl.kt delete mode 100644 kotlin-native/tools/kotlin-native-gradle-plugin/src/test/kotlin/ToolingModelTests.kt 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.") - } - -}