[Gradle] Introduce compilerOptions for Kotlin external target

Kotlin external target now properly exposes compilerOptions which could
be used by target users to configure target compilations compiler
options.

^KT-57292 In Progress
This commit is contained in:
Yahor Berdnikau
2023-08-01 10:26:10 +02:00
committed by Space Team
parent c1e26bfa47
commit 7dfbf28d93
8 changed files with 178 additions and 13 deletions
@@ -6,17 +6,26 @@ plugins {
dependencies {
compileOnly(gradleKotlinDsl())
compileOnly("com.android.tools.build:gradle:7.2.1")
compileOnly(project(":kotlin-gradle-plugin"))
compileOnly(project(":kotlin-gradle-plugin")) {
capabilities {
requireCapability("org.jetbrains.kotlin:kotlin-gradle-plugin-common")
}
}
compileOnly(project(":kotlin-gradle-plugin-api")) {
capabilities {
requireCapability("org.jetbrains.kotlin:kotlin-gradle-plugin-api-common")
}
}
compileOnly(project(":kotlin-gradle-plugin-idea"))
}
configureKotlinCompileTasksGradleCompatibility()
kotlin {
sourceSets.all {
languageSettings.optIn("org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi")
compilerOptions {
optIn.add("org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi")
/* Workaround for KT-54823 */
languageSettings.optIn("org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi")
optIn.add("org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi")
}
}
@@ -5,8 +5,11 @@
package org.jetbrains.kotlin.gradle.android
import org.gradle.api.Action
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.kotlin.dsl.getByType
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.external.DecoratedExternalKotlinTarget
@@ -23,4 +26,18 @@ class PrototypeAndroidTarget(
@Suppress("unchecked_cast")
override val compilations: NamedDomainObjectContainer<PrototypeAndroidCompilation>
get() = super.compilations as NamedDomainObjectContainer<PrototypeAndroidCompilation>
@ExperimentalKotlinGradlePluginApi
override val compilerOptions: KotlinJvmCompilerOptions
get() = super.compilerOptions as KotlinJvmCompilerOptions
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: KotlinJvmCompilerOptions.() -> Unit) {
configure(compilerOptions)
}
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: Action<KotlinJvmCompilerOptions>) {
configure.execute(compilerOptions)
}
}
@@ -734,6 +734,7 @@ public class org/jetbrains/kotlin/gradle/plugin/mpp/external/DecoratedExternalKo
public fun getArtifactsTaskName ()Ljava/lang/String;
public fun getAttributes ()Lorg/gradle/api/attributes/AttributeContainer;
public fun getCompilations ()Lorg/gradle/api/NamedDomainObjectContainer;
public fun getCompilerOptions ()Lorg/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerOptions;
public fun getComponents ()Ljava/util/Set;
public fun getDisambiguationClassifier ()Ljava/lang/String;
public synthetic fun getExtras ()Lorg/jetbrains/kotlin/tooling/core/Extras;
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.external
import org.gradle.api.artifacts.Configuration
import org.gradle.api.logging.Logger
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
@@ -30,6 +30,19 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinTarget
* // Covariant override that allows for narrowing the type of compilations that this target contains
* override val compilations: NamedDomainObjectContainer<MyCustomCompilationType>
* get() = super.compilations as NamedDomainObjectContainer<MyCustomCompilationType>
*
* // Covariant override of target compiler options that should be used to configure all target compilation compiler options
* override val compilerOptions: KotlinJvmCompilerOptions
* get() = super.compilerOptions as KotlinJvmCompilerOptions
*
* // Optionally follow api exposed in Kotlin built-in targets to configure compiler options
* fun compilerOptions(configure: KotlinJvmCompilerOptions.() -> Unit) {
* configure(compilerOptions)
* }
*
* fun compilerOptions(configure: Action<KotlinJvmCompilerOptions>) {
* configure.execute(compilerOptions)
* }
* }
* ```
*
@@ -14,6 +14,7 @@ import org.gradle.api.logging.Logging
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
@@ -27,6 +28,7 @@ internal class ExternalKotlinTargetImpl internal constructor(
override val targetName: String,
override val platformType: KotlinPlatformType,
override val publishable: Boolean,
override val compilerOptions: KotlinCommonCompilerOptions,
val apiElementsConfiguration: Configuration,
val runtimeElementsConfiguration: Configuration,
val sourcesElementsConfiguration: Configuration,
@@ -12,7 +12,11 @@ import org.gradle.api.attributes.Category
import org.gradle.api.attributes.Usage
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptionsDefault
import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompilerOptionsDefault
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptionsDefault
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.ide.kotlinIdeMultiplatformImport
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
@@ -22,6 +26,7 @@ import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.gradle.utils.markConsumable
import org.jetbrains.kotlin.gradle.utils.named
import org.jetbrains.kotlin.gradle.utils.newInstance
/**
* Creates an adhoc/external Kotlin Target which can be maintained and evolved outside the kotlin.git repository.
@@ -55,11 +60,21 @@ fun <T : DecoratedExternalKotlinTarget> KotlinMultiplatformExtension.createExter
target.project.locateOrRegisterTask<Jar>(lowerCamelCaseName(descriptor.targetName, "jar"))
}
val compilerOptions = when (descriptor.platformType) {
KotlinPlatformType.androidJvm,
KotlinPlatformType.jvm -> project.objects.newInstance<KotlinJvmCompilerOptionsDefault>()
KotlinPlatformType.wasm,
KotlinPlatformType.js -> project.objects.newInstance<KotlinJsCompilerOptionsDefault>()
KotlinPlatformType.common -> project.objects.newInstance<KotlinCommonCompilerOptionsDefault>()
KotlinPlatformType.native -> project.objects.newInstance<KotlinNativeCompilerOptionsDefault>()
}
val target = ExternalKotlinTargetImpl(
project = project,
targetName = descriptor.targetName,
platformType = descriptor.platformType,
publishable = true,
compilerOptions = compilerOptions,
apiElementsConfiguration = apiElementsConfiguration,
runtimeElementsConfiguration = runtimeElementsConfiguration,
sourcesElementsConfiguration = sourcesElementsConfiguration,
@@ -70,6 +85,8 @@ fun <T : DecoratedExternalKotlinTarget> KotlinMultiplatformExtension.createExter
artifactsTaskLocator = artifactsTaskLocator
)
target.wireCompilerOptionsToCompilations(descriptor.platformType)
target.setupApiElements(apiElementsConfiguration)
target.setupApiElements(apiElementsPublishedConfiguration)
target.setupRuntimeElements(runtimeElementsConfiguration)
@@ -130,3 +147,42 @@ private fun ExternalKotlinTargetImpl.setupRuntimeElements(configuration: Configu
private fun ExternalKotlinTargetImpl.setupSourcesElements(configuration: Configuration) {
configuration.configureSourcesPublicationAttributes(this)
}
private fun ExternalKotlinTargetImpl.wireCompilerOptionsToCompilations(platformType: KotlinPlatformType) {
when (platformType) {
KotlinPlatformType.androidJvm,
KotlinPlatformType.jvm -> {
compilations.configureEach {
KotlinJvmCompilerOptionsHelper.syncOptionsAsConvention(
compilerOptions as KotlinJvmCompilerOptions,
it.compilerOptions.options as KotlinJvmCompilerOptions
)
}
}
KotlinPlatformType.wasm,
KotlinPlatformType.js -> {
compilations.configureEach {
KotlinJsCompilerOptionsHelper.syncOptionsAsConvention(
compilerOptions as KotlinJsCompilerOptions,
it.compilerOptions.options as KotlinJsCompilerOptions
)
}
}
KotlinPlatformType.common -> {
compilations.configureEach {
KotlinCommonCompilerOptionsHelper.syncOptionsAsConvention(
compilerOptions,
it.compilerOptions.options
)
}
}
KotlinPlatformType.native -> {
compilations.configureEach {
KotlinNativeCompilerOptionsHelper.syncOptionsAsConvention(
compilerOptions as KotlinNativeCompilerOptions,
it.compilerOptions.options as KotlinNativeCompilerOptions
)
}
}
}
}
@@ -6,14 +6,15 @@
package org.jetbrains.kotlin.gradle.unitTests
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.external.createCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.external.createExternalKotlinTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile as KotlinJvmCompileTask
import org.jetbrains.kotlin.gradle.tasks.withType
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
import org.jetbrains.kotlin.gradle.util.*
import org.jetbrains.kotlin.gradle.utils.named
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -174,6 +175,50 @@ class ProjectCompilerOptionsTests {
assertEquals(false, project.kotlinCommonTask("compileKotlinMetadata").compilerOptions.progressiveMode.get())
}
@Test
fun externalTargetDsl() {
val project = buildProjectWithMPP()
project.runLifecycleAwareTest {
with(multiplatformExtension) {
val target = createExternalKotlinTarget<FakeTarget> { defaults() }
target.createCompilation<FakeCompilation> { defaults(this@with) }
target.createCompilation<FakeCompilation> { defaults(this@with, "test") }
target.compilerOptions {
javaParameters.set(true)
}
}
}
assertEquals(true, project.kotlinJvmTask("compileFakeKotlinFake").compilerOptions.javaParameters.get())
assertEquals(true, project.kotlinJvmTask("compileTestKotlinFake").compilerOptions.javaParameters.get())
}
@Test
fun externalTaskOptionsOverridesTargetOptions() {
val project = buildProjectWithMPP()
project.runLifecycleAwareTest {
tasks.withType<KotlinJvmCompileTask>().configureEach {
if (it.name == "compileFakeKotlinFake") {
it.compilerOptions.javaParameters.set(false)
}
}
with(multiplatformExtension) {
val target = createExternalKotlinTarget<FakeTarget> { defaults() }
target.createCompilation<FakeCompilation> { defaults(this@with) }
target.createCompilation<FakeCompilation> { defaults(this@with, "test") }
target.compilerOptions {
javaParameters.set(true)
}
}
}
assertEquals(false, project.kotlinJvmTask("compileFakeKotlinFake").compilerOptions.javaParameters.get())
assertEquals(true, project.kotlinJvmTask("compileTestKotlinFake").compilerOptions.javaParameters.get())
}
private fun Project.kotlinNativeTask(name: String): KotlinCompilationTask<KotlinNativeCompilerOptions> = tasks
.named<KotlinCompilationTask<KotlinNativeCompilerOptions>>(name)
.get()
@@ -182,6 +227,10 @@ class ProjectCompilerOptionsTests {
.named<KotlinCompilationTask<KotlinJsCompilerOptions>>(name)
.get()
private fun Project.kotlinJvmTask(name: String): KotlinCompilationTask<KotlinJvmCompilerOptions> = tasks
.named<KotlinCompilationTask<KotlinJvmCompilerOptions>>(name)
.get()
private fun Project.kotlinCommonTask(name: String): KotlinCompilationTask<KotlinCommonCompilerOptions> = tasks
.named<KotlinCompilationTask<KotlinCommonCompilerOptions>>(name)
.get()
@@ -5,14 +5,32 @@
package org.jetbrains.kotlin.gradle.util
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.gradle.api.NamedDomainObjectContainer
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.external.*
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinCompilationDescriptor.CompilationFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetDescriptor.TargetFactory
class FakeCompilation(delegate: Delegate) : DecoratedExternalKotlinCompilation(delegate)
class FakeTarget(delegate: Delegate) : DecoratedExternalKotlinTarget(delegate)
class FakeCompilation(delegate: Delegate) : DecoratedExternalKotlinCompilation(delegate) {
@Suppress("UNCHECKED_CAST")
override val compilerOptions: HasCompilerOptions<KotlinJvmCompilerOptions>
get() = super.compilerOptions as HasCompilerOptions<KotlinJvmCompilerOptions>
}
class FakeTarget(delegate: Delegate) : DecoratedExternalKotlinTarget(delegate) {
@Suppress("UNCHECKED_CAST")
override val compilations: NamedDomainObjectContainer<FakeCompilation>
get() = super.compilations as NamedDomainObjectContainer<FakeCompilation>
override val compilerOptions: KotlinJvmCompilerOptions
get() = super.compilerOptions as KotlinJvmCompilerOptions
fun compilerOptions(configure: KotlinJvmCompilerOptions.() -> Unit) {
configure(compilerOptions)
}
}
fun ExternalKotlinTargetDescriptorBuilder<FakeTarget>.defaults() {
targetName = "fake"