Provide an extended DSL for final native binaries
In 1.3.0 only basic settings for final native binaries (e.g.
executables or frameworks) are available. They allow a user to
specify what kinds of binaries should be produced from one or another
compilation but they don't allow specifying different options for
different binaries or creating more than 2 (debug and release)
binaries of the same kind (e.g. executable) from the same
compilation. Also link tasks for these binaries are created after
project evaluation thus they are inaccessible for a user outside
of an afterEvaluate block.
This patch adds an extended binary DSL allowing a user to declare
binaries independently from compilations and to specify different
options (e.g. linker arguments) for different binaries. Also
link tasks for binaries declared in this DSL are created at a
configuration time so user can access them outside of an
afterEvaluate block.
Also this patch adds creating run tasks for all executables
declared in the buildscript (KT-28106)
Initial DSL methods for binaries declaration are still supported.
Kotlin DSL example is the following:
kotlin {
macosX64 {
binaries {
// Create debug and release executable with
// a name prefix 'Foo'.
// Two domain objects will be created:
// fooDebugExecutable and fooReleaseExecutable
executable("Foo", listOf(RELEASE, DEBUG)) {
compilation = compilations["foo"]
entryPoint = "foo.main"
linkerOpts.add("-Llib/path")
println(runTask.name)
}
// Name prefix and build types are optional.
// debugFramework and releaseFramework are created here.
framework()
}
}
}
This commit is contained in:
@@ -15,8 +15,13 @@ val generateMppTargetContainerWithPresets by generator(
|
||||
sourceSets["main"]
|
||||
)
|
||||
|
||||
generateMppTargetContainerWithPresets.run {
|
||||
systemProperty(
|
||||
val generateAbstractBinaryContainer by generator(
|
||||
"org.jetbrains.kotlin.generators.gradle.dsl.MppNativeBinaryDSLCodegenKt",
|
||||
sourceSets["main"]
|
||||
)
|
||||
|
||||
listOf(generateMppTargetContainerWithPresets, generateAbstractBinaryContainer).forEach {
|
||||
it.systemProperty(
|
||||
"org.jetbrains.kotlin.generators.gradle.dsl.outputSourceRoot",
|
||||
project(":kotlin-gradle-plugin").projectDir.resolve("src/main/kotlin").absolutePath
|
||||
)
|
||||
@@ -25,4 +30,4 @@ generateMppTargetContainerWithPresets.run {
|
||||
// Workaround: 'java -jar' refuses to read the original dotted filename on Windows, 'Unable to access jarFile org.jetbrains.kotlin....jar'
|
||||
tasks.named<Jar>(generateMppTargetContainerWithPresets.name + "WriteClassPath").configure {
|
||||
archiveName = generateMppTargetContainerWithPresets.name
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -32,3 +32,9 @@ internal fun TypeName.renderErased(): String =
|
||||
internal fun TypeName.collectFqNames(): Set<String> =
|
||||
setOf(fqName) + typeArguments.flatMap { it.collectFqNames() }.toSet()
|
||||
|
||||
internal fun String.indented(nSpaces: Int = 4): String {
|
||||
val spaces = String(CharArray(nSpaces) { ' ' })
|
||||
return lines().joinToString("\n") {
|
||||
if (it.isNotBlank()) "$spaces$it" else it
|
||||
}
|
||||
}
|
||||
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.gradle.dsl
|
||||
|
||||
import java.io.File
|
||||
|
||||
fun main() {
|
||||
generateAbstractKotlinNativeBinaryContainer()
|
||||
}
|
||||
|
||||
internal data class BinaryType(
|
||||
val description: String,
|
||||
val className: TypeName,
|
||||
val nativeOutputKind: TypeName,
|
||||
val factoryMethod: String,
|
||||
val getMethod: String,
|
||||
val findMethod: String
|
||||
)
|
||||
|
||||
private fun binaryType(description: String, className: String, outputKind: String, baseMethodName: String) =
|
||||
BinaryType(
|
||||
description,
|
||||
typeName("$MPP_PACKAGE.$className"),
|
||||
typeName("${nativeOutputKindClass.fqName}.$outputKind"),
|
||||
baseMethodName,
|
||||
"get${baseMethodName.capitalize()}",
|
||||
"find${baseMethodName.capitalize()}"
|
||||
)
|
||||
|
||||
private val nativeBuildTypeClass = typeName("$MPP_PACKAGE.NativeBuildType")
|
||||
private val nativeOutputKindClass = typeName("$MPP_PACKAGE.NativeOutputKind")
|
||||
private val nativeBinaryBaseClass = typeName("$MPP_PACKAGE.NativeBinary")
|
||||
|
||||
private fun generateFactoryMethods(binaryType: BinaryType): String {
|
||||
val className = binaryType.className.renderShort()
|
||||
val outputKind = binaryType.nativeOutputKind.renderShort()
|
||||
val outputKindClass = nativeOutputKindClass.renderShort()
|
||||
val nativeBuildType = nativeBuildTypeClass.renderShort()
|
||||
val methodName = binaryType.factoryMethod
|
||||
val binaryDescription = binaryType.description
|
||||
|
||||
return """
|
||||
/** Creates $binaryDescription with the given [namePrefix] for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun $methodName(
|
||||
namePrefix: String,
|
||||
buildTypes: Collection<$nativeBuildType> = $nativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configure: $className.() -> Unit = {}
|
||||
) = createBinaries(namePrefix, namePrefix, $outputKindClass.$outputKind, buildTypes, ::$className, configure)
|
||||
|
||||
/** Creates $binaryDescription with the empty name prefix for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun $methodName(
|
||||
buildTypes: Collection<$nativeBuildType> = $nativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configure: $className.() -> Unit = {}
|
||||
) = createBinaries("", project.name, $outputKindClass.$outputKind, buildTypes, ::$className, configure)
|
||||
|
||||
/** Creates $binaryDescription with the given [namePrefix] for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun $methodName(
|
||||
namePrefix: String,
|
||||
buildTypes: Collection<$nativeBuildType> = $nativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configureClosure: Closure<*>
|
||||
) = $methodName(namePrefix, buildTypes) { ConfigureUtil.configure(configureClosure, this) }
|
||||
|
||||
/** Creates $binaryDescription with the default name prefix for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun $methodName(
|
||||
buildTypes: Collection<$nativeBuildType> = $nativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configureClosure: Closure<*>
|
||||
) = $methodName(buildTypes) { ConfigureUtil.configure(configureClosure, this) }
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
private fun generateTypedGetters(binaryType: BinaryType): String = with(binaryType) {
|
||||
val className = className.renderShort()
|
||||
val buildType = nativeBuildTypeClass.renderShort()
|
||||
val nativeBuildType = nativeBuildTypeClass.renderShort()
|
||||
|
||||
return """
|
||||
/** Returns $description with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
|
||||
abstract fun $getMethod(namePrefix: String, buildType: $buildType): $className
|
||||
|
||||
/** Returns $description with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun $getMethod(namePrefix: String, buildType: String): $className =
|
||||
$getMethod(namePrefix, $nativeBuildType.valueOf(buildType.toUpperCase()))
|
||||
|
||||
/** Returns $description with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun $getMethod(buildType: $buildType): $className = $getMethod("", buildType)
|
||||
|
||||
/** Returns $description with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun $getMethod(buildType: String): $className = $getMethod("", buildType)
|
||||
|
||||
/** Returns $description with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
|
||||
abstract fun $findMethod(namePrefix: String, buildType: $buildType): $className?
|
||||
|
||||
/** Returns $description with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
|
||||
fun $findMethod(namePrefix: String, buildType: String): $className? =
|
||||
$findMethod(namePrefix, $nativeBuildType.valueOf(buildType.toUpperCase()))
|
||||
|
||||
/** Returns $description with the empty name prefix and the given build type. Returns null if there is no such binary. */
|
||||
fun $findMethod(buildType: $buildType): $className? = $findMethod("", buildType)
|
||||
|
||||
/** Returns $description with the empty name prefix and the given build type. Returns null if there is no such binary. */
|
||||
fun $findMethod(buildType: String): $className? = $findMethod("", buildType)
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
fun generateAbstractKotlinNativeBinaryContainer() {
|
||||
|
||||
val binaryTypes = listOf(
|
||||
binaryType("an executable","Executable", "EXECUTABLE", "executable"),
|
||||
binaryType("a static library","StaticLibrary", "STATIC", "staticLib"),
|
||||
binaryType("a shared library","SharedLibrary", "DYNAMIC", "sharedLib"),
|
||||
binaryType("an Objective-C framework","Framework", "FRAMEWORK", "framework")
|
||||
)
|
||||
|
||||
val className = typeName("org.jetbrains.kotlin.gradle.dsl.AbstractKotlinNativeBinaryContainer")
|
||||
val superClassName = typeName("org.gradle.api.DomainObjectSet", nativeBinaryBaseClass.fqName)
|
||||
|
||||
val imports = """
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.DomainObjectSet
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import $MPP_PACKAGE.*
|
||||
""".trimIndent()
|
||||
|
||||
val generatedCodeWarning = "// DO NOT EDIT MANUALLY! Generated by ${object {}.javaClass.enclosingClass.name}"
|
||||
|
||||
val classProperties = listOf(
|
||||
"abstract val project: Project",
|
||||
"abstract val target: ${typeName(KOTLIN_NATIVE_TARGET_CLASS_FQNAME).shortName()}"
|
||||
).joinToString(separator = "\n") { it.indented(4) }
|
||||
|
||||
val nativeBinary = nativeBinaryBaseClass.renderShort()
|
||||
val nativeOutputKind = nativeOutputKindClass.renderShort()
|
||||
val nativeBuildType = nativeBuildTypeClass.renderShort()
|
||||
|
||||
val buildTypeConstants = listOf(
|
||||
"// User-visible constants.",
|
||||
"val DEBUG = $nativeBuildType.DEBUG",
|
||||
"val RELEASE = $nativeBuildType.RELEASE"
|
||||
).joinToString(separator = "\n") { it.indented(4) }
|
||||
|
||||
val baseFactoryFunction = """
|
||||
protected abstract fun <T : $nativeBinary> createBinaries(
|
||||
namePrefix: String,
|
||||
baseName: String,
|
||||
outputKind: $nativeOutputKind,
|
||||
buildTypes: Collection<$nativeBuildType>,
|
||||
create: (name: String, baseName: String, buildType: $nativeBuildType, compilation: KotlinNativeCompilation) -> T,
|
||||
configure: T.() -> Unit
|
||||
)
|
||||
""".trimIndent().indented(4)
|
||||
|
||||
val namedGetters = """
|
||||
/** Provide an access to binaries using the [] operator in Groovy DSL. */
|
||||
fun getAt(name: String): NativeBinary = getByName(name)
|
||||
|
||||
/** Provide an access to binaries using the [] operator in Kotlin DSL. */
|
||||
operator fun get(name: String): NativeBinary = getByName(name)
|
||||
|
||||
/** Returns a binary with the given [name]. Throws an exception if there is no such binary. */
|
||||
abstract fun getByName(name: String): NativeBinary
|
||||
|
||||
/** Returns a binary with the given [name]. Returns null if there is no such binary. */
|
||||
abstract fun findByName(name: String): NativeBinary?
|
||||
""".trimIndent().indented(4)
|
||||
|
||||
val code = listOf(
|
||||
"package ${className.packageName()}",
|
||||
imports,
|
||||
generatedCodeWarning,
|
||||
"abstract class ${className.renderShort()} : ${superClassName.renderShort()} {",
|
||||
classProperties,
|
||||
buildTypeConstants,
|
||||
baseFactoryFunction,
|
||||
namedGetters,
|
||||
binaryTypes.joinToString(separator = "\n\n") { generateTypedGetters(it).indented(4) },
|
||||
binaryTypes.joinToString(separator = "\n\n") { generateFactoryMethods(it).indented(4) },
|
||||
"}"
|
||||
).joinToString(separator = "\n\n")
|
||||
|
||||
val outputSourceRoot = System.getProperties()["org.jetbrains.kotlin.generators.gradle.dsl.outputSourceRoot"]
|
||||
val targetFile = File("$outputSourceRoot/${className.fqName.replace(".", "/")}.kt")
|
||||
targetFile.writeText(code)
|
||||
}
|
||||
+1
-6
@@ -19,7 +19,7 @@ private val parentInterface = KotlinTargetsContainerWithPresets::class
|
||||
private val presetsProperty = KotlinTargetsContainerWithPresets::presets.name
|
||||
|
||||
private fun generateKotlinTargetContainerWithPresetFunctionsInterface() {
|
||||
// Generate KotlinMutliplatformExtension subclass with member functions for the presets:
|
||||
// Generate KotlinMultiplatformExtension subclass with member functions for the presets:
|
||||
val functions = allPresetEntries.map {
|
||||
generatePresetFunctions(it, presetsProperty, "configureOrCreate")
|
||||
}
|
||||
@@ -79,8 +79,3 @@ private fun generatePresetFunctions(
|
||||
fun $presetName(configure: Closure<*>) = $presetName { ConfigureUtil.configure(configure, this) }
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
private fun String.indented(nSpaces: Int = 4): String {
|
||||
val spaces = String(CharArray(nSpaces) { ' ' })
|
||||
return lines().joinToString("\n") { "$spaces$it" }
|
||||
}
|
||||
+3
-3
@@ -16,10 +16,10 @@ internal class KotlinPresetEntry(
|
||||
|
||||
internal fun KotlinPresetEntry.typeNames(): Set<TypeName> = setOf(presetType, targetType)
|
||||
|
||||
private const val MPP_PACKAGE = "org.jetbrains.kotlin.gradle.plugin.mpp"
|
||||
internal const val MPP_PACKAGE = "org.jetbrains.kotlin.gradle.plugin.mpp"
|
||||
|
||||
private const val KOTLIN_NATIVE_TARGET_PRESET_CLASS_FQNAME = "$MPP_PACKAGE.KotlinNativeTargetPreset"
|
||||
private const val KOTLIN_NATIVE_TARGET_CLASS_FQNAME = "$MPP_PACKAGE.KotlinNativeTarget"
|
||||
internal const val KOTLIN_NATIVE_TARGET_PRESET_CLASS_FQNAME = "$MPP_PACKAGE.KotlinNativeTargetPreset"
|
||||
internal const val KOTLIN_NATIVE_TARGET_CLASS_FQNAME = "$MPP_PACKAGE.KotlinNativeTarget"
|
||||
|
||||
private const val KOTLIN_ONLY_TARGET_CLASS_FQNAME = "$MPP_PACKAGE.KotlinOnlyTarget"
|
||||
|
||||
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
package org.jetbrains.kotlin.gradle.dsl
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.DomainObjectSet
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
|
||||
// DO NOT EDIT MANUALLY! Generated by org.jetbrains.kotlin.generators.gradle.dsl.MppNativeBinaryDSLCodegenKt
|
||||
|
||||
abstract class AbstractKotlinNativeBinaryContainer : DomainObjectSet<NativeBinary> {
|
||||
|
||||
abstract val project: Project
|
||||
abstract val target: KotlinNativeTarget
|
||||
|
||||
// User-visible constants.
|
||||
val DEBUG = NativeBuildType.DEBUG
|
||||
val RELEASE = NativeBuildType.RELEASE
|
||||
|
||||
protected abstract fun <T : NativeBinary> createBinaries(
|
||||
namePrefix: String,
|
||||
baseName: String,
|
||||
outputKind: NativeOutputKind,
|
||||
buildTypes: Collection<NativeBuildType>,
|
||||
create: (name: String, baseName: String, buildType: NativeBuildType, compilation: KotlinNativeCompilation) -> T,
|
||||
configure: T.() -> Unit
|
||||
)
|
||||
|
||||
/** Provide an access to binaries using the [] operator in Groovy DSL. */
|
||||
fun getAt(name: String): NativeBinary = getByName(name)
|
||||
|
||||
/** Provide an access to binaries using the [] operator in Kotlin DSL. */
|
||||
operator fun get(name: String): NativeBinary = getByName(name)
|
||||
|
||||
/** Returns a binary with the given [name]. Throws an exception if there is no such binary. */
|
||||
abstract fun getByName(name: String): NativeBinary
|
||||
|
||||
/** Returns a binary with the given [name]. Returns null if there is no such binary. */
|
||||
abstract fun findByName(name: String): NativeBinary?
|
||||
|
||||
/** Returns an executable with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
|
||||
abstract fun getExecutable(namePrefix: String, buildType: NativeBuildType): Executable
|
||||
|
||||
/** Returns an executable with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getExecutable(namePrefix: String, buildType: String): Executable =
|
||||
getExecutable(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||
|
||||
/** Returns an executable with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getExecutable(buildType: NativeBuildType): Executable = getExecutable("", buildType)
|
||||
|
||||
/** Returns an executable with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getExecutable(buildType: String): Executable = getExecutable("", buildType)
|
||||
|
||||
/** Returns an executable with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
|
||||
abstract fun findExecutable(namePrefix: String, buildType: NativeBuildType): Executable?
|
||||
|
||||
/** Returns an executable with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
|
||||
fun findExecutable(namePrefix: String, buildType: String): Executable? =
|
||||
findExecutable(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||
|
||||
/** Returns an executable with the empty name prefix and the given build type. Returns null if there is no such binary. */
|
||||
fun findExecutable(buildType: NativeBuildType): Executable? = findExecutable("", buildType)
|
||||
|
||||
/** Returns an executable with the empty name prefix and the given build type. Returns null if there is no such binary. */
|
||||
fun findExecutable(buildType: String): Executable? = findExecutable("", buildType)
|
||||
|
||||
/** Returns a static library with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
|
||||
abstract fun getStaticLib(namePrefix: String, buildType: NativeBuildType): StaticLibrary
|
||||
|
||||
/** Returns a static library with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getStaticLib(namePrefix: String, buildType: String): StaticLibrary =
|
||||
getStaticLib(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||
|
||||
/** Returns a static library with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getStaticLib(buildType: NativeBuildType): StaticLibrary = getStaticLib("", buildType)
|
||||
|
||||
/** Returns a static library with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getStaticLib(buildType: String): StaticLibrary = getStaticLib("", buildType)
|
||||
|
||||
/** Returns a static library with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
|
||||
abstract fun findStaticLib(namePrefix: String, buildType: NativeBuildType): StaticLibrary?
|
||||
|
||||
/** Returns a static library with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
|
||||
fun findStaticLib(namePrefix: String, buildType: String): StaticLibrary? =
|
||||
findStaticLib(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||
|
||||
/** Returns a static library with the empty name prefix and the given build type. Returns null if there is no such binary. */
|
||||
fun findStaticLib(buildType: NativeBuildType): StaticLibrary? = findStaticLib("", buildType)
|
||||
|
||||
/** Returns a static library with the empty name prefix and the given build type. Returns null if there is no such binary. */
|
||||
fun findStaticLib(buildType: String): StaticLibrary? = findStaticLib("", buildType)
|
||||
|
||||
/** Returns a shared library with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
|
||||
abstract fun getSharedLib(namePrefix: String, buildType: NativeBuildType): SharedLibrary
|
||||
|
||||
/** Returns a shared library with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getSharedLib(namePrefix: String, buildType: String): SharedLibrary =
|
||||
getSharedLib(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||
|
||||
/** Returns a shared library with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getSharedLib(buildType: NativeBuildType): SharedLibrary = getSharedLib("", buildType)
|
||||
|
||||
/** Returns a shared library with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getSharedLib(buildType: String): SharedLibrary = getSharedLib("", buildType)
|
||||
|
||||
/** Returns a shared library with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
|
||||
abstract fun findSharedLib(namePrefix: String, buildType: NativeBuildType): SharedLibrary?
|
||||
|
||||
/** Returns a shared library with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
|
||||
fun findSharedLib(namePrefix: String, buildType: String): SharedLibrary? =
|
||||
findSharedLib(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||
|
||||
/** Returns a shared library with the empty name prefix and the given build type. Returns null if there is no such binary. */
|
||||
fun findSharedLib(buildType: NativeBuildType): SharedLibrary? = findSharedLib("", buildType)
|
||||
|
||||
/** Returns a shared library with the empty name prefix and the given build type. Returns null if there is no such binary. */
|
||||
fun findSharedLib(buildType: String): SharedLibrary? = findSharedLib("", buildType)
|
||||
|
||||
/** Returns an Objective-C framework with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
|
||||
abstract fun getFramework(namePrefix: String, buildType: NativeBuildType): Framework
|
||||
|
||||
/** Returns an Objective-C framework with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getFramework(namePrefix: String, buildType: String): Framework =
|
||||
getFramework(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||
|
||||
/** Returns an Objective-C framework with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getFramework(buildType: NativeBuildType): Framework = getFramework("", buildType)
|
||||
|
||||
/** Returns an Objective-C framework with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
|
||||
fun getFramework(buildType: String): Framework = getFramework("", buildType)
|
||||
|
||||
/** Returns an Objective-C framework with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
|
||||
abstract fun findFramework(namePrefix: String, buildType: NativeBuildType): Framework?
|
||||
|
||||
/** Returns an Objective-C framework with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
|
||||
fun findFramework(namePrefix: String, buildType: String): Framework? =
|
||||
findFramework(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||
|
||||
/** Returns an Objective-C framework with the empty name prefix and the given build type. Returns null if there is no such binary. */
|
||||
fun findFramework(buildType: NativeBuildType): Framework? = findFramework("", buildType)
|
||||
|
||||
/** Returns an Objective-C framework with the empty name prefix and the given build type. Returns null if there is no such binary. */
|
||||
fun findFramework(buildType: String): Framework? = findFramework("", buildType)
|
||||
|
||||
/** Creates an executable with the given [namePrefix] for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun executable(
|
||||
namePrefix: String,
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configure: Executable.() -> Unit = {}
|
||||
) = createBinaries(namePrefix, namePrefix, NativeOutputKind.EXECUTABLE, buildTypes, ::Executable, configure)
|
||||
|
||||
/** Creates an executable with the empty name prefix for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun executable(
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configure: Executable.() -> Unit = {}
|
||||
) = createBinaries("", project.name, NativeOutputKind.EXECUTABLE, buildTypes, ::Executable, configure)
|
||||
|
||||
/** Creates an executable with the given [namePrefix] for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun executable(
|
||||
namePrefix: String,
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configureClosure: Closure<*>
|
||||
) = executable(namePrefix, buildTypes) { ConfigureUtil.configure(configureClosure, this) }
|
||||
|
||||
/** Creates an executable with the default name prefix for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun executable(
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configureClosure: Closure<*>
|
||||
) = executable(buildTypes) { ConfigureUtil.configure(configureClosure, this) }
|
||||
|
||||
/** Creates a static library with the given [namePrefix] for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun staticLib(
|
||||
namePrefix: String,
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configure: StaticLibrary.() -> Unit = {}
|
||||
) = createBinaries(namePrefix, namePrefix, NativeOutputKind.STATIC, buildTypes, ::StaticLibrary, configure)
|
||||
|
||||
/** Creates a static library with the empty name prefix for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun staticLib(
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configure: StaticLibrary.() -> Unit = {}
|
||||
) = createBinaries("", project.name, NativeOutputKind.STATIC, buildTypes, ::StaticLibrary, configure)
|
||||
|
||||
/** Creates a static library with the given [namePrefix] for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun staticLib(
|
||||
namePrefix: String,
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configureClosure: Closure<*>
|
||||
) = staticLib(namePrefix, buildTypes) { ConfigureUtil.configure(configureClosure, this) }
|
||||
|
||||
/** Creates a static library with the default name prefix for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun staticLib(
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configureClosure: Closure<*>
|
||||
) = staticLib(buildTypes) { ConfigureUtil.configure(configureClosure, this) }
|
||||
|
||||
/** Creates a shared library with the given [namePrefix] for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun sharedLib(
|
||||
namePrefix: String,
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configure: SharedLibrary.() -> Unit = {}
|
||||
) = createBinaries(namePrefix, namePrefix, NativeOutputKind.DYNAMIC, buildTypes, ::SharedLibrary, configure)
|
||||
|
||||
/** Creates a shared library with the empty name prefix for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun sharedLib(
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configure: SharedLibrary.() -> Unit = {}
|
||||
) = createBinaries("", project.name, NativeOutputKind.DYNAMIC, buildTypes, ::SharedLibrary, configure)
|
||||
|
||||
/** Creates a shared library with the given [namePrefix] for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun sharedLib(
|
||||
namePrefix: String,
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configureClosure: Closure<*>
|
||||
) = sharedLib(namePrefix, buildTypes) { ConfigureUtil.configure(configureClosure, this) }
|
||||
|
||||
/** Creates a shared library with the default name prefix for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun sharedLib(
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configureClosure: Closure<*>
|
||||
) = sharedLib(buildTypes) { ConfigureUtil.configure(configureClosure, this) }
|
||||
|
||||
/** Creates an Objective-C framework with the given [namePrefix] for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun framework(
|
||||
namePrefix: String,
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configure: Framework.() -> Unit = {}
|
||||
) = createBinaries(namePrefix, namePrefix, NativeOutputKind.FRAMEWORK, buildTypes, ::Framework, configure)
|
||||
|
||||
/** Creates an Objective-C framework with the empty name prefix for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun framework(
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configure: Framework.() -> Unit = {}
|
||||
) = createBinaries("", project.name, NativeOutputKind.FRAMEWORK, buildTypes, ::Framework, configure)
|
||||
|
||||
/** Creates an Objective-C framework with the given [namePrefix] for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun framework(
|
||||
namePrefix: String,
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configureClosure: Closure<*>
|
||||
) = framework(namePrefix, buildTypes) { ConfigureUtil.configure(configureClosure, this) }
|
||||
|
||||
/** Creates an Objective-C framework with the default name prefix for each build type and configures it. */
|
||||
@JvmOverloads
|
||||
fun framework(
|
||||
buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
|
||||
configureClosure: Closure<*>
|
||||
) = framework(buildTypes) { ConfigureUtil.configure(configureClosure, this) }
|
||||
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.dsl
|
||||
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.plugins.ExtensionAware
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
import javax.inject.Inject
|
||||
|
||||
/*
|
||||
Naming:
|
||||
|
||||
executable('foo', [debug, release]) -> fooDebugExecutable + fooReleaseExecutable
|
||||
executable -> debugExecutable, releaseExecutable
|
||||
executable([debug]) -> debugExecutable
|
||||
|
||||
// Tests:
|
||||
1. Cannot add a second binary with the same parameters.
|
||||
2. Can access a binary by name
|
||||
3. Access linkTask
|
||||
4. Access runTask
|
||||
5. Final binaries have correct names
|
||||
6. Old APIs work fine:
|
||||
- creating binaries,
|
||||
- getting binaries and link tasks,
|
||||
- setting binary parameters using compilation DSL: linker opts and entry points
|
||||
*/
|
||||
|
||||
open class KotlinNativeBinaryContainer @Inject constructor(
|
||||
override val target: KotlinNativeTarget,
|
||||
backingContainer: DomainObjectSet<NativeBinary>
|
||||
) : AbstractKotlinNativeBinaryContainer(),
|
||||
DomainObjectSet<NativeBinary> by backingContainer
|
||||
{
|
||||
override val project: Project
|
||||
get() = target.project
|
||||
|
||||
private val defaultCompilation: KotlinNativeCompilation
|
||||
get() = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||
|
||||
private val nameToBinary = mutableMapOf<String, NativeBinary>()
|
||||
|
||||
// region DSL getters.
|
||||
private fun generateName(prefix: String, buildType: NativeBuildType, outputKindClassifier: String) =
|
||||
lowerCamelCaseName(prefix, buildType.getName(), outputKindClassifier)
|
||||
|
||||
private inline fun <reified T : NativeBinary> getBinary(
|
||||
namePrefix: String,
|
||||
buildType: NativeBuildType,
|
||||
outputKind: NativeOutputKind
|
||||
): T {
|
||||
val classifier = outputKind.taskNameClassifier
|
||||
val name = generateName(namePrefix, buildType, classifier)
|
||||
val binary = getByName(name)
|
||||
require(binary is T && binary.buildType == buildType) {
|
||||
"Binary $name has incorrect outputKind or build type.\n" +
|
||||
"Expected: ${buildType.getName()} $classifier. Actual: ${binary.buildType.getName()} ${binary.outputKind.taskNameClassifier}."
|
||||
}
|
||||
return binary as T
|
||||
}
|
||||
|
||||
private inline fun <reified T : NativeBinary> findBinary(
|
||||
namePrefix: String,
|
||||
buildType: NativeBuildType,
|
||||
outputKind: NativeOutputKind
|
||||
): T? {
|
||||
val classifier = outputKind.taskNameClassifier
|
||||
val name = generateName(namePrefix, buildType, classifier)
|
||||
val binary = findByName(name)
|
||||
return if (binary is T && binary.buildType == buildType) {
|
||||
binary
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getByName(name: String): NativeBinary = nameToBinary.getValue(name)
|
||||
override fun findByName(name: String): NativeBinary? = nameToBinary[name]
|
||||
|
||||
override fun getExecutable(namePrefix: String, buildType: NativeBuildType): Executable =
|
||||
getBinary(namePrefix, buildType, NativeOutputKind.EXECUTABLE)
|
||||
|
||||
override fun getStaticLib(namePrefix: String, buildType: NativeBuildType): StaticLibrary =
|
||||
getBinary(namePrefix, buildType, NativeOutputKind.STATIC)
|
||||
|
||||
override fun getSharedLib(namePrefix: String, buildType: NativeBuildType): SharedLibrary =
|
||||
getBinary(namePrefix, buildType, NativeOutputKind.DYNAMIC)
|
||||
|
||||
override fun getFramework(namePrefix: String, buildType: NativeBuildType): Framework =
|
||||
getBinary(namePrefix, buildType, NativeOutputKind.FRAMEWORK)
|
||||
|
||||
|
||||
override fun findExecutable(namePrefix: String, buildType: NativeBuildType): Executable? =
|
||||
findBinary(namePrefix, buildType, NativeOutputKind.EXECUTABLE)
|
||||
|
||||
override fun findStaticLib(namePrefix: String, buildType: NativeBuildType): StaticLibrary? =
|
||||
findBinary(namePrefix, buildType, NativeOutputKind.STATIC)
|
||||
|
||||
override fun findSharedLib(namePrefix: String, buildType: NativeBuildType): SharedLibrary? =
|
||||
findBinary(namePrefix, buildType, NativeOutputKind.DYNAMIC)
|
||||
|
||||
override fun findFramework(namePrefix: String, buildType: NativeBuildType): Framework? =
|
||||
findBinary(namePrefix, buildType, NativeOutputKind.FRAMEWORK)
|
||||
// endregion.
|
||||
|
||||
// region Factories
|
||||
override fun <T : NativeBinary> createBinaries(
|
||||
namePrefix: String,
|
||||
baseName: String,
|
||||
outputKind: NativeOutputKind,
|
||||
buildTypes: Collection<NativeBuildType>,
|
||||
create: (name: String, baseName: String, buildType: NativeBuildType, compilation: KotlinNativeCompilation) -> T,
|
||||
configure: T.() -> Unit
|
||||
) = buildTypes.forEach { buildType ->
|
||||
val name = generateName(namePrefix, buildType, outputKind.taskNameClassifier)
|
||||
|
||||
require(name !in nameToBinary) {
|
||||
"Cannot create binary $name: binary with such a name already exists"
|
||||
}
|
||||
|
||||
require(outputKind.availableFor(target.konanTarget)) {
|
||||
"Cannot create binary $name: ${outputKind.taskNameClassifier.decapitalize()} binaries are not available for target ${target.name}"
|
||||
}
|
||||
|
||||
val binary = create(name, baseName, buildType, defaultCompilation)
|
||||
add(binary)
|
||||
nameToBinary[binary.name] = binary
|
||||
// Allow accessing binaries as properties of the container in Groovy DSL.
|
||||
if (this is ExtensionAware) {
|
||||
extensions.add(binary.name, binary)
|
||||
}
|
||||
binary.configure()
|
||||
}
|
||||
|
||||
internal fun defaultTestExecutable(
|
||||
configure: Executable.() -> Unit
|
||||
) = createBinaries(
|
||||
"test",
|
||||
"test",
|
||||
NativeOutputKind.EXECUTABLE,
|
||||
listOf(NativeBuildType.DEBUG),
|
||||
{ name, baseName, buildType, compilation ->
|
||||
Executable(name, baseName, buildType, compilation, true)
|
||||
},
|
||||
configure
|
||||
)
|
||||
// endregion.
|
||||
}
|
||||
+123
-109
@@ -23,6 +23,7 @@ import org.gradle.api.plugins.BasePlugin
|
||||
import org.gradle.api.plugins.JavaBasePlugin
|
||||
import org.gradle.api.tasks.Copy
|
||||
import org.gradle.api.tasks.Delete
|
||||
import org.gradle.api.tasks.Exec
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||
@@ -33,8 +34,10 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPILATION_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinNativeCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.CInteropProcess
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink
|
||||
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
@@ -59,7 +62,8 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
|
||||
}
|
||||
|
||||
|
||||
abstract fun configureArchivesAndComponent(target: KotlinTargetType)
|
||||
abstract protected fun configureArchivesAndComponent(target: KotlinTargetType)
|
||||
abstract protected fun configureTest(target: KotlinTargetType)
|
||||
|
||||
private fun Project.registerOutputsForStaleOutputCleanup(kotlinCompilation: KotlinCompilation<*>) {
|
||||
val cleanTask = tasks.getByName(LifecycleBasePlugin.CLEAN_TASK_NAME) as Delete
|
||||
@@ -116,22 +120,6 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
|
||||
}
|
||||
}
|
||||
|
||||
protected fun configureTest(target: KotlinTarget) {
|
||||
val testCompilation = target.compilations.findByName(KotlinCompilation.TEST_COMPILATION_NAME) as? KotlinCompilationToRunnableFiles
|
||||
?: return // Otherwise, there is no runtime classpath
|
||||
|
||||
target.project.tasks.create(lowerCamelCaseName(target.targetName, testTaskNameSuffix), Test::class.java).apply {
|
||||
project.afterEvaluate {
|
||||
// use afterEvaluate to override the JavaPlugin defaults for Test tasks
|
||||
conventionMapping.map("testClassesDirs") { testCompilation.output.classesDirs }
|
||||
conventionMapping.map("classpath") { testCompilation.runtimeDependencyFiles }
|
||||
description = "Runs the unit tests."
|
||||
group = JavaBasePlugin.VERIFICATION_GROUP
|
||||
target.project.tasks.findByName(JavaBasePlugin.CHECK_TASK_NAME)?.dependsOn(this@apply)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun configureResourceProcessing(
|
||||
compilation: KotlinCompilationWithResources<*>,
|
||||
resourceSet: FileCollection
|
||||
@@ -372,6 +360,22 @@ open class KotlinTargetConfigurator<KotlinCompilationType : KotlinCompilation<*>
|
||||
}
|
||||
}
|
||||
|
||||
override fun configureTest(target: KotlinOnlyTarget<KotlinCompilationType>) {
|
||||
val testCompilation = target.compilations.findByName(KotlinCompilation.TEST_COMPILATION_NAME) as? KotlinCompilationToRunnableFiles<*>
|
||||
?: return // Otherwise, there is no runtime classpath
|
||||
|
||||
target.project.tasks.create(lowerCamelCaseName(target.targetName, testTaskNameSuffix), Test::class.java).apply {
|
||||
project.afterEvaluate {
|
||||
// use afterEvaluate to override the JavaPlugin defaults for Test tasks
|
||||
conventionMapping.map("testClassesDirs") { testCompilation.output.classesDirs }
|
||||
conventionMapping.map("classpath") { testCompilation.runtimeDependencyFiles }
|
||||
description = "Runs the unit tests."
|
||||
group = JavaBasePlugin.VERIFICATION_GROUP
|
||||
target.project.tasks.findByName(JavaBasePlugin.CHECK_TASK_NAME)?.dependsOn(this@apply)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addJar(configuration: Configuration, jarArtifact: PublishArtifact) {
|
||||
val publications = configuration.outgoing
|
||||
|
||||
@@ -388,49 +392,6 @@ open class KotlinNativeTargetConfigurator(
|
||||
createDefaultSourceSets = true,
|
||||
createTestCompilation = true
|
||||
) {
|
||||
private val hostTargets = listOf(KonanTarget.LINUX_X64, KonanTarget.MACOS_X64, KonanTarget.MINGW_X64)
|
||||
|
||||
private val Collection<*>.isDimensionVisible: Boolean
|
||||
get() = size > 1
|
||||
|
||||
private fun Project.createTestTask(compilation: KotlinNativeCompilation, testExecutableLinkTask: KotlinNativeCompile) {
|
||||
val compilationSuffix = compilation.name.takeIf { it != KotlinCompilation.TEST_COMPILATION_NAME }.orEmpty()
|
||||
val taskName = lowerCamelCaseName(compilation.target.targetName, compilationSuffix, testTaskNameSuffix)
|
||||
val testTask = tasks.create(taskName, RunTestExecutable::class.java).apply {
|
||||
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||
description = "Executes Kotlin/Native unit tests from the '${compilation.name}' compilation " +
|
||||
"for target '${compilation.target.name}'."
|
||||
enabled = compilation.target.konanTarget.isCurrentHost
|
||||
|
||||
val testExecutableProperty = testExecutableLinkTask.outputFile
|
||||
executable = testExecutableProperty.get().absolutePath
|
||||
outputDir = project.layout.projectDirectory.asFile
|
||||
|
||||
if (project.hasProperty("teamcity.version")) {
|
||||
args("--ktest_logger=TEAMCITY")
|
||||
}
|
||||
|
||||
onlyIf { testExecutableProperty.get().exists() }
|
||||
inputs.file(testExecutableProperty)
|
||||
dependsOn(testExecutableLinkTask)
|
||||
}
|
||||
tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME).apply {
|
||||
dependsOn(testTask)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.binaryOutputDirectory(
|
||||
buildType: NativeBuildType,
|
||||
kind: NativeOutputKind,
|
||||
compilation: KotlinNativeCompilation
|
||||
): File {
|
||||
val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
|
||||
val buildTypeSubDirectory = buildType.name.toLowerCase()
|
||||
val kindSubDirectory = kind.outputDirectoryName
|
||||
|
||||
return buildDir.resolve("bin/$targetSubDirectory${compilation.name}/$buildTypeSubDirectory/$kindSubDirectory")
|
||||
}
|
||||
|
||||
private fun Project.klibOutputDirectory(
|
||||
compilation: KotlinNativeCompilation
|
||||
): File {
|
||||
@@ -438,55 +399,14 @@ open class KotlinNativeTargetConfigurator(
|
||||
return buildDir.resolve("classes/kotlin/$targetSubDirectory${compilation.name}")
|
||||
}
|
||||
|
||||
private fun KotlinNativeCompile.addCompilerPlugins() {
|
||||
private fun AbstractKotlinNativeCompile.addCompilerPlugins() {
|
||||
SubpluginEnvironment
|
||||
.loadSubplugins(project, kotlinPluginVersion)
|
||||
.addSubpluginOptions<CommonCompilerArguments>(project, this, compilerPluginOptions)
|
||||
compilerPluginClasspath = project.configurations.getByName(NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME)
|
||||
}
|
||||
|
||||
private fun Project.createBinaryLinkTasks(compilation: KotlinNativeCompilation) = whenEvaluated {
|
||||
val konanTarget = compilation.target.konanTarget
|
||||
val availableOutputKinds = compilation.outputKinds.filter { it.availableFor(konanTarget) }
|
||||
val linkAll = project.tasks.maybeCreate(compilation.linkAllTaskName)
|
||||
|
||||
for (buildType in compilation.buildTypes) {
|
||||
for (kind in availableOutputKinds) {
|
||||
val compilerOutputKind = kind.compilerOutputKind
|
||||
|
||||
val linkTask = project.tasks.create(
|
||||
compilation.linkTaskName(kind, buildType),
|
||||
KotlinNativeCompile::class.java
|
||||
).apply {
|
||||
this.compilation = compilation
|
||||
outputKind = compilerOutputKind
|
||||
group = BasePlugin.BUILD_GROUP
|
||||
description = "Links ${kind.description} from the '${compilation.name}' " +
|
||||
"compilation for target '${compilation.platformType.name}'."
|
||||
enabled = compilation.target.konanTarget.enabledOnCurrentHost
|
||||
|
||||
optimized = buildType.optimized
|
||||
debuggable = buildType.debuggable
|
||||
|
||||
destinationDir = binaryOutputDirectory(buildType, kind, compilation)
|
||||
addCompilerPlugins()
|
||||
|
||||
linkAll.dependsOn(this)
|
||||
}
|
||||
|
||||
compilation.binaryTasks[kind to buildType] = linkTask
|
||||
|
||||
if (compilation.isTestCompilation &&
|
||||
buildType == NativeBuildType.DEBUG &&
|
||||
konanTarget in hostTargets
|
||||
) {
|
||||
// TODO: Refactor and move into the corresponding method of AbstractKotlinTargetConfigurator.
|
||||
createTestTask(compilation, linkTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Artifact creation.
|
||||
private fun Project.createKlibArtifact(
|
||||
compilation: KotlinNativeCompilation,
|
||||
artifactFile: File,
|
||||
@@ -541,7 +461,52 @@ open class KotlinNativeTargetConfigurator(
|
||||
interop: DefaultCInteropSettings,
|
||||
interopTask: CInteropProcess
|
||||
) = createKlibArtifact(interop.compilation, interopTask.outputFile, "cinterop-${interop.name}", interopTask, copy = true)
|
||||
// endregion.
|
||||
|
||||
// region Task creation.
|
||||
private fun Project.createLinkTask(binary: NativeBinary) {
|
||||
// TODO: drop compilation.linkAllTaskName
|
||||
// TODO: drop compilation.binaryTasks
|
||||
// TODO: Provide a link all task.
|
||||
tasks.create(
|
||||
binary.linkTaskName,
|
||||
KotlinNativeLink::class.java
|
||||
).apply {
|
||||
val target = binary.target
|
||||
this.binary = binary
|
||||
group = BasePlugin.BUILD_GROUP
|
||||
description = "Links ${binary.outputKind.description} '${binary.name}' for a target '${target.name}'."
|
||||
enabled = target.konanTarget.enabledOnCurrentHost
|
||||
destinationDir = binary.outputDirectory
|
||||
addCompilerPlugins()
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.createRunTask(binary: Executable) {
|
||||
val taskName = binary.runTaskName
|
||||
// TODO provide a special exec task for tests.
|
||||
tasks.create(taskName, Exec::class.java).apply {
|
||||
if (binary.isDefaultTestExecutable) {
|
||||
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||
description = "Executes Kotlin/Native unit tests for target ${binary.target.name}."
|
||||
tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(this)
|
||||
if (project.hasProperty("teamcity.version")) {
|
||||
args("--ktest_logger=TEAMCITY")
|
||||
}
|
||||
} else {
|
||||
group = RUN_GROUP
|
||||
description = "Executes Kotlin/Native executable ${binary.baseName} for target ${binary.target.name}"
|
||||
}
|
||||
|
||||
enabled = binary.target.konanTarget.isCurrentHost
|
||||
|
||||
executable = binary.outputFile.absolutePath
|
||||
workingDir = project.projectDir
|
||||
|
||||
onlyIf { binary.outputFile.exists() }
|
||||
dependsOn(binary.linkTaskName)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.createKlibCompilationTask(compilation: KotlinNativeCompilation) {
|
||||
val compileTask = tasks.create(
|
||||
@@ -549,7 +514,6 @@ open class KotlinNativeTargetConfigurator(
|
||||
KotlinNativeCompile::class.java
|
||||
).apply {
|
||||
this.compilation = compilation
|
||||
outputKind = CompilerOutputKind.LIBRARY
|
||||
group = BasePlugin.BUILD_GROUP
|
||||
description = "Compiles a klibrary from the '${compilation.name}' " +
|
||||
"compilation for target '${compilation.platformType.name}'."
|
||||
@@ -602,12 +566,20 @@ open class KotlinNativeTargetConfigurator(
|
||||
createCInteropKlibArtifact(interop, interopTask)
|
||||
}
|
||||
}
|
||||
// endregion.
|
||||
|
||||
// region Configuration.
|
||||
override fun configureTarget(target: KotlinNativeTarget) {
|
||||
super.configureTarget(target)
|
||||
configureBinaries(target)
|
||||
configureCInterops(target)
|
||||
warnAboutIncorrectDependencies(target)
|
||||
}
|
||||
|
||||
override fun configureArchivesAndComponent(target: KotlinNativeTarget): Unit = with(target.project) {
|
||||
tasks.create(target.artifactsTaskName)
|
||||
target.compilations.all {
|
||||
createKlibCompilationTask(it)
|
||||
createBinaryLinkTasks(it)
|
||||
}
|
||||
|
||||
with(configurations.getByName(target.apiElementsConfigurationName)) {
|
||||
@@ -615,6 +587,12 @@ open class KotlinNativeTargetConfigurator(
|
||||
}
|
||||
}
|
||||
|
||||
override fun configureTest(target: KotlinNativeTarget) {
|
||||
target.binaries.defaultTestExecutable {
|
||||
compilation = target.compilations.maybeCreate(KotlinCompilation.TEST_COMPILATION_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun configureCInterops(target: KotlinNativeTarget): Unit = with(target.project) {
|
||||
target.compilations.all { compilation ->
|
||||
createCInteropTasks(compilation)
|
||||
@@ -633,10 +611,44 @@ open class KotlinNativeTargetConfigurator(
|
||||
}
|
||||
}
|
||||
|
||||
override fun configureTarget(target: KotlinNativeTarget) {
|
||||
super.configureTarget(target)
|
||||
configureCInterops(target)
|
||||
warnAboutIncorrectDependencies(target)
|
||||
protected fun configureBinaries(target: KotlinNativeTarget) {
|
||||
val project = target.project
|
||||
target.binaries.all {
|
||||
project.createLinkTask(it)
|
||||
}
|
||||
|
||||
target.binaries.withType(Executable::class.java).all {
|
||||
project.createRunTask(it)
|
||||
}
|
||||
|
||||
// Create binaries for output kinds declared using the old DSL.
|
||||
project.whenEvaluated {
|
||||
target.compilations.all { compilation ->
|
||||
val binaries = target.binaries
|
||||
val konanTarget = compilation.target.konanTarget
|
||||
val name = compilation.name
|
||||
val buildTypes = compilation.buildTypes
|
||||
val availableOutputKinds = compilation.outputKinds.filter { it.availableFor(konanTarget) }
|
||||
|
||||
val configure: NativeBinary.() -> Unit = {
|
||||
this.compilation = compilation
|
||||
linkerOpts.addAll(compilation.linkerOpts)
|
||||
if (this is Executable) {
|
||||
entryPoint = compilation.entryPoint
|
||||
}
|
||||
compilation.binaryTasks[outputKind to buildType] = this
|
||||
}
|
||||
|
||||
for (kind in availableOutputKinds) {
|
||||
when (kind) {
|
||||
NativeOutputKind.EXECUTABLE -> binaries.executable(name, buildTypes, configure)
|
||||
NativeOutputKind.DYNAMIC -> binaries.sharedLib(name, buildTypes, configure)
|
||||
NativeOutputKind.STATIC -> binaries.staticLib(name, buildTypes, configure)
|
||||
NativeOutputKind.FRAMEWORK -> binaries.framework(name, buildTypes, configure)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineConfigurationsForTarget(target: KotlinNativeTarget) {
|
||||
@@ -685,6 +697,7 @@ open class KotlinNativeTargetConfigurator(
|
||||
}
|
||||
}
|
||||
}
|
||||
// endregion.
|
||||
|
||||
object NativeArtifactFormat {
|
||||
const val KLIB = "org.jetbrains.kotlin.klib"
|
||||
@@ -692,6 +705,7 @@ open class KotlinNativeTargetConfigurator(
|
||||
|
||||
companion object {
|
||||
const val INTEROP_GROUP = "interop"
|
||||
const val RUN_GROUP = "run"
|
||||
|
||||
protected fun defineConfigurationsForCInterop(
|
||||
compilation: KotlinNativeCompilation,
|
||||
|
||||
+1
-4
@@ -85,12 +85,9 @@ class KotlinNativeCompilationFactory(
|
||||
KotlinNativeCompilation(target, name).apply {
|
||||
if (name == KotlinCompilation.TEST_COMPILATION_NAME) {
|
||||
friendCompilationName = KotlinCompilation.MAIN_COMPILATION_NAME
|
||||
outputKinds = mutableListOf(NativeOutputKind.EXECUTABLE)
|
||||
buildTypes = mutableListOf(NativeBuildType.DEBUG)
|
||||
isTestCompilation = true
|
||||
} else {
|
||||
buildTypes = mutableListOf(NativeBuildType.DEBUG, NativeBuildType.RELEASE)
|
||||
}
|
||||
buildTypes = mutableListOf(NativeBuildType.DEBUG, NativeBuildType.RELEASE)
|
||||
}
|
||||
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.AbstractExecTask
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinNativeCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
import java.io.File
|
||||
|
||||
// TODO: Extract API.
|
||||
|
||||
// TODO: Should the baseName be a var?
|
||||
|
||||
/**
|
||||
* A base class representing a final binary produced by the Kotlin/Native compiler
|
||||
* @param name - a name of the DSL entity.
|
||||
* @param baseName - a base name for the output binary file. E.g. for baseName foo we produce binaries foo.kexe, libfoo.so, foo.framework.
|
||||
* @param compilation - a compilation used to produce this binary.
|
||||
*
|
||||
*/
|
||||
sealed class NativeBinary(
|
||||
private val name: String,
|
||||
val baseName: String,
|
||||
val buildType: NativeBuildType,
|
||||
var compilation: KotlinNativeCompilation
|
||||
) : Named {
|
||||
|
||||
val target: KotlinNativeTarget
|
||||
get() = compilation.target
|
||||
|
||||
val project: Project
|
||||
get() = target.project
|
||||
|
||||
abstract val outputKind: NativeOutputKind
|
||||
|
||||
// Configuration DSL.
|
||||
var debuggable: Boolean = false
|
||||
var optimized: Boolean = false
|
||||
|
||||
var linkerOpts: MutableList<String> = mutableListOf()
|
||||
|
||||
fun linkerOpts(vararg options: String) {
|
||||
linkerOpts.addAll(options.toList())
|
||||
}
|
||||
|
||||
fun linkerOpts(options: Iterable<String>) {
|
||||
linkerOpts.addAll(options)
|
||||
}
|
||||
|
||||
// Link task access.
|
||||
val linkTaskName: String
|
||||
get() = lowerCamelCaseName("link", name, target.targetName)
|
||||
|
||||
val linkTask: KotlinNativeLink
|
||||
get() = project.tasks.getByName(linkTaskName) as KotlinNativeLink
|
||||
|
||||
// Output access.
|
||||
// TODO: Provide output configurations and integrate them with Gradle Native.
|
||||
val outputDirectory: File = with(project) {
|
||||
val targetSubDirectory = target.disambiguationClassifier?.let { "$it/" }.orEmpty()
|
||||
buildDir.resolve("bin/$targetSubDirectory${this@NativeBinary.name}")
|
||||
}
|
||||
|
||||
val outputFile: File
|
||||
get() = linkTask.outputFile.get()
|
||||
|
||||
// Named implementation.
|
||||
override fun getName(): String = name
|
||||
}
|
||||
|
||||
class Executable constructor(
|
||||
name: String,
|
||||
baseName: String,
|
||||
buildType: NativeBuildType,
|
||||
compilation: KotlinNativeCompilation,
|
||||
internal val isDefaultTestExecutable: Boolean
|
||||
) : NativeBinary(name, baseName, buildType, compilation) {
|
||||
|
||||
constructor(
|
||||
name: String,
|
||||
baseName: String,
|
||||
buildType: NativeBuildType,
|
||||
compilation: KotlinNativeCompilation) : this(name, baseName, buildType, compilation, false)
|
||||
|
||||
override val outputKind: NativeOutputKind
|
||||
get() = NativeOutputKind.EXECUTABLE
|
||||
|
||||
var entryPoint: String? = null
|
||||
|
||||
fun entryPoint(point: String?) {
|
||||
entryPoint = point
|
||||
}
|
||||
|
||||
val runTaskName: String
|
||||
get() = if (isDefaultTestExecutable) {
|
||||
lowerCamelCaseName(compilation.target.targetName, AbstractKotlinTargetConfigurator.testTaskNameSuffix)
|
||||
} else {
|
||||
lowerCamelCaseName("run", name, compilation.target.targetName)
|
||||
}
|
||||
|
||||
// TODO: may make it lateinit (along with linkTasks)?
|
||||
val runTask: AbstractExecTask<*>
|
||||
get() = project.tasks.getByName(runTaskName) as AbstractExecTask<*>
|
||||
|
||||
fun runTask(configure: AbstractExecTask<*>.() -> Unit) {
|
||||
runTask.configure()
|
||||
}
|
||||
|
||||
fun runTask(configure: Closure<*>) {
|
||||
ConfigureUtil.configure(configure, runTask)
|
||||
}
|
||||
}
|
||||
|
||||
class StaticLibrary(
|
||||
name: String,
|
||||
baseName: String,
|
||||
buildType: NativeBuildType,
|
||||
compilation: KotlinNativeCompilation
|
||||
) : NativeBinary(name, baseName, buildType, compilation) {
|
||||
override val outputKind: NativeOutputKind
|
||||
get() = NativeOutputKind.STATIC
|
||||
}
|
||||
|
||||
class SharedLibrary(
|
||||
name: String,
|
||||
baseName: String,
|
||||
buildType: NativeBuildType,
|
||||
compilation: KotlinNativeCompilation
|
||||
) : NativeBinary(name, baseName, buildType, compilation) {
|
||||
override val outputKind: NativeOutputKind
|
||||
get() = NativeOutputKind.DYNAMIC
|
||||
}
|
||||
|
||||
class Framework(
|
||||
name: String,
|
||||
baseName: String,
|
||||
buildType: NativeBuildType,
|
||||
compilation: KotlinNativeCompilation
|
||||
) : NativeBinary(name, baseName, buildType, compilation) {
|
||||
|
||||
override val outputKind: NativeOutputKind
|
||||
get() = NativeOutputKind.FRAMEWORK
|
||||
|
||||
// TODO: Pack task configuration.
|
||||
}
|
||||
|
||||
|
||||
+9
-21
@@ -1,7 +1,6 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.Family
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
@@ -16,51 +15,40 @@ enum class NativeBuildType(val optimized: Boolean, val debuggable: Boolean) : Na
|
||||
DEBUG(false, true);
|
||||
|
||||
override fun getName(): String = name.toLowerCase()
|
||||
|
||||
companion object {
|
||||
val DEFAULT_BUILD_TYPES = setOf(DEBUG, RELEASE)
|
||||
}
|
||||
}
|
||||
|
||||
enum class NativeOutputKind(
|
||||
val compilerOutputKind: CompilerOutputKind,
|
||||
val taskNameClassifier: String,
|
||||
val outputDirectoryName: String = taskNameClassifier,
|
||||
val description: String = taskNameClassifier,
|
||||
val additionalCompilerFlags: List<String> = emptyList(),
|
||||
val runtimeUsageName: String? = null,
|
||||
val linkUsageName: String? = null,
|
||||
val publishable: Boolean = true // Not used yet.
|
||||
val description: String = taskNameClassifier
|
||||
) {
|
||||
EXECUTABLE(
|
||||
CompilerOutputKind.PROGRAM,
|
||||
"executable",
|
||||
description = "an executable",
|
||||
runtimeUsageName = Usage.NATIVE_RUNTIME,
|
||||
publishable = false
|
||||
description = "an executable"
|
||||
),
|
||||
DYNAMIC(
|
||||
CompilerOutputKind.DYNAMIC,
|
||||
"shared",
|
||||
description = "a dynamic library",
|
||||
runtimeUsageName = Usage.NATIVE_RUNTIME,
|
||||
linkUsageName = Usage.NATIVE_LINK,
|
||||
publishable = false
|
||||
description = "a dynamic library"
|
||||
) {
|
||||
override fun availableFor(target: KonanTarget) = target != KonanTarget.WASM32
|
||||
},
|
||||
STATIC(
|
||||
CompilerOutputKind.STATIC,
|
||||
"static",
|
||||
description = "a static library",
|
||||
runtimeUsageName = Usage.NATIVE_RUNTIME,
|
||||
linkUsageName = Usage.NATIVE_LINK,
|
||||
publishable = false
|
||||
description = "a static library"
|
||||
) {
|
||||
override fun availableFor(target: KonanTarget) = target != KonanTarget.WASM32
|
||||
},
|
||||
FRAMEWORK(
|
||||
CompilerOutputKind.FRAMEWORK,
|
||||
"framework",
|
||||
description = "an Objective-C framework",
|
||||
linkUsageName = KotlinNativeUsage.FRAMEWORK,
|
||||
publishable = false
|
||||
description = "a framework"
|
||||
) {
|
||||
override fun availableFor(target: KonanTarget) =
|
||||
target.family == Family.OSX || target.family == Family.IOS
|
||||
|
||||
+7
-8
@@ -15,13 +15,11 @@ import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.dsl.*
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.defaultSourceSetLanguageSettingsChecker
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileCommon
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
import java.io.File
|
||||
@@ -321,7 +319,8 @@ class KotlinNativeCompilation(
|
||||
target.compilations.getByName(it)
|
||||
}
|
||||
|
||||
internal val binaryTasks = mutableMapOf<Pair<NativeOutputKind, NativeBuildType>, KotlinNativeCompile>()
|
||||
// Used only to support the old APIs. TODO: Remove when the old APIs are removed.
|
||||
internal val binaryTasks = mutableMapOf<Pair<NativeOutputKind, NativeBuildType>, NativeBinary>()
|
||||
|
||||
// Native-specific DSL.
|
||||
var extraOpts = mutableListOf<String>()
|
||||
@@ -376,10 +375,9 @@ class KotlinNativeCompilation(
|
||||
}
|
||||
|
||||
// Task accessors.
|
||||
fun findLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink? = binaryTasks[kind to buildType]?.linkTask
|
||||
|
||||
fun findLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeCompile? = binaryTasks[kind to buildType]
|
||||
|
||||
fun getLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeCompile =
|
||||
fun getLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink =
|
||||
findLinkTask(kind, buildType)
|
||||
?: throw IllegalArgumentException("Cannot find a link task for the binary kind '$kind' and the build type '$buildType'")
|
||||
|
||||
@@ -403,6 +401,7 @@ class KotlinNativeCompilation(
|
||||
override val processResourcesTaskName: String
|
||||
get() = disambiguateName("processResources")
|
||||
|
||||
// TODO: Add linkAll task and add a deprecation here.
|
||||
val linkAllTaskName: String
|
||||
get() = lowerCamelCaseName(
|
||||
"link",
|
||||
|
||||
+25
-11
@@ -21,6 +21,7 @@ import org.gradle.util.ConfigureUtil
|
||||
import org.gradle.util.WrapUtil
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||
@@ -191,28 +192,41 @@ class KotlinNativeTarget(
|
||||
attributes.attribute(konanTargetAttribute, konanTarget.name)
|
||||
}
|
||||
|
||||
// TODO: Should binary files be output of a target or a compilation?
|
||||
val binaries = if(isGradleVersionAtLeast(4, 2)) {
|
||||
// Use newInstance to allow accessing binaries by their names in Groovy using the extension mechanism.
|
||||
project.objects.newInstance(KotlinNativeBinaryContainer::class.java, this, WrapUtil.toDomainObjectSet(NativeBinary::class.java))
|
||||
} else {
|
||||
KotlinNativeBinaryContainer(this, WrapUtil.toDomainObjectSet(NativeBinary::class.java))
|
||||
}
|
||||
|
||||
fun binaries(configure: KotlinNativeBinaryContainer.() -> Unit) {
|
||||
binaries.configure()
|
||||
}
|
||||
|
||||
fun binaries(configure: Closure<*>) {
|
||||
ConfigureUtil.configure(configure, binaries)
|
||||
}
|
||||
|
||||
override val artifactsTaskName: String
|
||||
get() = disambiguateName("link")
|
||||
|
||||
override val publishable: Boolean
|
||||
get() = konanTarget.enabledOnCurrentHost
|
||||
|
||||
// User-visible constants
|
||||
val DEBUG = NativeBuildType.DEBUG
|
||||
val RELEASE = NativeBuildType.RELEASE
|
||||
|
||||
val EXECUTABLE = NativeOutputKind.EXECUTABLE
|
||||
val FRAMEWORK = NativeOutputKind.FRAMEWORK
|
||||
val DYNAMIC = NativeOutputKind.DYNAMIC
|
||||
val STATIC = NativeOutputKind.STATIC
|
||||
|
||||
companion object {
|
||||
val konanTargetAttribute = Attribute.of(
|
||||
"org.jetbrains.kotlin.native.target",
|
||||
String::class.java
|
||||
)
|
||||
|
||||
// TODO: Can we do it better?
|
||||
// User-visible constants
|
||||
val DEBUG = NativeBuildType.DEBUG
|
||||
val RELEASE = NativeBuildType.RELEASE
|
||||
|
||||
val EXECUTABLE = NativeOutputKind.EXECUTABLE
|
||||
val FRAMEWORK = NativeOutputKind.FRAMEWORK
|
||||
val DYNAMIC = NativeOutputKind.DYNAMIC
|
||||
val STATIC = NativeOutputKind.STATIC
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinNativeCompile
|
||||
|
||||
internal class DefaultLanguageSettingsBuilder : LanguageSettingsBuilder {
|
||||
private var languageVersionImpl: LanguageVersion? = null
|
||||
@@ -70,7 +70,7 @@ internal class DefaultLanguageSettingsBuilder : LanguageSettingsBuilder {
|
||||
val pluginOptionsTask = compilerPluginOptionsTask.value ?: return null
|
||||
return when (pluginOptionsTask) {
|
||||
is AbstractKotlinCompile<*> -> pluginOptionsTask.pluginOptions
|
||||
is KotlinNativeCompile -> pluginOptionsTask.compilerPluginOptions
|
||||
is AbstractKotlinNativeCompile -> pluginOptionsTask.compilerPluginOptions
|
||||
else -> error("Unexpected task: $pluginOptionsTask")
|
||||
}.arguments
|
||||
}
|
||||
@@ -80,7 +80,7 @@ internal class DefaultLanguageSettingsBuilder : LanguageSettingsBuilder {
|
||||
val pluginClasspathTask = compilerPluginOptionsTask.value ?: return null
|
||||
return when (pluginClasspathTask) {
|
||||
is AbstractKotlinCompile<*> -> pluginClasspathTask.pluginClasspath
|
||||
is KotlinNativeCompile -> pluginClasspathTask.compilerPluginClasspath ?: pluginClasspathTask.project.files()
|
||||
is AbstractKotlinNativeCompile -> pluginClasspathTask.compilerPluginClasspath ?: pluginClasspathTask.project.files()
|
||||
else -> error("Unexpected task: $pluginClasspathTask")
|
||||
}
|
||||
}
|
||||
|
||||
+85
-28
@@ -16,10 +16,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultCInteropSettings
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isMainCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind.*
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
@@ -81,20 +78,26 @@ private fun FileCollection.filterOutPublishableInteropLibs(project: Project): Fi
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
open class KotlinNativeCompile : AbstractCompile(), KotlinCompile<KotlinCommonOptions> {
|
||||
abstract class AbstractKotlinNativeCompile : AbstractCompile(), KotlinCompile<KotlinCommonOptions> {
|
||||
|
||||
init {
|
||||
sourceCompatibility = "1.6"
|
||||
targetCompatibility = "1.6"
|
||||
}
|
||||
|
||||
@Internal
|
||||
lateinit var compilation: KotlinNativeCompilation
|
||||
abstract val compilation: KotlinNativeCompilation
|
||||
|
||||
// region inputs/outputs
|
||||
@Input
|
||||
lateinit var outputKind: CompilerOutputKind
|
||||
@get:Input
|
||||
abstract val outputKind: CompilerOutputKind
|
||||
|
||||
@get:Input
|
||||
abstract val optimized: Boolean
|
||||
|
||||
@get:Input
|
||||
abstract val debuggable: Boolean
|
||||
|
||||
abstract val baseName: String
|
||||
|
||||
// Inputs and outputs
|
||||
@InputFiles
|
||||
@@ -116,23 +119,13 @@ open class KotlinNativeCompile : AbstractCompile(), KotlinCompile<KotlinCommonOp
|
||||
throw UnsupportedOperationException("Setting classpath directly is unsupported.")
|
||||
}
|
||||
|
||||
@Input
|
||||
var optimized = false
|
||||
@Input
|
||||
var debuggable = true
|
||||
|
||||
val processTests
|
||||
@Input get() = compilation.isTestCompilation
|
||||
|
||||
val target: String
|
||||
@Input get() = compilation.target.konanTarget.name
|
||||
|
||||
val entryPoint: String?
|
||||
@Optional @Input get() = compilation.entryPoint
|
||||
|
||||
val linkerOpts: List<String>
|
||||
@Input get() = compilation.linkerOpts
|
||||
|
||||
// TODO: rework.
|
||||
val additionalCompilerOptions: Collection<String>
|
||||
@Input get() = compilation.extraOpts
|
||||
|
||||
@@ -163,13 +156,14 @@ open class KotlinNativeCompile : AbstractCompile(), KotlinCompile<KotlinCommonOp
|
||||
set(value) { languageSettings!!.apiVersion = value }
|
||||
|
||||
override var languageVersion: String?
|
||||
get() = this@KotlinNativeCompile.languageVersion
|
||||
get() = this@AbstractKotlinNativeCompile.languageVersion
|
||||
set(value) { languageSettings!!.languageVersion = value }
|
||||
|
||||
override var allWarningsAsErrors: Boolean = false
|
||||
override var suppressWarnings: Boolean = false
|
||||
override var verbose: Boolean = false
|
||||
|
||||
// TODO: deprecate extraOptions because now we have a uniform way to access these parameters.
|
||||
// Delegate for compilations's extra options.
|
||||
override var freeCompilerArgs: List<String>
|
||||
get() = compilation.extraOpts
|
||||
@@ -202,7 +196,6 @@ open class KotlinNativeCompile : AbstractCompile(), KotlinCompile<KotlinCommonOp
|
||||
|
||||
val prefix = outputKind.prefix(konanTarget)
|
||||
val suffix = outputKind.suffix(konanTarget)
|
||||
val baseName = if (compilation.isMainCompilation) project.name else compilation.name
|
||||
var filename = "$prefix$baseName$suffix"
|
||||
if (outputKind in listOf(FRAMEWORK, STATIC, DYNAMIC) || outputKind == PROGRAM && konanTarget == KonanTarget.WASM32) {
|
||||
filename = filename.replace('-', '_')
|
||||
@@ -228,7 +221,7 @@ open class KotlinNativeCompile : AbstractCompile(), KotlinCompile<KotlinCommonOp
|
||||
val defaultSerializedCompilerArguments: List<String>
|
||||
@Internal get() = buildCommonArgs(true)
|
||||
|
||||
private fun buildCommonArgs(defaultsOnly: Boolean = false) = mutableListOf<String>().apply {
|
||||
private fun buildCommonArgs(defaultsOnly: Boolean = false): List<String> = mutableListOf<String>().apply {
|
||||
|
||||
add("-Xmulti-platform")
|
||||
|
||||
@@ -264,7 +257,7 @@ open class KotlinNativeCompile : AbstractCompile(), KotlinCompile<KotlinCommonOp
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildArgs(defaultsOnly: Boolean = false) = mutableListOf<String>().apply {
|
||||
protected open fun buildArgs(defaultsOnly: Boolean = false): List<String> = mutableListOf<String>().apply {
|
||||
addKey("-opt", optimized)
|
||||
addKey("-g", debuggable)
|
||||
addKey("-ea", debuggable)
|
||||
@@ -272,7 +265,6 @@ open class KotlinNativeCompile : AbstractCompile(), KotlinCompile<KotlinCommonOp
|
||||
|
||||
addArg("-target", target)
|
||||
addArg("-p", outputKind.name.toLowerCase())
|
||||
addArgIfNotNull("-entry", entryPoint)
|
||||
|
||||
if (!defaultsOnly) {
|
||||
addArg("-o", outputFile.get().absolutePath)
|
||||
@@ -291,8 +283,6 @@ open class KotlinNativeCompile : AbstractCompile(), KotlinCompile<KotlinCommonOp
|
||||
addArg("-friend-modules", friends.map { it.absolutePath }.joinToString(File.pathSeparator))
|
||||
}
|
||||
|
||||
addListArg("-linker-options", linkerOpts)
|
||||
|
||||
addAll(buildCommonArgs(defaultsOnly))
|
||||
|
||||
// Sources.
|
||||
@@ -310,6 +300,73 @@ open class KotlinNativeCompile : AbstractCompile(), KotlinCompile<KotlinCommonOp
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A task producing a klibrary from a compilation.
|
||||
*/
|
||||
open class KotlinNativeCompile : AbstractKotlinNativeCompile() {
|
||||
@Internal
|
||||
override lateinit var compilation: KotlinNativeCompilation
|
||||
|
||||
@get:Input
|
||||
override val outputKind = LIBRARY
|
||||
|
||||
@get:Input
|
||||
override val optimized = false
|
||||
|
||||
@get:Input
|
||||
override val debuggable = true
|
||||
|
||||
@get:Internal
|
||||
override val baseName: String
|
||||
get() = if (compilation.isMainCompilation) project.name else compilation.name
|
||||
}
|
||||
|
||||
/**
|
||||
* A task producing a final binary from a compilation.
|
||||
*/
|
||||
open class KotlinNativeLink : AbstractKotlinNativeCompile() {
|
||||
@Internal
|
||||
lateinit var binary: NativeBinary
|
||||
|
||||
@get:Internal
|
||||
override val compilation: KotlinNativeCompilation
|
||||
get() = binary.compilation
|
||||
|
||||
@get:Input
|
||||
override val outputKind: CompilerOutputKind
|
||||
get() = binary.outputKind.compilerOutputKind
|
||||
|
||||
@get:Input
|
||||
override val optimized: Boolean
|
||||
get() = binary.optimized
|
||||
|
||||
@get:Input
|
||||
override val debuggable: Boolean
|
||||
get() = binary.debuggable
|
||||
|
||||
@get:Internal
|
||||
override val baseName: String
|
||||
get() = binary.baseName
|
||||
|
||||
@get:Optional
|
||||
@get:Input
|
||||
val entryPoint: String?
|
||||
get() = (binary as? Executable)?.entryPoint
|
||||
|
||||
@get:Input
|
||||
val linkerOpts: List<String>
|
||||
get() = binary.linkerOpts
|
||||
|
||||
override fun buildArgs(defaultsOnly: Boolean): List<String> {
|
||||
val superArgs = super.buildArgs(defaultsOnly)
|
||||
return mutableListOf<String>().apply {
|
||||
addAll(superArgs)
|
||||
addArgIfNotNull("-entry", entryPoint)
|
||||
addListArg("-linker-options", linkerOpts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class CInteropProcess : DefaultTask() {
|
||||
|
||||
@Internal
|
||||
|
||||
Reference in New Issue
Block a user