[Gradle] Add multiplatform extension compiler options DSL

Now the multiplatform extension exposes compiler option DSL for common
compiler arguments. This compiler option synced as a convention for
targets compiler option.

In the case of Kotlin source sets which are not used as defaultSourceSet
 in compilations - extension compiler options are synced as convention
 into those.

^KT-57292 In Progress
This commit is contained in:
Yahor Berdnikau
2023-08-01 22:24:02 +02:00
committed by Space Team
parent 41e5a31e1b
commit bc871c6cfa
13 changed files with 160 additions and 27 deletions
@@ -34,6 +34,8 @@ public abstract class org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtensi
public fun applyHierarchyTemplate (Lkotlin/jvm/functions/Function1;)V
public fun applyHierarchyTemplate (Lorg/jetbrains/kotlin/gradle/plugin/KotlinHierarchyTemplate;)V
public fun applyHierarchyTemplate (Lorg/jetbrains/kotlin/gradle/plugin/KotlinHierarchyTemplate;Lkotlin/jvm/functions/Function1;)V
public final fun compilerOptions (Lkotlin/jvm/functions/Function1;)V
public final fun compilerOptions (Lorg/gradle/api/Action;)V
public fun dependencies (Lorg/gradle/api/NamedDomainObjectProvider;Lkotlin/jvm/functions/Function1;)V
public fun getAndroidMain (Lorg/gradle/api/NamedDomainObjectContainer;)Lorg/gradle/api/NamedDomainObjectProvider;
public fun getAndroidNativeMain (Lorg/gradle/api/NamedDomainObjectContainer;)Lorg/gradle/api/NamedDomainObjectProvider;
@@ -43,6 +45,7 @@ public abstract class org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtensi
public fun getBOTH ()Lorg/jetbrains/kotlin/gradle/plugin/KotlinJsCompilerType;
public fun getCommonMain (Lorg/gradle/api/NamedDomainObjectContainer;)Lorg/gradle/api/NamedDomainObjectProvider;
public fun getCommonTest (Lorg/gradle/api/NamedDomainObjectContainer;)Lorg/gradle/api/NamedDomainObjectProvider;
public final fun getCompilerOptions ()Lorg/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerOptions;
public fun getCompilerTypeFromProperties ()Lorg/jetbrains/kotlin/gradle/plugin/KotlinJsCompilerType;
public fun getDefaultJsCompilerType ()Lorg/jetbrains/kotlin/gradle/plugin/KotlinJsCompilerType;
public fun getIR ()Lorg/jetbrains/kotlin/gradle/plugin/KotlinJsCompilerType;
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.PRESETS_API_IS_DEPRECATED_MESSAGE
import org.jetbrains.kotlin.gradle.DeprecatedTargetPresetApi
import org.jetbrains.kotlin.gradle.internal.syncCommonOptions
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinaliseDsl
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
@@ -22,6 +23,8 @@ import org.jetbrains.kotlin.gradle.plugin.hierarchy.KotlinHierarchyDslImpl
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.targets.android.internal.InternalKotlinTargetPreset
import org.jetbrains.kotlin.gradle.targets.android.internal.internal
import org.jetbrains.kotlin.gradle.utils.configureExperimentalTryK2
import org.jetbrains.kotlin.gradle.utils.newInstance
import javax.inject.Inject
@Suppress("DEPRECATION")
@@ -239,6 +242,24 @@ abstract class KotlinMultiplatformExtension
internal val rootSoftwareComponent: KotlinSoftwareComponent by lazy {
KotlinSoftwareComponentWithCoordinatesAndPublication(project, "kotlin", targets)
}
@ExperimentalKotlinGradlePluginApi
val compilerOptions: KotlinCommonCompilerOptions = project.objects
.newInstance<KotlinCommonCompilerOptionsDefault>()
.configureExperimentalTryK2(project)
.also {
syncCommonOptions(it)
}
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: KotlinCommonCompilerOptions.() -> Unit) {
configure(compilerOptions)
}
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: Action<KotlinCommonCompilerOptions>) {
configure.execute(compilerOptions)
}
}
@DeprecatedTargetPresetApi
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2023 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.internal
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptionsDefault
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptionsHelper
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.await
import org.jetbrains.kotlin.gradle.plugin.launch
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.utils.newInstance
internal fun KotlinMultiplatformExtension.syncCommonOptions(
extensionCompilerOptions: KotlinCommonCompilerOptions
) {
targets.configureEach { target ->
KotlinCommonCompilerOptionsHelper.syncOptionsAsConvention(
extensionCompilerOptions,
target.compilerOptions
)
}
project.launch {
awaitSourceSets().configureEach { kotlinSourceSet ->
val defaultLanguageSettings = kotlinSourceSet.languageSettings as DefaultLanguageSettingsBuilder
launch {
KotlinPluginLifecycle.Stage.AfterFinaliseCompilations.await()
if (!defaultLanguageSettings.compilationCompilerOptions.isCompleted) {
// For shared source sets without any associated compilation, it would be a separate instance of common compiler options
val compilerOptions = project.objects.newInstance<KotlinCommonCompilerOptionsDefault>()
KotlinCommonCompilerOptionsHelper.syncOptionsAsConvention(
extensionCompilerOptions,
compilerOptions
)
defaultLanguageSettings.compilationCompilerOptions.complete(compilerOptions)
}
}
}
}
}
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
import org.jetbrains.kotlin.gradle.utils.configureExperimentalTryK2
import org.jetbrains.kotlin.gradle.utils.newInstance
import javax.inject.Inject
@@ -42,7 +41,6 @@ abstract class KotlinMetadataTarget @Inject constructor(
@ExperimentalKotlinGradlePluginApi
override val compilerOptions: KotlinCommonCompilerOptions = project.objects
.newInstance<KotlinCommonCompilerOptionsDefault>()
.configureExperimentalTryK2(project)
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: KotlinCommonCompilerOptions.() -> Unit) {
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
import org.jetbrains.kotlin.gradle.plugin.mpp.configureSourcesPublicationAttributes
import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.gradle.utils.markConsumable
import org.jetbrains.kotlin.gradle.utils.named
@@ -68,7 +67,7 @@ fun <T : DecoratedExternalKotlinTarget> KotlinMultiplatformExtension.createExter
KotlinPlatformType.js -> project.objects.newInstance<KotlinJsCompilerOptionsDefault>()
KotlinPlatformType.common -> project.objects.newInstance<KotlinCommonCompilerOptionsDefault>()
KotlinPlatformType.native -> project.objects.newInstance<KotlinNativeCompilerOptionsDefault>()
}.configureExperimentalTryK2(project)
}
val target = ExternalKotlinTargetImpl(
project = project,
@@ -9,7 +9,6 @@ import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptionsDefault
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
@@ -22,17 +21,7 @@ import javax.inject.Inject
internal open class DefaultLanguageSettingsBuilder @Inject constructor(
@Transient private val project: Project
) : LanguageSettingsBuilder {
internal var compilationCompilerOptions: CompletableFuture<KotlinCommonCompilerOptions> = CompletableFuture()
init {
project.launch {
KotlinPluginLifecycle.Stage.AfterFinaliseCompilations.await()
if (!compilationCompilerOptions.isCompleted) {
// For shared source sets without any associated compilation, it would be a separate instance of common compiler options
compilationCompilerOptions.complete(project.objects.newInstance<KotlinCommonCompilerOptionsDefault>())
}
}
}
internal val compilationCompilerOptions: CompletableFuture<KotlinCommonCompilerOptions> = CompletableFuture()
override var languageVersion: String? = null
get() = if (compilationCompilerOptions.isCompleted) {
@@ -335,7 +335,6 @@ abstract class KotlinAndroidTarget @Inject constructor(
@ExperimentalKotlinGradlePluginApi
override val compilerOptions: KotlinJvmCompilerOptions = project.objects
.newInstance<KotlinJvmCompilerOptionsDefault>()
.configureExperimentalTryK2(project)
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: KotlinJvmCompilerOptions.() -> Unit) {
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.tasks.locateTask
import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestReport
import org.jetbrains.kotlin.gradle.testing.testTaskName
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.gradle.utils.newInstance
@@ -254,5 +253,4 @@ constructor(
override val compilerOptions: KotlinJsCompilerOptions =
project.objects
.newInstance<KotlinJsCompilerOptionsDefault>()
.configureExperimentalTryK2(project)
}
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import org.jetbrains.kotlin.gradle.targets.js.typescript.TypeScriptValidationTask
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.tasks.registerTask
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
import org.jetbrains.kotlin.gradle.utils.decamelize
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
@@ -399,7 +398,6 @@ constructor(
@ExperimentalKotlinGradlePluginApi
override val compilerOptions: KotlinJsCompilerOptions = project.objects
.newInstance<KotlinJsCompilerOptionsDefault>()
.configureExperimentalTryK2(project)
.apply {
configureJsDefaultOptions()
@@ -338,7 +338,6 @@ abstract class KotlinJvmTarget @Inject constructor(
@ExperimentalKotlinGradlePluginApi
override val compilerOptions: KotlinJvmCompilerOptions = project.objects
.newInstance<KotlinJvmCompilerOptionsDefault>()
.configureExperimentalTryK2(project)
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: KotlinJvmCompilerOptions.() -> Unit) {
@@ -9,7 +9,6 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Action
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
import org.gradle.api.file.Directory
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.provider.Provider
@@ -22,7 +21,6 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor
import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactory
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_BUILD_DIR_NAME
import org.jetbrains.kotlin.gradle.utils.configureExperimentalTryK2
import org.jetbrains.kotlin.gradle.utils.newInstance
import java.io.File
import javax.inject.Inject
@@ -66,7 +64,6 @@ abstract class KotlinWithJavaTarget<KotlinOptionsType : KotlinCommonOptions, CO
@ExperimentalKotlinGradlePluginApi
override val compilerOptions: KotlinJvmCompilerOptions = project.objects
.newInstance<KotlinJvmCompilerOptionsDefault>()
.configureExperimentalTryK2(project)
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: KotlinJvmCompilerOptions.() -> Unit) {
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.gradle.targets.native.KotlinNativeSimulatorTestRun
import org.jetbrains.kotlin.gradle.targets.native.NativeBinaryTestRunSource
import org.jetbrains.kotlin.gradle.targets.native.internal.includeCommonizedCInteropMetadata
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.utils.configureExperimentalTryK2
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
import org.jetbrains.kotlin.gradle.utils.klibModuleName
import org.jetbrains.kotlin.gradle.utils.newInstance
@@ -140,7 +139,6 @@ abstract class KotlinNativeTarget @Inject constructor(
@ExperimentalKotlinGradlePluginApi
override val compilerOptions: KotlinNativeCompilerOptions = project.objects
.newInstance<KotlinNativeCompilerOptionsDefault>()
.configureExperimentalTryK2(project)
.apply {
moduleName.convention(
project.klibModuleName(
@@ -219,6 +219,95 @@ class ProjectCompilerOptionsTests {
assertEquals(true, project.kotlinJvmTask("compileTestKotlinFake").compilerOptions.javaParameters.get())
}
@Test
fun topLevelOptions() {
val project = buildProjectWithMPP()
project.runLifecycleAwareTest {
with(multiplatformExtension) {
compilerOptions {
progressiveMode.set(true)
}
jvm()
js()
iosArm64()
linuxX64()
}
}
assertEquals(true, project.kotlinCommonTask("compileKotlinMetadata").compilerOptions.progressiveMode.get())
assertEquals(true, project.kotlinCommonTask("compileNativeMainKotlinMetadata").compilerOptions.progressiveMode.get())
assertEquals(true, project.kotlinCommonTask("compileCommonMainKotlinMetadata").compilerOptions.progressiveMode.get())
assertEquals(true, project.kotlinJvmTask("compileKotlinJvm").compilerOptions.progressiveMode.get())
assertEquals(true, project.kotlinJvmTask("compileTestKotlinJvm").compilerOptions.progressiveMode.get())
assertEquals(true, project.kotlinJsTask("compileKotlinJs").compilerOptions.progressiveMode.get())
assertEquals(true, project.kotlinJsTask("compileTestKotlinJs").compilerOptions.progressiveMode.get())
assertEquals(true, project.kotlinNativeTask("compileKotlinLinuxX64").compilerOptions.progressiveMode.get())
assertEquals(true, project.kotlinNativeTask("compileTestKotlinLinuxX64").compilerOptions.progressiveMode.get())
assertEquals(true, project.kotlinNativeTask("compileKotlinIosArm64").compilerOptions.progressiveMode.get())
assertEquals(true, project.kotlinNativeTask("compileTestKotlinIosArm64").compilerOptions.progressiveMode.get())
}
@Test
fun testTargetDslOverridesTopLevelDsl() {
val project = buildProjectWithMPP()
project.runLifecycleAwareTest {
with(multiplatformExtension) {
jvm {
compilerOptions {
languageVersion.set(KotlinVersion.KOTLIN_1_8)
}
}
compilerOptions {
languageVersion.set(KotlinVersion.KOTLIN_2_0)
}
}
}
assertEquals(KotlinVersion.KOTLIN_1_8, project.kotlinJvmTask("compileKotlinJvm").compilerOptions.languageVersion.orNull)
assertEquals(KotlinVersion.KOTLIN_1_8, project.kotlinJvmTask("compileTestKotlinJvm").compilerOptions.languageVersion.orNull)
}
@Test
fun testTaskDslOverrideTopLevelDsl() {
val project = buildProjectWithMPP()
project.runLifecycleAwareTest {
tasks.withType<KotlinJvmCompileTask>().configureEach {
if (it.name == "compileKotlinJvm") {
it.compilerOptions.languageVersion.set(KotlinVersion.KOTLIN_1_8)
}
}
with(multiplatformExtension) {
jvm()
compilerOptions {
languageVersion.set(KotlinVersion.KOTLIN_2_0)
}
}
}
assertEquals(KotlinVersion.KOTLIN_1_8, project.kotlinJvmTask("compileKotlinJvm").compilerOptions.languageVersion.orNull)
}
@Test
fun testTopLevelDslAlsoConfiguresSharedSourceSets() {
val project = buildProjectWithMPP()
project.runLifecycleAwareTest {
with(multiplatformExtension) {
jvm()
js()
compilerOptions {
languageVersion.set(KotlinVersion.KOTLIN_2_0)
}
}
}
assertEquals("2.0", project.multiplatformExtension.sourceSets.getByName("commonTest").languageSettings.languageVersion)
}
private fun Project.kotlinNativeTask(name: String): KotlinCompilationTask<KotlinNativeCompilerOptions> = tasks
.named<KotlinCompilationTask<KotlinNativeCompilerOptions>>(name)
.get()