diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinArtifact.kt b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinArtifact.kt new file mode 100644 index 00000000000..5f60f193823 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinArtifact.kt @@ -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 + val taskName: String + fun registerAssembleTask(project: Project) +} + +interface KotlinNativeArtifact : KotlinArtifact { + val modes: Set + val isStatic: Boolean + val linkerOptions: List + val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit + val binaryOptions: Map +} + +interface KotlinNativeLibrary : KotlinNativeArtifact { + val target: KonanTarget +} + +interface KotlinNativeFramework : KotlinNativeArtifact { + val target: KonanTarget + val embedBitcode: BitcodeEmbeddingMode? +} + +interface KotlinNativeFatFramework : KotlinNativeArtifact { + val targets: Set + val embedBitcode: BitcodeEmbeddingMode? +} + +interface KotlinNativeXCFramework : KotlinNativeArtifact { + val targets: Set + val embedBitcode: BitcodeEmbeddingMode? +} + +interface KotlinArtifactConfig { + val artifactName: String + val modules: Set + fun setModules(vararg project: Any) + fun addModule(project: Any) + fun createArtifact(extensions: ExtensionAware): KotlinArtifact +} + +interface KotlinNativeArtifactConfig : KotlinArtifactConfig { + var modes: Set + fun modes(vararg modes: NativeBuildType) + var isStatic: Boolean + var linkerOptions: List + fun kotlinOptions(fn: Action) + 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 + fun targets(vararg targets: KonanTarget) + var embedBitcode: BitcodeEmbeddingMode? +} + +interface KotlinNativeXCFrameworkConfig : KotlinNativeArtifactConfig { + var targets: Set + 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 + val artifacts: NamedDomainObjectSet + 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) + + @ExperimentalArtifactDsl + fun Library(configure: Action) + + @ExperimentalArtifactDsl + fun Framework(name: String, configure: Action) + + @ExperimentalArtifactDsl + fun Framework(configure: Action) + + @ExperimentalArtifactDsl + fun FatFramework(name: String, configure: Action) + + @ExperimentalArtifactDsl + fun FatFramework(configure: Action) + + @ExperimentalArtifactDsl + fun XCFramework(name: String, configure: Action) + + @ExperimentalArtifactDsl + fun XCFramework(configure: Action) +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/lib/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/lib/build.gradle index 7cd20687706..45fc2a8ab82 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/lib/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/lib/build.gradle @@ -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) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifact.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifact.kt index b269451b17e..40074c06bb0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifact.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifact.kt @@ -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() - fun setModules(vararg project: Any) { +abstract class KotlinArtifactConfigImpl( + override val artifactName: String +) : KotlinArtifactConfig { + override val modules = mutableSetOf() + 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 - val taskName: String get() = lowerCamelCaseName("assemble", name) - - fun validate() - fun registerAssembleTask() -} - -abstract class KotlinNativeArtifactConfig(artifactName: String) : KotlinArtifactConfig(artifactName) { - var modes: Set = NativeBuildType.DEFAULT_BUILD_TYPES - fun modes(vararg modes: NativeBuildType) { +abstract class KotlinNativeArtifactConfigImpl(artifactName: String) : KotlinArtifactConfigImpl(artifactName), KotlinNativeArtifactConfig { + override var modes: Set = NativeBuildType.DEFAULT_BUILD_TYPES + override fun modes(vararg modes: NativeBuildType) { this.modes = modes.toSet() } - @JvmField - var isStatic: Boolean = false - - @JvmField - var linkerOptions: List = emptyList() + override var isStatic: Boolean = false + override var linkerOptions: List = emptyList() internal var kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit = {} - fun kotlinOptions(fn: Action) { + override fun kotlinOptions(fn: Action) { kotlinOptionsFn = fn::execute } internal val binaryOptions: MutableMap = mutableMapOf() - fun binaryOption(name: String, value: String) { + override fun binaryOption(name: String, value: String) { binaryOptions[name] = value } -} - -interface KotlinNativeArtifact : KotlinArtifact { - val modes: Set - val isStatic: Boolean - val linkerOptions: List - val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit - val binaryOptions: Map 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" } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifactDSL.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifactDSL.kt index 929f7192950..15f32b1385e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifactDSL.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifactDSL.kt @@ -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) { - addKotlinArtifact(name, configure) - } - - @ExperimentalArtifactDsl - fun Library(configure: Action) { - addKotlinArtifact(configure) - } - - @ExperimentalArtifactDsl - fun Framework(name: String, configure: Action) { - addKotlinArtifact(name, configure) - } - - @ExperimentalArtifactDsl - fun Framework(configure: Action) { - addKotlinArtifact(configure) - } - - @ExperimentalArtifactDsl - fun FatFramework(name: String, configure: Action) { - addKotlinArtifact(name, configure) - } - - @ExperimentalArtifactDsl - fun FatFramework(configure: Action) { - addKotlinArtifact(configure) - } - - @ExperimentalArtifactDsl - fun XCFramework(name: String, configure: Action) { - addKotlinArtifact(name, configure) - } - - @ExperimentalArtifactDsl - fun XCFramework(configure: Action) { - addKotlinArtifact(configure) - } - - private inline fun addKotlinArtifact(configure: Action) { - addKotlinArtifact(project.name.replace(UNSAFE_NAME_SYMBOLS, "_"), configure) - } - - private inline fun addKotlinArtifact(name: String, configure: Action) { - //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) { + addKotlinArtifact(name, configure) + } + + override fun Library(configure: Action) { + addKotlinArtifact(configure) + } + + override fun Framework(name: String, configure: Action) { + addKotlinArtifact(name, configure) + } + + override fun Framework(configure: Action) { + addKotlinArtifact(configure) + } + + override fun FatFramework(name: String, configure: Action) { + addKotlinArtifact(name, configure) + } + + override fun FatFramework(configure: Action) { + addKotlinArtifact(configure) + } + + override fun XCFramework(name: String, configure: Action) { + addKotlinArtifact(name, configure) + } + + override fun XCFramework(configure: Action) { + addKotlinArtifact(configure) + } + + private inline fun addKotlinArtifact(configure: Action) { + addKotlinArtifact(project.name.replace(UNSAFE_NAME_SYMBOLS, "_"), configure) + } + + private inline fun addKotlinArtifact(name: String, configure: Action) { + //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!") + } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFatFramework.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFatFramework.kt index a105f6320db..d87dbb4effd 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFatFramework.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFatFramework.kt @@ -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 = emptySet() - fun targets(vararg targets: KonanTarget) { +abstract class KotlinNativeFatFrameworkConfigImpl @Inject constructor(artifactName: String) : + KotlinNativeArtifactConfigImpl(artifactName), KotlinNativeFatFrameworkConfig { + override var targets: Set = 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, - override val modes: Set, - override val isStatic: Boolean, - override val linkerOptions: List, - override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit, - override val binaryOptions: Map, - val targets: Set, - 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, + override val modes: Set, + override val isStatic: Boolean, + override val linkerOptions: List, + override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit, + override val binaryOptions: Map, + override val targets: Set, + 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(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 } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFramework.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFramework.kt index 42bf90b8155..9bd97dc201e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFramework.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFramework.kt @@ -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, override val modes: Set, @@ -54,22 +63,15 @@ class KotlinNativeFramework( override val linkerOptions: List, override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit, override val binaryOptions: Map, - 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(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) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt index 78fcc93dbe0..89847cb78c7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt @@ -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, override val modes: Set, @@ -50,21 +59,14 @@ class KotlinNativeLibrary( override val linkerOptions: List, override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit, override val binaryOptions: Map, - 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(taskName) { task -> task.group = BasePlugin.BUILD_GROUP task.description = "Assemble all types of registered '$artifactName' ${kind.description} for ${target.visibleName}." diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt index 3300ff7e021..7d882b3e8ca 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt @@ -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) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeXCFramework.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeXCFramework.kt index 4491c2c2e91..19eab837ddc 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeXCFramework.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeXCFramework.kt @@ -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 = emptySet() - fun targets(vararg targets: KonanTarget) { +abstract class KotlinNativeXCFrameworkConfigImpl @Inject constructor(artifactName: String) : + KotlinNativeArtifactConfigImpl(artifactName), KotlinNativeXCFrameworkConfig { + override var targets: Set = 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, - override val modes: Set, - override val isStatic: Boolean, - override val linkerOptions: List, - override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit, - override val binaryOptions: Map, - val targets: Set, - 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, + override val modes: Set, + override val isStatic: Boolean, + override val linkerOptions: List, + override val kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit, + override val binaryOptions: Map, + override val targets: Set, + 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(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 }