From e955fa429b8e9cb1bbd0470cae2d15566155e75b Mon Sep 17 00:00:00 2001 From: "konstantin.tskhovrebov" Date: Tue, 21 Dec 2021 13:17:00 +0100 Subject: [PATCH] Add groovy friendly DSL for kotlin artifacts. --- .../kotlin/gradle/NativeLibraryDslIT.kt | 17 ++- .../new-kn-library-dsl/lib/build.gradle | 48 +++++++ .../new-kn-library-dsl/lib/build.gradle.kts | 10 -- .../shared/build.gradle.kts | 57 +++++--- .../plugin/mpp/KotlinMultiplatformPlugin.kt | 2 + .../native/tasks/artifact/KotlinArtifact.kt | 47 ++----- .../tasks/artifact/KotlinArtifactDSL.kt | 126 ++++++++++++++++++ .../artifact/KotlinNativeFatFramework.kt | 6 +- .../tasks/artifact/KotlinNativeFramework.kt | 2 +- .../tasks/artifact/KotlinNativeLibrary.kt | 2 +- .../tasks/artifact/KotlinNativeXCFramework.kt | 6 +- 11 files changed, 248 insertions(+), 75 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/lib/build.gradle delete mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/lib/build.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifactDSL.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NativeLibraryDslIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NativeLibraryDslIT.kt index 9afc3b258d6..da4244a6e78 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NativeLibraryDslIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NativeLibraryDslIT.kt @@ -18,16 +18,25 @@ class NativeLibraryDslIT : BaseGradleIT() { build(":shared:tasks") { assertSuccessful() assertTasksRegistered( - ":shared:assembleMylibDebugSharedLibraryLinuxX64", - ":shared:assembleMyslibDebugSharedLibraryLinuxX64", - ":shared:assembleMylibReleaseSharedLibraryLinuxX64", + ":shared:assembleMyfatframeFatFramework", + ":shared:assembleMyframeFramework", ":shared:assembleMylibSharedLibrary", - ":shared:assembleMyslibSharedLibrary" + ":shared:assembleMyslibSharedLibrary", + ":shared:assembleSharedXCFramework" ) assertTasksNotRegistered( ":shared:assembleMyslibReleaseSharedLibraryLinuxX64" ) } + build(":lib:tasks") { + assertSuccessful() + assertTasksRegistered( + ":lib:assembleGroofatframeFatFramework", + ":lib:assembleGrooframeFramework", + ":lib:assembleGroolibSharedLibrary", + ":lib:assembleLibXCFramework" + ) + } } } 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 new file mode 100644 index 00000000000..7cd20687706 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/lib/build.gradle @@ -0,0 +1,48 @@ +plugins { + id 'org.jetbrains.kotlin.multiplatform' +} + +kotlin { + linuxX64() + iosX64() + iosArm64() + iosSimulatorArm64() +} + +kotlinArtifacts { + Native.Library("groolib") { + modes(DEBUG) + target = iosX64 + isStatic = false + linkerOptions = ["a", "b"] + kotlinOptions { + verbose = true + freeCompilerArgs = ["foo"] + } + binaryOption("name", "value") + setModules( + project(":shared"), + project(":lib") + ) + } + Native.Framework("grooframe") { + modes(DEBUG, RELEASE) + target = iosArm64 + isStatic = false + embedBitcode = EmbedBitcodeMode.MARKER + kotlinOptions { + verbose = true + } + addModule(project(":shared")) + } + Native.FatFramework("groofatframe") { + targets(iosX64, iosSimulatorArm64) + embedBitcode = EmbedBitcodeMode.DISABLE + kotlinOptions { + suppressWarnings = true + } + } + Native.XCFramework { + targets(iosX64, iosArm64, iosSimulatorArm64) + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/lib/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/lib/build.gradle.kts deleted file mode 100644 index ffe541f40e7..00000000000 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/lib/build.gradle.kts +++ /dev/null @@ -1,10 +0,0 @@ -plugins { - kotlin("multiplatform") -} - -kotlin { - linuxX64() - iosX64() - iosArm64() - iosSimulatorArm64() -} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/shared/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/shared/build.gradle.kts index 6a354546919..336ce3b28a8 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/shared/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-kn-library-dsl/shared/build.gradle.kts @@ -1,7 +1,3 @@ -import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType -import org.jetbrains.kotlin.gradle.targets.native.tasks.artifact.* -import org.jetbrains.kotlin.konan.target.KonanTarget.* - plugins { kotlin("multiplatform") } @@ -13,20 +9,41 @@ kotlin { iosSimulatorArm64() } -kotlinArtifact("mylib", Library) { - target = LINUX_X64 -} - -kotlinArtifact("myslib", Library) { - target = LINUX_X64 - modes = setOf(NativeBuildType.DEBUG) - addModule(project(":lib")) -} - -kotlinArtifact(XCFramework) { - targets = setOf(IOS_X64, IOS_ARM64, IOS_SIMULATOR_ARM64) - setModules( - project(":shared"), - project(":lib") - ) +kotlinArtifacts { + Native.Library("mylib") { + target = linuxX64 + } + Native.Library("myslib") { + target = linuxX64 + isStatic = false + modes(DEBUG) + addModule(project(":lib")) + kotlinOptions { + verbose = false + freeCompilerArgs = emptyList() + } + } + Native.Framework("myframe") { + modes(DEBUG, RELEASE) + target = iosArm64 + isStatic = false + embedBitcode = EmbedBitcodeMode.MARKER + kotlinOptions { + verbose = false + } + } + Native.FatFramework("myfatframe") { + targets(iosX64, iosSimulatorArm64) + embedBitcode = EmbedBitcodeMode.DISABLE + kotlinOptions { + suppressWarnings = false + } + } + Native.XCFramework { + targets(iosX64, iosArm64, iosSimulatorArm64) + setModules( + project(":shared"), + project(":lib") + ) + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index 9eb7ea76a2a..38ee3415b42 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.gradle.plugin.sources.checkSourceSetVisibilityRequir import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTargetPreset +import org.jetbrains.kotlin.gradle.targets.native.tasks.artifact.registerKotlinArtifactsExtension import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.utils.* @@ -95,6 +96,7 @@ class KotlinMultiplatformPlugin : Plugin { METADATA_TARGET_NAME ) configurePublishingWithMavenPublish(project) + project.registerKotlinArtifactsExtension() targetsContainer.withType(AbstractKotlinTarget::class.java).all { applyUserDefinedAttributes(it) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifact.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifact.kt index a9937280bcc..0bc74308a03 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifact.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifact.kt @@ -5,10 +5,10 @@ package org.jetbrains.kotlin.gradle.targets.native.tasks.artifact -import org.gradle.api.Plugin +import groovy.lang.Closure +import org.gradle.api.Action import org.gradle.api.Project import org.gradle.api.attributes.Usage -import org.gradle.kotlin.dsl.create import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget @@ -17,7 +17,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.presetName -import javax.inject.Inject abstract class KotlinArtifact { internal val modules = mutableSetOf() @@ -36,12 +35,16 @@ abstract class KotlinArtifact { abstract class KotlinNativeArtifact : KotlinArtifact() { var modes: Set = NativeBuildType.DEFAULT_BUILD_TYPES - var isStatic: Boolean = false - var linkerOptions: List = emptyList() + fun modes(vararg modes: NativeBuildType) { + this.modes = modes.toSet() + } + + @JvmField var isStatic: Boolean = false + @JvmField var linkerOptions: List = emptyList() internal var kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit = {} - fun kotlinOptions(fn: KotlinCommonToolOptions.() -> Unit) { - kotlinOptionsFn = fn + fun kotlinOptions(fn: Action) { + kotlinOptionsFn = fn::execute } internal val binaryOptions: MutableMap = mutableMapOf() @@ -93,34 +96,4 @@ abstract class KotlinNativeArtifact : KotlinArtifact() { deps.forEach { dependencies.add(exportConfigurationName, it) } return exportConfigurationName } -} - -open class ArtifactType(internal val create: () -> T) -object Library : ArtifactType({ KotlinNativeLibrary() }) -object Framework : ArtifactType({ KotlinNativeFramework() }) -object FatFramework : ArtifactType({ KotlinNativeFatFramework() }) -object XCFramework : ArtifactType({ KotlinNativeXCFramework() }) - -@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 - -private val SAFE_NAME_PATTERN = """\W""".toRegex() - -@ExperimentalArtifactDsl -fun Project.kotlinArtifact(type: ArtifactType, configure: T.() -> Unit) = - kotlinArtifact(name.replace(SAFE_NAME_PATTERN, "_"), type, configure) - -@ExperimentalArtifactDsl -fun Project.kotlinArtifact(name: String, type: ArtifactType, configure: T.() -> Unit) { - val artifact = type.create() - artifact.addModule(this) - configure(artifact) - if (artifact.validate(this, name)) { - artifact.registerAssembleTask(this, name) - } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifactDSL.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifactDSL.kt new file mode 100644 index 00000000000..93d1e5dd382 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinArtifactDSL.kt @@ -0,0 +1,126 @@ +/* + * Copyright 2010-2021 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.targets.native.tasks.artifact + +import org.gradle.api.Action +import org.gradle.api.Project +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType +import org.jetbrains.kotlin.konan.target.KonanTarget +import javax.inject.Inject + +private val SAFE_NAME_PATTERN = """\W""".toRegex() +private inline fun Project.kotlinArtifact(configure: Action) { + kotlinArtifact(name.replace(SAFE_NAME_PATTERN, "_"), configure) +} + +private inline fun Project.kotlinArtifact(name: String, configure: Action) { + val artifact = objects.newInstance(T::class.java) + artifact.addModule(this) + configure.execute(artifact) + if (artifact.validate(this, name)) { + artifact.registerAssembleTask(this, name) + } +} + +//Groovy script DSL +abstract class NativeArtifacts @Inject constructor(private val project: Project) { + @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) { + project.kotlinArtifact(name, configure) + } + + @ExperimentalArtifactDsl + fun Library(configure: Action) { + project.kotlinArtifact(configure) + } + + @ExperimentalArtifactDsl + fun Framework(name: String, configure: Action) { + project.kotlinArtifact(name, configure) + } + + @ExperimentalArtifactDsl + fun Framework(configure: Action) { + project.kotlinArtifact(configure) + } + + @ExperimentalArtifactDsl + fun FatFramework(name: String, configure: Action) { + project.kotlinArtifact(name, configure) + } + + @ExperimentalArtifactDsl + fun FatFramework(configure: Action) { + project.kotlinArtifact(configure) + } + + @ExperimentalArtifactDsl + fun XCFramework(name: String, configure: Action) { + project.kotlinArtifact(name, configure) + } + + @ExperimentalArtifactDsl + fun XCFramework(configure: Action) { + project.kotlinArtifact(configure) + } +} + +//Groovy script DSL +internal fun Project.registerKotlinArtifactsExtension() { + extensions.create("kotlinArtifacts", KotlinArtifactsExtension::class.java, this) +} + +abstract class KotlinArtifactsExtension @Inject constructor(project: Project) { + val DEBUG = NativeBuildType.DEBUG + val RELEASE = NativeBuildType.RELEASE + + class BitcodeEmbeddingModeDsl { + val DISABLE = org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode.DISABLE + val BITCODE = org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode.BITCODE + val MARKER = org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode.MARKER + } + + @JvmField + val Native = project.objects.newInstance(NativeArtifacts::class.java, project) + + @JvmField + val EmbedBitcodeMode = BitcodeEmbeddingModeDsl() + + val androidX64 = KonanTarget.ANDROID_X64 + val androidX86 = KonanTarget.ANDROID_X86 + val androidArm32 = KonanTarget.ANDROID_ARM32 + val androidArm64 = KonanTarget.ANDROID_ARM64 + val iosArm32 = KonanTarget.IOS_ARM32 + val iosArm64 = KonanTarget.IOS_ARM64 + val iosX64 = KonanTarget.IOS_X64 + val iosSimulatorArm64 = KonanTarget.IOS_SIMULATOR_ARM64 + val watchosArm32 = KonanTarget.WATCHOS_ARM32 + val watchosArm64 = KonanTarget.WATCHOS_ARM64 + val watchosX86 = KonanTarget.WATCHOS_X86 + val watchosX64 = KonanTarget.WATCHOS_X64 + val watchosSimulatorArm64 = KonanTarget.WATCHOS_SIMULATOR_ARM64 + val tvosArm64 = KonanTarget.TVOS_ARM64 + val tvosX64 = KonanTarget.TVOS_X64 + val tvosSimulatorArm64 = KonanTarget.TVOS_SIMULATOR_ARM64 + val linuxX64 = KonanTarget.LINUX_X64 + val mingwX86 = KonanTarget.MINGW_X86 + val mingwX64 = KonanTarget.MINGW_X64 + val macosX64 = KonanTarget.MACOS_X64 + val macosArm64 = KonanTarget.MACOS_ARM64 + val linuxArm64 = KonanTarget.LINUX_ARM64 + val linuxArm32Hfp = KonanTarget.LINUX_ARM32_HFP + val linuxMips32 = KonanTarget.LINUX_MIPS32 + val linuxMipsel32 = KonanTarget.LINUX_MIPSEL32 + val wasm32 = KonanTarget.WASM32 +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFatFramework.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFatFramework.kt index 624e5c17199..a7ea3a1cfa6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFatFramework.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFatFramework.kt @@ -18,8 +18,12 @@ import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.util.visibleName -class KotlinNativeFatFramework : KotlinNativeArtifact() { +open class KotlinNativeFatFramework : KotlinNativeArtifact() { var targets: Set = emptySet() + fun targets(vararg targets: KonanTarget) { + this.targets = targets.toSet() + } + var embedBitcode: BitcodeEmbeddingMode? = null private val kind = NativeOutputKind.FRAMEWORK diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFramework.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFramework.kt index 1053fc0e2ca..c58fa41d5e2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFramework.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeFramework.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.presetName import org.jetbrains.kotlin.konan.util.visibleName -class KotlinNativeFramework : KotlinNativeArtifact() { +open class KotlinNativeFramework : KotlinNativeArtifact() { lateinit var target: KonanTarget var embedBitcode: BitcodeEmbeddingMode? = null diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt index 1009f654f6a..f045b762826 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.presetName import org.jetbrains.kotlin.konan.util.visibleName -class KotlinNativeLibrary : KotlinNativeArtifact() { +open class KotlinNativeLibrary : KotlinNativeArtifact() { lateinit var target: KonanTarget private val kind: NativeOutputKind diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeXCFramework.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeXCFramework.kt index 19ecc68437c..673b01e1154 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeXCFramework.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeXCFramework.kt @@ -18,8 +18,12 @@ import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.konan.target.KonanTarget -class KotlinNativeXCFramework : KotlinNativeArtifact() { +open class KotlinNativeXCFramework : KotlinNativeArtifact() { var targets: Set = emptySet() + fun targets(vararg targets: KonanTarget) { + this.targets = targets.toSet() + } + var embedBitcode: BitcodeEmbeddingMode? = null private val kind = NativeOutputKind.FRAMEWORK