Add groovy friendly DSL for kotlin artifacts.

This commit is contained in:
konstantin.tskhovrebov
2021-12-21 13:17:00 +01:00
committed by teamcity
parent 898c46c124
commit e955fa429b
11 changed files with 248 additions and 75 deletions
@@ -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"
)
}
}
}
@@ -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)
}
}
@@ -1,10 +0,0 @@
plugins {
kotlin("multiplatform")
}
kotlin {
linuxX64()
iosX64()
iosArm64()
iosSimulatorArm64()
}
@@ -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")
)
}
}
@@ -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<Project> {
METADATA_TARGET_NAME
)
configurePublishingWithMavenPublish(project)
project.registerKotlinArtifactsExtension()
targetsContainer.withType(AbstractKotlinTarget::class.java).all { applyUserDefinedAttributes(it) }
@@ -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<Any>()
@@ -36,12 +35,16 @@ abstract class KotlinArtifact {
abstract class KotlinNativeArtifact : KotlinArtifact() {
var modes: Set<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES
var isStatic: Boolean = false
var linkerOptions: List<String> = emptyList()
fun modes(vararg modes: NativeBuildType) {
this.modes = modes.toSet()
}
@JvmField var isStatic: Boolean = false
@JvmField var linkerOptions: List<String> = emptyList()
internal var kotlinOptionsFn: KotlinCommonToolOptions.() -> Unit = {}
fun kotlinOptions(fn: KotlinCommonToolOptions.() -> Unit) {
kotlinOptionsFn = fn
fun kotlinOptions(fn: Action<KotlinCommonToolOptions>) {
kotlinOptionsFn = fn::execute
}
internal val binaryOptions: MutableMap<String, String> = mutableMapOf()
@@ -93,34 +96,4 @@ abstract class KotlinNativeArtifact : KotlinArtifact() {
deps.forEach { dependencies.add(exportConfigurationName, it) }
return exportConfigurationName
}
}
open class ArtifactType<T : KotlinArtifact>(internal val create: () -> T)
object Library : ArtifactType<KotlinNativeLibrary>({ KotlinNativeLibrary() })
object Framework : ArtifactType<KotlinNativeFramework>({ KotlinNativeFramework() })
object FatFramework : ArtifactType<KotlinNativeFatFramework>({ KotlinNativeFatFramework() })
object XCFramework : ArtifactType<KotlinNativeXCFramework>({ 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 <T : KotlinArtifact> Project.kotlinArtifact(type: ArtifactType<T>, configure: T.() -> Unit) =
kotlinArtifact(name.replace(SAFE_NAME_PATTERN, "_"), type, configure)
@ExperimentalArtifactDsl
fun <T : KotlinArtifact> Project.kotlinArtifact(name: String, type: ArtifactType<T>, configure: T.() -> Unit) {
val artifact = type.create()
artifact.addModule(this)
configure(artifact)
if (artifact.validate(this, name)) {
artifact.registerAssembleTask(this, name)
}
}
@@ -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 <reified T : KotlinArtifact> Project.kotlinArtifact(configure: Action<T>) {
kotlinArtifact(name.replace(SAFE_NAME_PATTERN, "_"), configure)
}
private inline fun <reified T : KotlinArtifact> Project.kotlinArtifact(name: String, configure: Action<T>) {
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<KotlinNativeLibrary>) {
project.kotlinArtifact(name, configure)
}
@ExperimentalArtifactDsl
fun Library(configure: Action<KotlinNativeLibrary>) {
project.kotlinArtifact(configure)
}
@ExperimentalArtifactDsl
fun Framework(name: String, configure: Action<KotlinNativeFramework>) {
project.kotlinArtifact(name, configure)
}
@ExperimentalArtifactDsl
fun Framework(configure: Action<KotlinNativeFramework>) {
project.kotlinArtifact(configure)
}
@ExperimentalArtifactDsl
fun FatFramework(name: String, configure: Action<KotlinNativeFatFramework>) {
project.kotlinArtifact(name, configure)
}
@ExperimentalArtifactDsl
fun FatFramework(configure: Action<KotlinNativeFatFramework>) {
project.kotlinArtifact(configure)
}
@ExperimentalArtifactDsl
fun XCFramework(name: String, configure: Action<KotlinNativeXCFramework>) {
project.kotlinArtifact(name, configure)
}
@ExperimentalArtifactDsl
fun XCFramework(configure: Action<KotlinNativeXCFramework>) {
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
}
@@ -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<KonanTarget> = emptySet()
fun targets(vararg targets: KonanTarget) {
this.targets = targets.toSet()
}
var embedBitcode: BitcodeEmbeddingMode? = null
private val kind = NativeOutputKind.FRAMEWORK
@@ -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
@@ -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
@@ -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<KonanTarget> = emptySet()
fun targets(vararg targets: KonanTarget) {
this.targets = targets.toSet()
}
var embedBitcode: BitcodeEmbeddingMode? = null
private val kind = NativeOutputKind.FRAMEWORK