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 {
Native.Library("groolib") {
it.native.Library("groolib") {
modes(DEBUG)
target = iosX64
isStatic = false
it.static = false
linkerOptions = ["a", "b"]
kotlinOptions {
verbose = true
@@ -25,24 +25,24 @@ kotlinArtifacts {
project(":lib")
)
}
Native.Framework("grooframe") {
it.native.Framework("grooframe") {
modes(DEBUG, RELEASE)
target = iosArm64
isStatic = false
it.static = false
embedBitcode = EmbedBitcodeMode.MARKER
kotlinOptions {
verbose = true
}
addModule(project(":shared"))
}
Native.FatFramework("groofatframe") {
it.native.FatFramework("groofatframe") {
targets(iosX64, iosSimulatorArm64)
embedBitcode = EmbedBitcodeMode.DISABLE
kotlinOptions {
suppressWarnings = true
}
}
Native.XCFramework {
it.native.XCFramework {
targets(iosX64, iosArm64, iosSimulatorArm64)
}
}
@@ -6,11 +6,11 @@
package org.jetbrains.kotlin.gradle.targets.native.tasks.artifact
import org.gradle.api.Action
import org.gradle.api.Named
import org.gradle.api.Project
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.KotlinNativeArtifactConfig
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
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.presetName
abstract class KotlinArtifactConfig(
val artifactName: String
) {
internal val modules = mutableSetOf<Any>()
fun setModules(vararg project: Any) {
abstract class KotlinArtifactConfigImpl(
override val artifactName: String
) : KotlinArtifactConfig {
override val modules = mutableSetOf<Any>()
override fun setModules(vararg project: Any) {
modules.clear()
modules.addAll(project)
}
fun addModule(project: Any) {
override fun addModule(project: Any) {
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 {
val project: Project
val artifactName: String
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) {
abstract class KotlinNativeArtifactConfigImpl(artifactName: String) : KotlinArtifactConfigImpl(artifactName), KotlinNativeArtifactConfig {
override var modes: Set<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES
override fun modes(vararg modes: NativeBuildType) {
this.modes = modes.toSet()
}
@JvmField
var isStatic: Boolean = false
@JvmField
var linkerOptions: List<String> = emptyList()
override var isStatic: Boolean = false
override var linkerOptions: List<String> = emptyList()
internal var kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit = {}
fun kotlinOptions(fn: Action<KotlinCommonToolOptions>) {
override fun kotlinOptions(fn: Action<KotlinCommonToolOptions>) {
kotlinOptionsFn = fn::execute
}
internal val binaryOptions: MutableMap<String, String> = mutableMapOf()
fun binaryOption(name: String, value: String) {
override fun binaryOption(name: String, value: String) {
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() {
check(modules.isNotEmpty()) {
"Native artifact '$artifactName' wasn't configured because it requires at least one module for linking"
}
super.validate()
check(modes.isNotEmpty()) {
"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
import org.gradle.api.Action
import org.gradle.api.DomainObjectSet
import org.gradle.api.NamedDomainObjectSet
import org.gradle.api.Project
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.utils.castIsolatedKotlinPluginClassLoaderAware
import org.jetbrains.kotlin.konan.target.KonanTarget
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"
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)
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()
abstract class KotlinArtifactsExtension @Inject constructor(project: Project) {
//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 = project.objects.domainObjectSet(KotlinArtifactConfig::class.java)
val artifacts = project.objects.namedDomainObjectSet(KotlinArtifact::class.java)
abstract class KotlinArtifactsExtensionImpl @Inject constructor(project: Project) : KotlinArtifactsExtension {
override val artifactConfigs = project.objects.domainObjectSet(KotlinArtifactConfig::class.java)
override val artifacts = project.objects.namedDomainObjectSet(KotlinArtifact::class.java)
override val Native = project.objects.newInstance(KotlinNativeArtifactDSLImpl::class.java, project)
val DEBUG = NativeBuildType.DEBUG
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
}
@JvmField
val Native = project.objects.newInstance(NativeArtifacts::class.java, project)
@JvmField
val EmbedBitcodeMode = BitcodeEmbeddingModeDsl()
@@ -160,4 +69,65 @@ abstract class KotlinArtifactsExtension @Inject constructor(project: Project) {
val linuxMips32 = KonanTarget.LINUX_MIPS32
val linuxMipsel32 = KonanTarget.LINUX_MIPSEL32
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.language.base.plugins.LifecycleBasePlugin
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.NativeBuildType
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 javax.inject.Inject
abstract class KotlinNativeFatFrameworkConfig @Inject constructor(
artifactName: String
) : KotlinNativeArtifactConfig(artifactName) {
var targets: Set<KonanTarget> = emptySet()
fun targets(vararg targets: KonanTarget) {
abstract class KotlinNativeFatFrameworkConfigImpl @Inject constructor(artifactName: String) :
KotlinNativeArtifactConfigImpl(artifactName), KotlinNativeFatFrameworkConfig {
override var targets: Set<KonanTarget> = emptySet()
override fun targets(vararg targets: KonanTarget) {
this.targets = targets.toSet()
}
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 var embedBitcode: BitcodeEmbeddingMode? = null
override fun validate() {
super.validate()
val kind = NativeOutputKind.FRAMEWORK
check(targets.isNotEmpty()) {
"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()
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) {
it.group = "build"
it.description = "Assemble all types of registered '$artifactName' FatFramework"
@@ -96,15 +98,15 @@ class KotlinNativeFatFramework(
val librariesConfigurationName = project.registerLibsDependencies(target, artifactName + nameSuffix, modules)
val exportConfigurationName = project.registerExportDependencies(target, artifactName + nameSuffix, modules)
val targetTask = registerLinkFrameworkTask(
project,
artifactName,
target,
buildType,
librariesConfigurationName,
exportConfigurationName,
embedBitcode,
"${artifactName}FatFrameworkTemp",
nameSuffix
project = project,
name = artifactName,
target = target,
buildType = buildType,
librariesConfigurationName = librariesConfigurationName,
exportConfigurationName = exportConfigurationName,
embedBitcode = embedBitcode,
outDirName = "${artifactName}FatFrameworkTemp",
taskNameSuffix = nameSuffix
)
fatTask.dependsOn(targetTask)
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.language.base.plugins.LifecycleBasePlugin
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.NativeBuildType
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 javax.inject.Inject
abstract class KotlinNativeFrameworkConfig @Inject constructor(
artifactName: String
) : KotlinNativeArtifactConfig(artifactName) {
abstract var target: KonanTarget
var embedBitcode: BitcodeEmbeddingMode? = null
abstract class KotlinNativeFrameworkConfigImpl @Inject constructor(artifactName: String) :
KotlinNativeArtifactConfigImpl(artifactName), KotlinNativeFrameworkConfig {
override fun createArtifact(project: Project, extensions: ExtensionAware) = KotlinNativeFramework(
project,
artifactName,
modules,
modes,
isStatic,
linkerOptions,
kotlinOptionsFn,
binaryOptions,
target,
embedBitcode,
extensions
)
override fun validate() {
super.validate()
val kind = NativeOutputKind.FRAMEWORK
check(kind.availableFor(target)) {
"Native artifact '$artifactName' wasn't configured because ${kind.description} is not available for ${target.visibleName}"
}
}
override fun createArtifact(extensions: ExtensionAware): KotlinNativeFrameworkImpl {
validate()
return KotlinNativeFrameworkImpl(
artifactName = artifactName,
modules = modules,
modes = modes,
isStatic = isStatic,
linkerOptions = linkerOptions,
kotlinOptionsFn = kotlinOptionsFn,
binaryOptions = binaryOptions,
target = target,
embedBitcode = embedBitcode,
extensions = extensions
)
}
}
class KotlinNativeFramework(
override val project: Project,
class KotlinNativeFrameworkImpl(
override val artifactName: String,
override val modules: Set<Any>,
override val modes: Set<NativeBuildType>,
@@ -54,22 +63,15 @@ class KotlinNativeFramework(
override val linkerOptions: List<String>,
override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit,
override val binaryOptions: Map<String, String>,
val target: KonanTarget,
val embedBitcode: BitcodeEmbeddingMode?,
override val target: KonanTarget,
override val embedBitcode: BitcodeEmbeddingMode?,
extensions: ExtensionAware
) : KotlinNativeArtifact, ExtensionAware by extensions {
) : KotlinNativeFramework, ExtensionAware by extensions {
private val kind = NativeOutputKind.FRAMEWORK
override fun getName() = lowerCamelCaseName(artifactName, kind.taskNameClassifier, target.presetName)
override val taskName = lowerCamelCaseName("assemble", name)
override fun validate() {
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()
override fun registerAssembleTask(project: Project) {
val resultTask = project.registerTask<Task>(taskName) { task ->
task.group = BasePlugin.BUILD_GROUP
task.description = "Assemble ${kind.description} '$artifactName' for ${target.visibleName}."
@@ -80,13 +82,13 @@ class KotlinNativeFramework(
val exportConfigurationName = project.registerExportDependencies(target, artifactName, modules)
modes.forEach { buildType ->
val targetTask = registerLinkFrameworkTask(
project,
artifactName,
target,
buildType,
librariesConfigurationName,
exportConfigurationName,
embedBitcode
project = project,
name = artifactName,
target = target,
buildType = buildType,
librariesConfigurationName = librariesConfigurationName,
exportConfigurationName = exportConfigurationName,
embedBitcode = embedBitcode
)
resultTask.dependsOn(targetTask)
}
@@ -11,6 +11,8 @@ import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.ExtensionAware
import org.gradle.language.base.plugins.LifecycleBasePlugin
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.NativeOutputKind
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 javax.inject.Inject
abstract class KotlinNativeLibraryConfig @Inject constructor(
artifactName: String
) : KotlinNativeArtifactConfig(artifactName) {
abstract var target: KonanTarget
abstract class KotlinNativeLibraryConfigImpl @Inject constructor(artifactName: String) :
KotlinNativeArtifactConfigImpl(artifactName), KotlinNativeLibraryConfig {
override fun createArtifact(project: Project, extensions: ExtensionAware) = KotlinNativeLibrary(
project,
artifactName,
modules,
modes,
isStatic,
linkerOptions,
kotlinOptionsFn,
binaryOptions,
target,
extensions
)
override fun validate() {
super.validate()
val kind = if (isStatic) NativeOutputKind.STATIC else NativeOutputKind.DYNAMIC
check(kind.availableFor(target)) {
"Native artifact '$artifactName' wasn't configured because ${kind.description} is not available for ${target.visibleName}"
}
}
override fun createArtifact(extensions: ExtensionAware): KotlinNativeLibraryImpl {
validate()
return KotlinNativeLibraryImpl(
artifactName = artifactName,
modules = modules,
modes = modes,
isStatic = isStatic,
linkerOptions = linkerOptions,
kotlinOptionsFn = kotlinOptionsFn,
binaryOptions = binaryOptions,
target = target,
extensions = extensions
)
}
}
class KotlinNativeLibrary(
override val project: Project,
class KotlinNativeLibraryImpl(
override val artifactName: String,
override val modules: Set<Any>,
override val modes: Set<NativeBuildType>,
@@ -50,21 +59,14 @@ class KotlinNativeLibrary(
override val linkerOptions: List<String>,
override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit,
override val binaryOptions: Map<String, String>,
val target: KonanTarget,
override val target: KonanTarget,
extensions: ExtensionAware
) : KotlinNativeArtifact, ExtensionAware by extensions {
) : KotlinNativeLibrary, ExtensionAware by extensions {
private val kind = if (isStatic) NativeOutputKind.STATIC else NativeOutputKind.DYNAMIC
override fun getName() = lowerCamelCaseName(artifactName, kind.taskNameClassifier, "Library", target.presetName)
override val taskName = lowerCamelCaseName("assemble", name)
override fun validate() {
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()
override fun registerAssembleTask(project: Project) {
val resultTask = project.registerTask<Task>(taskName) { task ->
task.group = BasePlugin.BUILD_GROUP
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 buildArgs = buildKotlinNativeBinaryLinkerArgs(
outFile,
optimized,
debuggable,
konanTarget,
outputKind,
libraries.klibs(),
emptyList(), //FriendModules aren't needed here because it's no test artifact
enableEndorsedLibs,
kotlinOptions,
emptyList(),//CompilerPlugins aren't needed here because it's no compilation but linking
processTests,
entryPoint,
embedBitcode,
linkerOptions,
localBinaryOptions,
isStaticFramework,
exportLibraries.klibs(),
includeLibraries.klibs(),
emptyList()//todo support org.jetbrains.kotlin.gradle.tasks.CacheBuilder and org.jetbrains.kotlin.gradle.tasks.ExternalDependenciesBuilder
outFile = outFile,
optimized = optimized,
debuggable = debuggable,
target = konanTarget,
outputKind = outputKind,
libraries = libraries.klibs(),
friendModules = emptyList(), //FriendModules aren't needed here because it's no test artifact
enableEndorsedLibs = enableEndorsedLibs,
kotlinOptions = kotlinOptions,
compilerPlugins = emptyList(),//CompilerPlugins aren't needed here because it's no compilation but linking
processTests = processTests,
entryPoint = entryPoint,
embedBitcode = embedBitcode,
linkerOpts = linkerOptions,
binaryOptions = localBinaryOptions,
isStaticFramework = isStaticFramework,
exportLibraries = exportLibraries.klibs(),
includeLibraries = includeLibraries.klibs(),
additionalOptions = emptyList()//todo support org.jetbrains.kotlin.gradle.tasks.CacheBuilder and org.jetbrains.kotlin.gradle.tasks.ExternalDependenciesBuilder
)
KotlinNativeCompilerRunner(project).run(buildArgs)
@@ -10,6 +10,8 @@ import org.gradle.api.Task
import org.gradle.api.plugins.ExtensionAware
import org.gradle.language.base.plugins.LifecycleBasePlugin
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.NativeBuildType
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 javax.inject.Inject
abstract class KotlinNativeXCFrameworkConfig @Inject constructor(
artifactName: String
) : KotlinNativeArtifactConfig(artifactName) {
var targets: Set<KonanTarget> = emptySet()
fun targets(vararg targets: KonanTarget) {
abstract class KotlinNativeXCFrameworkConfigImpl @Inject constructor(artifactName: String) :
KotlinNativeArtifactConfigImpl(artifactName), KotlinNativeXCFrameworkConfig {
override var targets: Set<KonanTarget> = emptySet()
override fun targets(vararg targets: KonanTarget) {
this.targets = targets.toSet()
}
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 var embedBitcode: BitcodeEmbeddingMode? = null
override fun validate() {
super.validate()
val kind = NativeOutputKind.FRAMEWORK
check(targets.isNotEmpty()) {
"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()
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) {
it.group = "build"
it.description = "Assemble all types of registered '$artifactName' XCFramework"
@@ -92,15 +94,15 @@ class KotlinNativeXCFramework(
val librariesConfigurationName = project.registerLibsDependencies(target, artifactName + nameSuffix, modules)
val exportConfigurationName = project.registerExportDependencies(target, artifactName + nameSuffix, modules)
val targetTask = registerLinkFrameworkTask(
project,
artifactName,
target,
buildType,
librariesConfigurationName,
exportConfigurationName,
embedBitcode,
"${artifactName}XCFrameworkTemp",
nameSuffix
project = project,
name = artifactName,
target = target,
buildType = buildType,
librariesConfigurationName = librariesConfigurationName,
exportConfigurationName = exportConfigurationName,
embedBitcode = embedBitcode,
outDirName = "${artifactName}XCFrameworkTemp",
taskNameSuffix = nameSuffix
)
holder.task.dependsOn(targetTask)
val frameworkFileProvider = targetTask.map { it.outputFile }