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
This commit is contained in:
committed by
Vasily Levchenko
parent
716326a60f
commit
8a48609823
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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<File>
|
||||
|
||||
@Input
|
||||
var repo: File = project.rootDir
|
||||
|
||||
val installDir: File
|
||||
val installDir: Provider<File>
|
||||
@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
|
||||
)
|
||||
|
||||
@@ -58,16 +58,16 @@ project.rootProject.ext.platformManager.enabled.each { target ->
|
||||
|
||||
def targetName = target.visibleName
|
||||
|
||||
ArrayList<Task> installTasks = []
|
||||
ArrayList<Task> cacheTasks = []
|
||||
ArrayList<TaskProvider> installTasks = []
|
||||
ArrayList<TaskProvider> 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
|
||||
}
|
||||
}
|
||||
|
||||
+83
-52
@@ -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<T: KonanBuildingTask>(private val name_: String,
|
||||
val type: Class<T>,
|
||||
val project: ProjectInternal,
|
||||
val targets: Iterable<String>)
|
||||
: KonanBuildingSpec, Named, DomainObjectSet<T> by WrapUtil.toDomainObjectSet(type) {
|
||||
abstract class KonanBuildingConfig<T : KonanBuildingTask>(
|
||||
private val name_: String,
|
||||
val type: Class<T>,
|
||||
val project: ProjectInternal,
|
||||
val targets: Iterable<String>
|
||||
) : KonanBuildingSpec, Named {
|
||||
|
||||
internal val mainVariant = KonanSoftwareComponent(project)
|
||||
override fun getName() = name_
|
||||
|
||||
protected val targetToTask = mutableMapOf<KonanTarget, T>()
|
||||
protected val targetToTask = mutableMapOf<KonanTarget, TaskProvider<T>>()
|
||||
|
||||
internal val aggregateBuildTask: Task
|
||||
fun tasks() = targetToTask.values
|
||||
|
||||
private val aggregateBuildTask: TaskProvider<Task>
|
||||
|
||||
internal var pomActions = mutableListOf<Action<MavenPom>>()
|
||||
|
||||
@@ -56,12 +62,11 @@ abstract class KonanBuildingConfig<T: KonanBuildingTask>(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<T: KonanBuildingTask>(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<T: KonanBuildingTask>(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<T> =
|
||||
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<Task> =
|
||||
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<Task>? {
|
||||
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<T: KonanBuildingTask>(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<Unit>) = forEach { it.libraries(closure) }
|
||||
override fun libraries(action: Action<KonanLibrariesSpec>) = forEach { it.libraries(action) }
|
||||
override fun libraries(configure: KonanLibrariesSpec.() -> Unit) = forEach { it.libraries(configure) }
|
||||
override fun libraries(closure: Closure<Unit>) =
|
||||
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<KonanLibrariesSpec>) =
|
||||
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<Any>) = 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<Any>) =
|
||||
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<T: KonanBuildingTask>(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<T>) =
|
||||
target(targetString) { configureAction.execute(this) }
|
||||
target(targetString) { configureAction.execute(this) }
|
||||
|
||||
fun target(targetString: String, configureAction: Closure<Unit>) =
|
||||
target(targetString, ConfigureUtil.configureUsing(configureAction))
|
||||
target(targetString, ConfigureUtil.configureUsing(configureAction))
|
||||
|
||||
fun pom(action: Action<MavenPom>) = pomActions + action
|
||||
}
|
||||
|
||||
+19
-19
@@ -43,33 +43,33 @@ abstract class KonanCompileConfig<T: KonanCompileTask>(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<Any>) = 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<Any>) = 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<String>) = forEach { it.linkerOpts(values) }
|
||||
override fun linkerOpts(vararg values: String) = forEach { it.linkerOpts(*values) }
|
||||
override fun linkerOpts(values: List<String>) = 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<Unit>) = forEach { it.dependencies(closure) }
|
||||
override fun dependencies(closure: Closure<Unit>) = tasks().forEach { it.configure { t -> t.dependencies(closure) } }
|
||||
}
|
||||
|
||||
open class KonanProgram(name: String,
|
||||
|
||||
+14
-15
@@ -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<Any>) = forEach {
|
||||
it.includeDirs.allHeaders(includeDirs)
|
||||
override fun allHeaders(includeDirs: Collection<Any>) = tasks().forEach {
|
||||
it.configure { t -> t.includeDirs.allHeaders(includeDirs) }
|
||||
}
|
||||
|
||||
override fun headerFilterOnly(vararg includeDirs: Any) = headerFilterOnly(includeDirs.toList())
|
||||
override fun headerFilterOnly(includeDirs: Collection<Any>) = forEach {
|
||||
it.includeDirs.headerFilterOnly(includeDirs)
|
||||
override fun headerFilterOnly(includeDirs: Collection<Any>) = 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<Unit>) = includeDirs(ConfigureUtil.configureUsing(closure))
|
||||
override fun includeDirs(action: Action<IncludeDirectoriesSpec>) = includeDirs { action.execute(this) }
|
||||
override fun includeDirs(configure: IncludeDirectoriesSpec.() -> Unit) = includeDirs.configure()
|
||||
|
||||
override fun linkerOpts(values: List<String>) = forEach { it.linkerOpts(values) }
|
||||
override fun linkerOpts(values: List<String>) = 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<Unit>) = 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<Unit>) = tasks().forEach { it.configure { t -> t.dependencies(closure) }}
|
||||
}
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
+29
-8
@@ -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<String>(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
|
||||
|
||||
-2
@@ -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)
|
||||
|
||||
+3
-47
@@ -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<Exec>? = 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<String>(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() {
|
||||
|
||||
-147
@@ -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<KonanInteropLibrary>()
|
||||
val libraries = project.konanArtifactsContainer.toList().filterIsInstance<KonanLibrary>()
|
||||
val programs = project.konanArtifactsContainer.toList().filterIsInstance<KonanProgram>()
|
||||
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<KonanInteropLibrary>,
|
||||
libraries: List<KonanLibrary>,
|
||||
programs: List<KonanProgram>
|
||||
): 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<String>
|
||||
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<String>().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<Pair<String, String>> = 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(")")
|
||||
}
|
||||
}
|
||||
-25
@@ -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<String>
|
||||
|
||||
-50
@@ -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<KonanModelArtifact>
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<File>
|
||||
val srcFiles: List<File>
|
||||
val libraries: List<File>
|
||||
val searchPaths: List<File>
|
||||
}
|
||||
-79
@@ -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<KonanModelArtifact>,
|
||||
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<File>,
|
||||
override val srcFiles: List<File>,
|
||||
override val libraries: List<File>,
|
||||
override val searchPaths: List<File>
|
||||
) : KonanModelArtifact
|
||||
@@ -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 <T> void assertEquals(
|
||||
T actual,
|
||||
T expected,
|
||||
String message = "${'$'}expected expected but ${'$'}actual found") {
|
||||
if (expected != actual) {
|
||||
throw new AssertionError(message)
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void assertContentEquals(
|
||||
Collection<T> actual,
|
||||
Collection<T> expected,
|
||||
String message = "${'$'}expected\nexpected but\n${'$'}actual\nfound") {
|
||||
if (actual.size() != expected.size() || !actual.containsAll(expected)) {
|
||||
throw new AssertionError(message)
|
||||
}
|
||||
}
|
||||
|
||||
task testModelData {
|
||||
dependsOn('compileKonanBaz')
|
||||
doLast {
|
||||
def model = KonanToolingModelBuilder.INSTANCE.buildAll("KonanModel", project)
|
||||
assertEquals(model.konanHome, file(project.getProperty('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.")
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user