Extract kotlin artifacts public API.

This commit is contained in:
konstantin.tskhovrebov
2022-04-12 10:06:35 +02:00
committed by Space
parent 19dc91135c
commit 3085f6bacf
9 changed files with 424 additions and 328 deletions
@@ -0,0 +1,137 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.mpp.BitcodeEmbeddingMode
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.konan.target.KonanTarget
interface KotlinArtifact : Named, ExtensionAware {
val artifactName: String
val modules: Set<Any>
val taskName: String
fun registerAssembleTask(project: Project)
}
interface KotlinNativeArtifact : KotlinArtifact {
val modes: Set<NativeBuildType>
val isStatic: Boolean
val linkerOptions: List<String>
val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit
val binaryOptions: Map<String, String>
}
interface KotlinNativeLibrary : KotlinNativeArtifact {
val target: KonanTarget
}
interface KotlinNativeFramework : KotlinNativeArtifact {
val target: KonanTarget
val embedBitcode: BitcodeEmbeddingMode?
}
interface KotlinNativeFatFramework : KotlinNativeArtifact {
val targets: Set<KonanTarget>
val embedBitcode: BitcodeEmbeddingMode?
}
interface KotlinNativeXCFramework : KotlinNativeArtifact {
val targets: Set<KonanTarget>
val embedBitcode: BitcodeEmbeddingMode?
}
interface KotlinArtifactConfig {
val artifactName: String
val modules: Set<Any>
fun setModules(vararg project: Any)
fun addModule(project: Any)
fun createArtifact(extensions: ExtensionAware): KotlinArtifact
}
interface KotlinNativeArtifactConfig : KotlinArtifactConfig {
var modes: Set<NativeBuildType>
fun modes(vararg modes: NativeBuildType)
var isStatic: Boolean
var linkerOptions: List<String>
fun kotlinOptions(fn: Action<KotlinCommonToolOptions>)
fun binaryOption(name: String, value: String)
}
interface KotlinNativeLibraryConfig : KotlinNativeArtifactConfig {
var target: KonanTarget
}
interface KotlinNativeFrameworkConfig : KotlinNativeArtifactConfig {
var target: KonanTarget
var embedBitcode: BitcodeEmbeddingMode?
}
interface KotlinNativeFatFrameworkConfig : KotlinNativeArtifactConfig {
var targets: Set<KonanTarget>
fun targets(vararg targets: KonanTarget)
var embedBitcode: BitcodeEmbeddingMode?
}
interface KotlinNativeXCFrameworkConfig : KotlinNativeArtifactConfig {
var targets: Set<KonanTarget>
fun targets(vararg targets: KonanTarget)
var embedBitcode: BitcodeEmbeddingMode?
}
interface KotlinArtifactsExtension {
//Extending by external plugins:
//
//project.kotlinArtifactsExtension.apply {
// artifactConfigs.all {
// //add custom extension to artifact config DSL
// (it as ExtensionAware).extensions.create("myConfig", Config::class.java)
// }
// artifacts.all {
// val config = it.extensions.findByName("myConfig") as Config
// //configure additional tasks, etc
// //here we can use artifact parameters
// }
//}
val artifactConfigs: DomainObjectSet<KotlinArtifactConfig>
val artifacts: NamedDomainObjectSet<KotlinArtifact>
val Native: KotlinNativeArtifactDSL
}
interface KotlinNativeArtifactDSL {
@RequiresOptIn(
message = "This API is experimental. It may be changed in the future.",
level = RequiresOptIn.Level.WARNING
)
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.FUNCTION)
annotation class ExperimentalArtifactDsl
@ExperimentalArtifactDsl
fun Library(name: String, configure: Action<KotlinNativeLibraryConfig>)
@ExperimentalArtifactDsl
fun Library(configure: Action<KotlinNativeLibraryConfig>)
@ExperimentalArtifactDsl
fun Framework(name: String, configure: Action<KotlinNativeFrameworkConfig>)
@ExperimentalArtifactDsl
fun Framework(configure: Action<KotlinNativeFrameworkConfig>)
@ExperimentalArtifactDsl
fun FatFramework(name: String, configure: Action<KotlinNativeFatFrameworkConfig>)
@ExperimentalArtifactDsl
fun FatFramework(configure: Action<KotlinNativeFatFrameworkConfig>)
@ExperimentalArtifactDsl
fun XCFramework(name: String, configure: Action<KotlinNativeXCFrameworkConfig>)
@ExperimentalArtifactDsl
fun XCFramework(configure: Action<KotlinNativeXCFrameworkConfig>)
}
@@ -10,10 +10,10 @@ kotlin {
} }
kotlinArtifacts { kotlinArtifacts {
Native.Library("groolib") { it.native.Library("groolib") {
modes(DEBUG) modes(DEBUG)
target = iosX64 target = iosX64
isStatic = false it.static = false
linkerOptions = ["a", "b"] linkerOptions = ["a", "b"]
kotlinOptions { kotlinOptions {
verbose = true verbose = true
@@ -25,24 +25,24 @@ kotlinArtifacts {
project(":lib") project(":lib")
) )
} }
Native.Framework("grooframe") { it.native.Framework("grooframe") {
modes(DEBUG, RELEASE) modes(DEBUG, RELEASE)
target = iosArm64 target = iosArm64
isStatic = false it.static = false
embedBitcode = EmbedBitcodeMode.MARKER embedBitcode = EmbedBitcodeMode.MARKER
kotlinOptions { kotlinOptions {
verbose = true verbose = true
} }
addModule(project(":shared")) addModule(project(":shared"))
} }
Native.FatFramework("groofatframe") { it.native.FatFramework("groofatframe") {
targets(iosX64, iosSimulatorArm64) targets(iosX64, iosSimulatorArm64)
embedBitcode = EmbedBitcodeMode.DISABLE embedBitcode = EmbedBitcodeMode.DISABLE
kotlinOptions { kotlinOptions {
suppressWarnings = true suppressWarnings = true
} }
} }
Native.XCFramework { it.native.XCFramework {
targets(iosX64, iosArm64, iosSimulatorArm64) targets(iosX64, iosArm64, iosSimulatorArm64)
} }
} }
@@ -6,11 +6,11 @@
package org.jetbrains.kotlin.gradle.targets.native.tasks.artifact package org.jetbrains.kotlin.gradle.targets.native.tasks.artifact
import org.gradle.api.Action import org.gradle.api.Action
import org.gradle.api.Named
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.attributes.Usage import org.gradle.api.attributes.Usage
import org.gradle.api.plugins.ExtensionAware import org.jetbrains.kotlin.gradle.dsl.KotlinArtifactConfig
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeArtifactConfig
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
@@ -19,66 +19,47 @@ import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.target.presetName import org.jetbrains.kotlin.konan.target.presetName
abstract class KotlinArtifactConfig( abstract class KotlinArtifactConfigImpl(
val artifactName: String override val artifactName: String
) { ) : KotlinArtifactConfig {
internal val modules = mutableSetOf<Any>() override val modules = mutableSetOf<Any>()
fun setModules(vararg project: Any) { override fun setModules(vararg project: Any) {
modules.clear() modules.clear()
modules.addAll(project) modules.addAll(project)
} }
fun addModule(project: Any) { override fun addModule(project: Any) {
modules.add(project) modules.add(project)
} }
abstract fun createArtifact(project: Project, extensions: ExtensionAware): KotlinArtifact protected open fun validate() {
check(modules.isNotEmpty()) {
"Native artifact '$artifactName' wasn't configured because it requires at least one module for linking"
}
}
} }
interface KotlinArtifact : Named, ExtensionAware { abstract class KotlinNativeArtifactConfigImpl(artifactName: String) : KotlinArtifactConfigImpl(artifactName), KotlinNativeArtifactConfig {
val project: Project override var modes: Set<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES
val artifactName: String override fun modes(vararg modes: NativeBuildType) {
val modules: Set<Any>
val taskName: String get() = lowerCamelCaseName("assemble", name)
fun validate()
fun registerAssembleTask()
}
abstract class KotlinNativeArtifactConfig(artifactName: String) : KotlinArtifactConfig(artifactName) {
var modes: Set<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES
fun modes(vararg modes: NativeBuildType) {
this.modes = modes.toSet() this.modes = modes.toSet()
} }
@JvmField override var isStatic: Boolean = false
var isStatic: Boolean = false override var linkerOptions: List<String> = emptyList()
@JvmField
var linkerOptions: List<String> = emptyList()
internal var kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit = {} internal var kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit = {}
fun kotlinOptions(fn: Action<KotlinCommonToolOptions>) { override fun kotlinOptions(fn: Action<KotlinCommonToolOptions>) {
kotlinOptionsFn = fn::execute kotlinOptionsFn = fn::execute
} }
internal val binaryOptions: MutableMap<String, String> = mutableMapOf() internal val binaryOptions: MutableMap<String, String> = mutableMapOf()
fun binaryOption(name: String, value: String) { override fun binaryOption(name: String, value: String) {
binaryOptions[name] = value binaryOptions[name] = value
} }
}
interface KotlinNativeArtifact : KotlinArtifact {
val modes: Set<NativeBuildType>
val isStatic: Boolean
val linkerOptions: List<String>
val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit
val binaryOptions: Map<String, String>
override fun validate() { override fun validate() {
check(modules.isNotEmpty()) { super.validate()
"Native artifact '$artifactName' wasn't configured because it requires at least one module for linking"
}
check(modes.isNotEmpty()) { check(modes.isNotEmpty()) {
"Native artifact '$artifactName' wasn't configured because it requires at least one build type in modes" "Native artifact '$artifactName' wasn't configured because it requires at least one build type in modes"
} }
@@ -6,118 +6,30 @@
package org.jetbrains.kotlin.gradle.targets.native.tasks.artifact package org.jetbrains.kotlin.gradle.targets.native.tasks.artifact
import org.gradle.api.Action import org.gradle.api.Action
import org.gradle.api.DomainObjectSet
import org.gradle.api.NamedDomainObjectSet
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionAware
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.gradle.utils.castIsolatedKotlinPluginClassLoaderAware import org.jetbrains.kotlin.gradle.utils.castIsolatedKotlinPluginClassLoaderAware
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
import javax.inject.Inject import javax.inject.Inject
//Groovy script DSL
abstract class NativeArtifacts @Inject constructor(private val project: Project) {
companion object {
private val UNSAFE_NAME_SYMBOLS = """\W""".toRegex()
}
@RequiresOptIn(
message = "This API is experimental. It may be changed in the future.",
level = RequiresOptIn.Level.WARNING
)
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.FUNCTION)
annotation class ExperimentalArtifactDsl
@ExperimentalArtifactDsl
fun Library(name: String, configure: Action<KotlinNativeLibraryConfig>) {
addKotlinArtifact(name, configure)
}
@ExperimentalArtifactDsl
fun Library(configure: Action<KotlinNativeLibraryConfig>) {
addKotlinArtifact(configure)
}
@ExperimentalArtifactDsl
fun Framework(name: String, configure: Action<KotlinNativeFrameworkConfig>) {
addKotlinArtifact(name, configure)
}
@ExperimentalArtifactDsl
fun Framework(configure: Action<KotlinNativeFrameworkConfig>) {
addKotlinArtifact(configure)
}
@ExperimentalArtifactDsl
fun FatFramework(name: String, configure: Action<KotlinNativeFatFrameworkConfig>) {
addKotlinArtifact(name, configure)
}
@ExperimentalArtifactDsl
fun FatFramework(configure: Action<KotlinNativeFatFrameworkConfig>) {
addKotlinArtifact(configure)
}
@ExperimentalArtifactDsl
fun XCFramework(name: String, configure: Action<KotlinNativeXCFrameworkConfig>) {
addKotlinArtifact(name, configure)
}
@ExperimentalArtifactDsl
fun XCFramework(configure: Action<KotlinNativeXCFrameworkConfig>) {
addKotlinArtifact(configure)
}
private inline fun <reified T : KotlinArtifactConfig> addKotlinArtifact(configure: Action<T>) {
addKotlinArtifact(project.name.replace(UNSAFE_NAME_SYMBOLS, "_"), configure)
}
private inline fun <reified T : KotlinArtifactConfig> addKotlinArtifact(name: String, configure: Action<T>) {
//create via newInstance for extensibility
val config: T = project.objects.newInstance(T::class.java, name)
project.kotlinArtifactsExtension.artifactConfigs.add(config)
//current project is added by default
config.addModule(project)
//apply user configuration
configure.execute(config)
//create immutable artifact object
val artifact = config.createArtifact(project, config as ExtensionAware)
val isAdded = project.kotlinArtifactsExtension.artifacts.add(artifact)
if (!isAdded) {
error("Kotlin artifact with name '${artifact.name}' is already exists! Change the name, please!")
}
}
}
//Groovy script DSL
private const val KOTLIN_ARTIFACTS_EXTENSION_NAME = "kotlinArtifacts" private const val KOTLIN_ARTIFACTS_EXTENSION_NAME = "kotlinArtifacts"
internal fun Project.registerKotlinArtifactsExtension() { internal fun Project.registerKotlinArtifactsExtension() {
val kotlinArtifactsExt = objects.newInstance(KotlinArtifactsExtension::class.java, this) val kotlinArtifactsExt = objects.newInstance(KotlinArtifactsExtensionImpl::class.java, this)
extensions.add(KOTLIN_ARTIFACTS_EXTENSION_NAME, kotlinArtifactsExt) extensions.add(KOTLIN_ARTIFACTS_EXTENSION_NAME, kotlinArtifactsExt)
kotlinArtifactsExt.artifacts.all { it.registerAssembleTask() } kotlinArtifactsExt.artifacts.all { it.registerAssembleTask(this) }
} }
internal val Project.kotlinArtifactsExtension: KotlinArtifactsExtension val Project.kotlinArtifactsExtension: KotlinArtifactsExtension
get() = extensions.getByName(KOTLIN_ARTIFACTS_EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware() get() = extensions.getByName(KOTLIN_ARTIFACTS_EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware()
abstract class KotlinArtifactsExtension @Inject constructor(project: Project) { abstract class KotlinArtifactsExtensionImpl @Inject constructor(project: Project) : KotlinArtifactsExtension {
//Extending by external plugins: override val artifactConfigs = project.objects.domainObjectSet(KotlinArtifactConfig::class.java)
// override val artifacts = project.objects.namedDomainObjectSet(KotlinArtifact::class.java)
//project.kotlinArtifactsExtension.apply { override val Native = project.objects.newInstance(KotlinNativeArtifactDSLImpl::class.java, project)
// artifactConfigs.all {
// //add custom extension to artifact config DSL
// (it as ExtensionAware).extensions.create("myConfig", Config::class.java)
// }
// artifacts.all {
// val config = it.extensions.findByName("myConfig") as Config
// //configure additional tasks, etc
// //here we can use artifact parameters
// }
//}
val artifactConfigs = project.objects.domainObjectSet(KotlinArtifactConfig::class.java)
val artifacts = project.objects.namedDomainObjectSet(KotlinArtifact::class.java)
val DEBUG = NativeBuildType.DEBUG val DEBUG = NativeBuildType.DEBUG
val RELEASE = NativeBuildType.RELEASE val RELEASE = NativeBuildType.RELEASE
@@ -128,9 +40,6 @@ abstract class KotlinArtifactsExtension @Inject constructor(project: Project) {
val MARKER = org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode.MARKER val MARKER = org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode.MARKER
} }
@JvmField
val Native = project.objects.newInstance(NativeArtifacts::class.java, project)
@JvmField @JvmField
val EmbedBitcodeMode = BitcodeEmbeddingModeDsl() val EmbedBitcodeMode = BitcodeEmbeddingModeDsl()
@@ -160,4 +69,65 @@ abstract class KotlinArtifactsExtension @Inject constructor(project: Project) {
val linuxMips32 = KonanTarget.LINUX_MIPS32 val linuxMips32 = KonanTarget.LINUX_MIPS32
val linuxMipsel32 = KonanTarget.LINUX_MIPSEL32 val linuxMipsel32 = KonanTarget.LINUX_MIPSEL32
val wasm32 = KonanTarget.WASM32 val wasm32 = KonanTarget.WASM32
}
abstract class KotlinNativeArtifactDSLImpl @Inject constructor(private val project: Project) : KotlinNativeArtifactDSL {
companion object {
private val UNSAFE_NAME_SYMBOLS = """\W""".toRegex()
}
override fun Library(name: String, configure: Action<KotlinNativeLibraryConfig>) {
addKotlinArtifact<KotlinNativeLibraryConfigImpl>(name, configure)
}
override fun Library(configure: Action<KotlinNativeLibraryConfig>) {
addKotlinArtifact<KotlinNativeLibraryConfigImpl>(configure)
}
override fun Framework(name: String, configure: Action<KotlinNativeFrameworkConfig>) {
addKotlinArtifact<KotlinNativeFrameworkConfigImpl>(name, configure)
}
override fun Framework(configure: Action<KotlinNativeFrameworkConfig>) {
addKotlinArtifact<KotlinNativeFrameworkConfigImpl>(configure)
}
override fun FatFramework(name: String, configure: Action<KotlinNativeFatFrameworkConfig>) {
addKotlinArtifact<KotlinNativeFatFrameworkConfigImpl>(name, configure)
}
override fun FatFramework(configure: Action<KotlinNativeFatFrameworkConfig>) {
addKotlinArtifact<KotlinNativeFatFrameworkConfigImpl>(configure)
}
override fun XCFramework(name: String, configure: Action<KotlinNativeXCFrameworkConfig>) {
addKotlinArtifact<KotlinNativeXCFrameworkConfigImpl>(name, configure)
}
override fun XCFramework(configure: Action<KotlinNativeXCFrameworkConfig>) {
addKotlinArtifact<KotlinNativeXCFrameworkConfigImpl>(configure)
}
private inline fun <reified T : KotlinArtifactConfig> addKotlinArtifact(configure: Action<in T>) {
addKotlinArtifact(project.name.replace(UNSAFE_NAME_SYMBOLS, "_"), configure)
}
private inline fun <reified T : KotlinArtifactConfig> addKotlinArtifact(name: String, configure: Action<in T>) {
//create via newInstance for extensibility
val config: T = project.objects.newInstance(T::class.java, name)
project.kotlinArtifactsExtension.artifactConfigs.add(config)
//current project is added by default
config.addModule(project)
//apply user configuration
configure.execute(config)
//create immutable artifact object
val artifact = config.createArtifact(config as ExtensionAware)
val isAdded = project.kotlinArtifactsExtension.artifacts.add(artifact)
if (!isAdded) {
error("Kotlin artifact '${artifact.name}' is already exists! Change the name, please!")
}
}
} }
@@ -10,6 +10,8 @@ import org.gradle.api.Task
import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionAware
import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeFatFramework
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeFatFrameworkConfig
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind
@@ -22,49 +24,18 @@ import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.util.visibleName import org.jetbrains.kotlin.konan.util.visibleName
import javax.inject.Inject import javax.inject.Inject
abstract class KotlinNativeFatFrameworkConfig @Inject constructor( abstract class KotlinNativeFatFrameworkConfigImpl @Inject constructor(artifactName: String) :
artifactName: String KotlinNativeArtifactConfigImpl(artifactName), KotlinNativeFatFrameworkConfig {
) : KotlinNativeArtifactConfig(artifactName) { override var targets: Set<KonanTarget> = emptySet()
var targets: Set<KonanTarget> = emptySet() override fun targets(vararg targets: KonanTarget) {
fun targets(vararg targets: KonanTarget) {
this.targets = targets.toSet() this.targets = targets.toSet()
} }
var embedBitcode: BitcodeEmbeddingMode? = null override var embedBitcode: BitcodeEmbeddingMode? = null
override fun createArtifact(project: Project, extensions: ExtensionAware) = KotlinNativeFatFramework(
project,
artifactName,
modules,
modes,
isStatic,
linkerOptions,
kotlinOptionsFn,
binaryOptions,
targets,
embedBitcode,
extensions
)
}
class KotlinNativeFatFramework(
override val project: Project,
override val artifactName: String,
override val modules: Set<Any>,
override val modes: Set<NativeBuildType>,
override val isStatic: Boolean,
override val linkerOptions: List<String>,
override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit,
override val binaryOptions: Map<String, String>,
val targets: Set<KonanTarget>,
val embedBitcode: BitcodeEmbeddingMode?,
extensions: ExtensionAware
) : KotlinNativeArtifact, ExtensionAware by extensions {
private val kind = NativeOutputKind.FRAMEWORK
override fun getName() = lowerCamelCaseName(artifactName, "FatFramework")
override fun validate() { override fun validate() {
super.validate() super.validate()
val kind = NativeOutputKind.FRAMEWORK
check(targets.isNotEmpty()) { check(targets.isNotEmpty()) {
"Native artifact '$artifactName' wasn't configured because it requires at least one target" "Native artifact '$artifactName' wasn't configured because it requires at least one target"
} }
@@ -74,8 +45,39 @@ class KotlinNativeFatFramework(
} }
} }
override fun registerAssembleTask() { override fun createArtifact(extensions: ExtensionAware): KotlinNativeFatFrameworkImpl {
validate() validate()
return KotlinNativeFatFrameworkImpl(
artifactName = artifactName,
modules = modules,
modes = modes,
isStatic = isStatic,
linkerOptions = linkerOptions,
kotlinOptionsFn = kotlinOptionsFn,
binaryOptions = binaryOptions,
targets = targets,
embedBitcode = embedBitcode,
extensions = extensions
)
}
}
class KotlinNativeFatFrameworkImpl(
override val artifactName: String,
override val modules: Set<Any>,
override val modes: Set<NativeBuildType>,
override val isStatic: Boolean,
override val linkerOptions: List<String>,
override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit,
override val binaryOptions: Map<String, String>,
override val targets: Set<KonanTarget>,
override val embedBitcode: BitcodeEmbeddingMode?,
extensions: ExtensionAware
) : KotlinNativeFatFramework, ExtensionAware by extensions {
override fun getName() = lowerCamelCaseName(artifactName, "FatFramework")
override val taskName = lowerCamelCaseName("assemble", name)
override fun registerAssembleTask(project: Project) {
val parentTask = project.registerTask<Task>(taskName) { val parentTask = project.registerTask<Task>(taskName) {
it.group = "build" it.group = "build"
it.description = "Assemble all types of registered '$artifactName' FatFramework" it.description = "Assemble all types of registered '$artifactName' FatFramework"
@@ -96,15 +98,15 @@ class KotlinNativeFatFramework(
val librariesConfigurationName = project.registerLibsDependencies(target, artifactName + nameSuffix, modules) val librariesConfigurationName = project.registerLibsDependencies(target, artifactName + nameSuffix, modules)
val exportConfigurationName = project.registerExportDependencies(target, artifactName + nameSuffix, modules) val exportConfigurationName = project.registerExportDependencies(target, artifactName + nameSuffix, modules)
val targetTask = registerLinkFrameworkTask( val targetTask = registerLinkFrameworkTask(
project, project = project,
artifactName, name = artifactName,
target, target = target,
buildType, buildType = buildType,
librariesConfigurationName, librariesConfigurationName = librariesConfigurationName,
exportConfigurationName, exportConfigurationName = exportConfigurationName,
embedBitcode, embedBitcode = embedBitcode,
"${artifactName}FatFrameworkTemp", outDirName = "${artifactName}FatFrameworkTemp",
nameSuffix taskNameSuffix = nameSuffix
) )
fatTask.dependsOn(targetTask) fatTask.dependsOn(targetTask)
val frameworkFileProvider = targetTask.map { it.outputFile } val frameworkFileProvider = targetTask.map { it.outputFile }
@@ -12,6 +12,9 @@ import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.TaskProvider
import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeArtifact
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeFramework
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeFrameworkConfig
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind
@@ -24,29 +27,35 @@ import org.jetbrains.kotlin.konan.target.presetName
import org.jetbrains.kotlin.konan.util.visibleName import org.jetbrains.kotlin.konan.util.visibleName
import javax.inject.Inject import javax.inject.Inject
abstract class KotlinNativeFrameworkConfig @Inject constructor( abstract class KotlinNativeFrameworkConfigImpl @Inject constructor(artifactName: String) :
artifactName: String KotlinNativeArtifactConfigImpl(artifactName), KotlinNativeFrameworkConfig {
) : KotlinNativeArtifactConfig(artifactName) {
abstract var target: KonanTarget
var embedBitcode: BitcodeEmbeddingMode? = null
override fun createArtifact(project: Project, extensions: ExtensionAware) = KotlinNativeFramework( override fun validate() {
project, super.validate()
artifactName, val kind = NativeOutputKind.FRAMEWORK
modules, check(kind.availableFor(target)) {
modes, "Native artifact '$artifactName' wasn't configured because ${kind.description} is not available for ${target.visibleName}"
isStatic, }
linkerOptions, }
kotlinOptionsFn,
binaryOptions, override fun createArtifact(extensions: ExtensionAware): KotlinNativeFrameworkImpl {
target, validate()
embedBitcode, return KotlinNativeFrameworkImpl(
extensions artifactName = artifactName,
) modules = modules,
modes = modes,
isStatic = isStatic,
linkerOptions = linkerOptions,
kotlinOptionsFn = kotlinOptionsFn,
binaryOptions = binaryOptions,
target = target,
embedBitcode = embedBitcode,
extensions = extensions
)
}
} }
class KotlinNativeFramework( class KotlinNativeFrameworkImpl(
override val project: Project,
override val artifactName: String, override val artifactName: String,
override val modules: Set<Any>, override val modules: Set<Any>,
override val modes: Set<NativeBuildType>, override val modes: Set<NativeBuildType>,
@@ -54,22 +63,15 @@ class KotlinNativeFramework(
override val linkerOptions: List<String>, override val linkerOptions: List<String>,
override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit, override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit,
override val binaryOptions: Map<String, String>, override val binaryOptions: Map<String, String>,
val target: KonanTarget, override val target: KonanTarget,
val embedBitcode: BitcodeEmbeddingMode?, override val embedBitcode: BitcodeEmbeddingMode?,
extensions: ExtensionAware extensions: ExtensionAware
) : KotlinNativeArtifact, ExtensionAware by extensions { ) : KotlinNativeFramework, ExtensionAware by extensions {
private val kind = NativeOutputKind.FRAMEWORK private val kind = NativeOutputKind.FRAMEWORK
override fun getName() = lowerCamelCaseName(artifactName, kind.taskNameClassifier, target.presetName) override fun getName() = lowerCamelCaseName(artifactName, kind.taskNameClassifier, target.presetName)
override val taskName = lowerCamelCaseName("assemble", name)
override fun validate() { override fun registerAssembleTask(project: Project) {
super.validate()
check(kind.availableFor(target)) {
"Native artifact '$artifactName' wasn't configured because ${kind.description} is not available for ${target.visibleName}"
}
}
override fun registerAssembleTask() {
validate()
val resultTask = project.registerTask<Task>(taskName) { task -> val resultTask = project.registerTask<Task>(taskName) { task ->
task.group = BasePlugin.BUILD_GROUP task.group = BasePlugin.BUILD_GROUP
task.description = "Assemble ${kind.description} '$artifactName' for ${target.visibleName}." task.description = "Assemble ${kind.description} '$artifactName' for ${target.visibleName}."
@@ -80,13 +82,13 @@ class KotlinNativeFramework(
val exportConfigurationName = project.registerExportDependencies(target, artifactName, modules) val exportConfigurationName = project.registerExportDependencies(target, artifactName, modules)
modes.forEach { buildType -> modes.forEach { buildType ->
val targetTask = registerLinkFrameworkTask( val targetTask = registerLinkFrameworkTask(
project, project = project,
artifactName, name = artifactName,
target, target = target,
buildType, buildType = buildType,
librariesConfigurationName, librariesConfigurationName = librariesConfigurationName,
exportConfigurationName, exportConfigurationName = exportConfigurationName,
embedBitcode embedBitcode = embedBitcode
) )
resultTask.dependsOn(targetTask) resultTask.dependsOn(targetTask)
} }
@@ -11,6 +11,8 @@ import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionAware
import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeLibrary
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeLibraryConfig
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind
import org.jetbrains.kotlin.gradle.plugin.mpp.enabledOnCurrentHost import org.jetbrains.kotlin.gradle.plugin.mpp.enabledOnCurrentHost
@@ -22,27 +24,34 @@ import org.jetbrains.kotlin.konan.target.presetName
import org.jetbrains.kotlin.konan.util.visibleName import org.jetbrains.kotlin.konan.util.visibleName
import javax.inject.Inject import javax.inject.Inject
abstract class KotlinNativeLibraryConfig @Inject constructor( abstract class KotlinNativeLibraryConfigImpl @Inject constructor(artifactName: String) :
artifactName: String KotlinNativeArtifactConfigImpl(artifactName), KotlinNativeLibraryConfig {
) : KotlinNativeArtifactConfig(artifactName) {
abstract var target: KonanTarget
override fun createArtifact(project: Project, extensions: ExtensionAware) = KotlinNativeLibrary( override fun validate() {
project, super.validate()
artifactName, val kind = if (isStatic) NativeOutputKind.STATIC else NativeOutputKind.DYNAMIC
modules, check(kind.availableFor(target)) {
modes, "Native artifact '$artifactName' wasn't configured because ${kind.description} is not available for ${target.visibleName}"
isStatic, }
linkerOptions, }
kotlinOptionsFn,
binaryOptions, override fun createArtifact(extensions: ExtensionAware): KotlinNativeLibraryImpl {
target, validate()
extensions return KotlinNativeLibraryImpl(
) artifactName = artifactName,
modules = modules,
modes = modes,
isStatic = isStatic,
linkerOptions = linkerOptions,
kotlinOptionsFn = kotlinOptionsFn,
binaryOptions = binaryOptions,
target = target,
extensions = extensions
)
}
} }
class KotlinNativeLibrary( class KotlinNativeLibraryImpl(
override val project: Project,
override val artifactName: String, override val artifactName: String,
override val modules: Set<Any>, override val modules: Set<Any>,
override val modes: Set<NativeBuildType>, override val modes: Set<NativeBuildType>,
@@ -50,21 +59,14 @@ class KotlinNativeLibrary(
override val linkerOptions: List<String>, override val linkerOptions: List<String>,
override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit, override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit,
override val binaryOptions: Map<String, String>, override val binaryOptions: Map<String, String>,
val target: KonanTarget, override val target: KonanTarget,
extensions: ExtensionAware extensions: ExtensionAware
) : KotlinNativeArtifact, ExtensionAware by extensions { ) : KotlinNativeLibrary, ExtensionAware by extensions {
private val kind = if (isStatic) NativeOutputKind.STATIC else NativeOutputKind.DYNAMIC private val kind = if (isStatic) NativeOutputKind.STATIC else NativeOutputKind.DYNAMIC
override fun getName() = lowerCamelCaseName(artifactName, kind.taskNameClassifier, "Library", target.presetName) override fun getName() = lowerCamelCaseName(artifactName, kind.taskNameClassifier, "Library", target.presetName)
override val taskName = lowerCamelCaseName("assemble", name)
override fun validate() { override fun registerAssembleTask(project: Project) {
super.validate()
check(kind.availableFor(target)) {
"Native artifact '$artifactName' wasn't configured because ${kind.description} is not available for ${target.visibleName}"
}
}
override fun registerAssembleTask() {
validate()
val resultTask = project.registerTask<Task>(taskName) { task -> val resultTask = project.registerTask<Task>(taskName) { task ->
task.group = BasePlugin.BUILD_GROUP task.group = BasePlugin.BUILD_GROUP
task.description = "Assemble all types of registered '$artifactName' ${kind.description} for ${target.visibleName}." task.description = "Assemble all types of registered '$artifactName' ${kind.description} for ${target.visibleName}."
@@ -155,25 +155,25 @@ open class KotlinNativeLinkArtifactTask @Inject constructor(
val localBinaryOptions = PropertiesProvider(project).nativeBinaryOptions + binaryOptions val localBinaryOptions = PropertiesProvider(project).nativeBinaryOptions + binaryOptions
val buildArgs = buildKotlinNativeBinaryLinkerArgs( val buildArgs = buildKotlinNativeBinaryLinkerArgs(
outFile, outFile = outFile,
optimized, optimized = optimized,
debuggable, debuggable = debuggable,
konanTarget, target = konanTarget,
outputKind, outputKind = outputKind,
libraries.klibs(), libraries = libraries.klibs(),
emptyList(), //FriendModules aren't needed here because it's no test artifact friendModules = emptyList(), //FriendModules aren't needed here because it's no test artifact
enableEndorsedLibs, enableEndorsedLibs = enableEndorsedLibs,
kotlinOptions, kotlinOptions = kotlinOptions,
emptyList(),//CompilerPlugins aren't needed here because it's no compilation but linking compilerPlugins = emptyList(),//CompilerPlugins aren't needed here because it's no compilation but linking
processTests, processTests = processTests,
entryPoint, entryPoint = entryPoint,
embedBitcode, embedBitcode = embedBitcode,
linkerOptions, linkerOpts = linkerOptions,
localBinaryOptions, binaryOptions = localBinaryOptions,
isStaticFramework, isStaticFramework = isStaticFramework,
exportLibraries.klibs(), exportLibraries = exportLibraries.klibs(),
includeLibraries.klibs(), includeLibraries = includeLibraries.klibs(),
emptyList()//todo support org.jetbrains.kotlin.gradle.tasks.CacheBuilder and org.jetbrains.kotlin.gradle.tasks.ExternalDependenciesBuilder additionalOptions = emptyList()//todo support org.jetbrains.kotlin.gradle.tasks.CacheBuilder and org.jetbrains.kotlin.gradle.tasks.ExternalDependenciesBuilder
) )
KotlinNativeCompilerRunner(project).run(buildArgs) KotlinNativeCompilerRunner(project).run(buildArgs)
@@ -10,6 +10,8 @@ import org.gradle.api.Task
import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionAware
import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeXCFramework
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeXCFrameworkConfig
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind
@@ -22,49 +24,18 @@ import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
import javax.inject.Inject import javax.inject.Inject
abstract class KotlinNativeXCFrameworkConfig @Inject constructor( abstract class KotlinNativeXCFrameworkConfigImpl @Inject constructor(artifactName: String) :
artifactName: String KotlinNativeArtifactConfigImpl(artifactName), KotlinNativeXCFrameworkConfig {
) : KotlinNativeArtifactConfig(artifactName) { override var targets: Set<KonanTarget> = emptySet()
var targets: Set<KonanTarget> = emptySet() override fun targets(vararg targets: KonanTarget) {
fun targets(vararg targets: KonanTarget) {
this.targets = targets.toSet() this.targets = targets.toSet()
} }
var embedBitcode: BitcodeEmbeddingMode? = null override var embedBitcode: BitcodeEmbeddingMode? = null
override fun createArtifact(project: Project, extensions: ExtensionAware) = KotlinNativeXCFramework(
project,
artifactName,
modules,
modes,
isStatic,
linkerOptions,
kotlinOptionsFn,
binaryOptions,
targets,
embedBitcode,
extensions
)
}
class KotlinNativeXCFramework(
override val project: Project,
override val artifactName: String,
override val modules: Set<Any>,
override val modes: Set<NativeBuildType>,
override val isStatic: Boolean,
override val linkerOptions: List<String>,
override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit,
override val binaryOptions: Map<String, String>,
val targets: Set<KonanTarget>,
val embedBitcode: BitcodeEmbeddingMode?,
extensions: ExtensionAware
) : KotlinNativeArtifact, ExtensionAware by extensions {
private val kind = NativeOutputKind.FRAMEWORK
override fun getName() = lowerCamelCaseName(artifactName, "XCFramework")
override fun validate() { override fun validate() {
super.validate() super.validate()
val kind = NativeOutputKind.FRAMEWORK
check(targets.isNotEmpty()) { check(targets.isNotEmpty()) {
"Native artifact '$artifactName' wasn't configured because it requires at least one target" "Native artifact '$artifactName' wasn't configured because it requires at least one target"
} }
@@ -74,8 +45,39 @@ class KotlinNativeXCFramework(
} }
} }
override fun registerAssembleTask() { override fun createArtifact(extensions: ExtensionAware): KotlinNativeXCFrameworkImpl {
validate() validate()
return KotlinNativeXCFrameworkImpl(
artifactName = artifactName,
modules = modules,
modes = modes,
isStatic = isStatic,
linkerOptions = linkerOptions,
kotlinOptionsFn = kotlinOptionsFn,
binaryOptions = binaryOptions,
targets = targets,
embedBitcode = embedBitcode,
extensions = extensions
)
}
}
class KotlinNativeXCFrameworkImpl(
override val artifactName: String,
override val modules: Set<Any>,
override val modes: Set<NativeBuildType>,
override val isStatic: Boolean,
override val linkerOptions: List<String>,
override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit,
override val binaryOptions: Map<String, String>,
override val targets: Set<KonanTarget>,
override val embedBitcode: BitcodeEmbeddingMode?,
extensions: ExtensionAware
) : KotlinNativeXCFramework, ExtensionAware by extensions {
override fun getName() = lowerCamelCaseName(artifactName, "XCFramework")
override val taskName = lowerCamelCaseName("assemble", name)
override fun registerAssembleTask(project: Project) {
val parentTask = project.registerTask<Task>(taskName) { val parentTask = project.registerTask<Task>(taskName) {
it.group = "build" it.group = "build"
it.description = "Assemble all types of registered '$artifactName' XCFramework" it.description = "Assemble all types of registered '$artifactName' XCFramework"
@@ -92,15 +94,15 @@ class KotlinNativeXCFramework(
val librariesConfigurationName = project.registerLibsDependencies(target, artifactName + nameSuffix, modules) val librariesConfigurationName = project.registerLibsDependencies(target, artifactName + nameSuffix, modules)
val exportConfigurationName = project.registerExportDependencies(target, artifactName + nameSuffix, modules) val exportConfigurationName = project.registerExportDependencies(target, artifactName + nameSuffix, modules)
val targetTask = registerLinkFrameworkTask( val targetTask = registerLinkFrameworkTask(
project, project = project,
artifactName, name = artifactName,
target, target = target,
buildType, buildType = buildType,
librariesConfigurationName, librariesConfigurationName = librariesConfigurationName,
exportConfigurationName, exportConfigurationName = exportConfigurationName,
embedBitcode, embedBitcode = embedBitcode,
"${artifactName}XCFrameworkTemp", outDirName = "${artifactName}XCFrameworkTemp",
nameSuffix taskNameSuffix = nameSuffix
) )
holder.task.dependsOn(targetTask) holder.task.dependsOn(targetTask)
val frameworkFileProvider = targetTask.map { it.outputFile } val frameworkFileProvider = targetTask.map { it.outputFile }