[Gradle] Introduce compilerOptions on Kotlin targets for JVM

KotlinJvmTarget, KotlinAndroidTarget, KotlinWithJavaTarget now expose
compiler options that are passed as a convention into target
compilations compiler options. Compiler options from Kotlin/JVM and
Kotlin/Android plugins compiler options are used now as convention for
target compiler options.

^KT-57292 In Progress
This commit is contained in:
Yahor Berdnikau
2023-07-30 22:10:14 +02:00
committed by Space Team
parent 38b17420c1
commit 6f394f42a6
11 changed files with 215 additions and 30 deletions
@@ -55,6 +55,52 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
}
}
@GradleTest
@DisplayName("Jvm project target compiler options DSL override project level options")
@JvmGradlePluginTests
fun jvmOptionTarget(gradleVersion: GradleVersion) {
project(
"simpleProject",
gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) {
buildGradle.appendText(
//language=Groovy
"""
|
|kotlin {
| target.compilerOptions {
| javaParameters = true
| verbose = false
| }
|
| compilerOptions {
| javaParameters = false
| verbose = false
| }
|}
""".trimMargin()
)
build("compileKotlin") {
assertTasksExecuted(":compileKotlin")
val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") }
assert(compilationArgs.contains("-java-parameters")) {
printBuildOutput()
"Compiler arguments does not contain '-progressive': $compilationArgs"
}
// '-verbose' by default will be set to 'true' by debug log level
assert(!compilationArgs.contains("-verbose")) {
printBuildOutput()
"Compiler arguments contains '-verbose': $compilationArgs"
}
}
}
}
@DisplayName("languageSettings should not override project options when not configured")
@JvmGradlePluginTests
@GradleTest
@@ -252,6 +298,54 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
}
}
@DisplayName("Android target compiler options override project level compiler options")
@AndroidGradlePluginTests
@GradleAndroidTest
fun androidProjectTargetOverrideProjectOptions(
gradleVersion: GradleVersion,
agpVersion: String,
jdk: JdkVersions.ProvidedJdk
) {
project(
"AndroidSimpleApp",
gradleVersion,
buildJdk = jdk.location,
buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion, logLevel = LogLevel.DEBUG)
) {
buildGradle.appendText(
//language=Groovy
"""
|
|kotlin {
| target.compilerOptions {
| javaParameters = true
| moduleName = "my_app"
| }
|
| compilerOptions {
| javaParameters = false
| moduleName = "other_app"
| }
|}
""".trimMargin()
)
build("compileDebugKotlin") {
assertTasksExecuted(":compileDebugKotlin")
assertOutputDoesNotContain(
"w: :compileKotlin 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!"
)
assertCompilerArguments(
":compileDebugKotlin",
"-java-parameters",
"-module-name my_app_debug"
)
}
}
}
@DisplayName("KT-59056: freeCompilerArgs are combined with android.kotlinOptions.freeCompilerArgs")
@AndroidGradlePluginTests
@GradleAndroidTest
@@ -41,7 +41,7 @@ internal open class KotlinAndroidPlugin(
kotlinAndroidExtension.target = target
project.configureCompilerOptionsForTarget(
kotlinAndroidExtension.compilerOptions,
target.compilations
target.compilerOptions
)
kotlinAndroidExtension.compilerOptions.noJdk.value(true).disallowChanges()
@@ -29,7 +29,7 @@ internal open class KotlinJvmPlugin(
internal fun Project.configureCompilerOptionsForTarget(
extensionCompilerOptions: KotlinJvmCompilerOptions,
@Suppress("DEPRECATION") compilationsContainer: NamedDomainObjectContainer<out AbstractKotlinCompilation<KotlinJvmOptions>>
targetCompilerOptions: KotlinJvmCompilerOptions
) {
extensionCompilerOptions.verbose.convention(logger.isDebugEnabled)
extensionCompilerOptions.moduleName.convention(baseModuleName())
@@ -37,17 +37,10 @@ internal open class KotlinJvmPlugin(
extensionCompilerOptions,
project
)
compilationsContainer.configureEach {
val jvmCompilerOptions = it.compilerOptions.options as KotlinJvmCompilerOptions
KotlinJvmCompilerOptionsHelper.syncOptionsAsConvention(
from = extensionCompilerOptions,
into = jvmCompilerOptions
)
jvmCompilerOptions.moduleName.convention(
it.moduleNameForCompilation(extensionCompilerOptions.moduleName)
)
}
KotlinJvmCompilerOptionsHelper.syncOptionsAsConvention(
from = extensionCompilerOptions,
into = targetCompilerOptions
)
}
}
@@ -85,7 +78,7 @@ internal open class KotlinJvmPlugin(
project.configureCompilerOptionsForTarget(
kotlinExtension.compilerOptions,
target.compilations
target.compilerOptions
)
project.pluginManager.apply(ScriptingGradleSubplugin::class.java)
@@ -0,0 +1,31 @@
/*
* 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.plugin.mpp.compilationImpl
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptionsHelper
import org.jetbrains.kotlin.gradle.plugin.mpp.DecoratedKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinCompilationImplFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.moduleNameForCompilation
internal class KotlinCompilationJvmCompilerOptionsFromTargetConfigurator(
private val targetCompilerOptions: KotlinJvmCompilerOptions
) : KotlinCompilationImplFactory.PostConfigure {
override fun configure(compilation: DecoratedKotlinCompilation<*>) {
val jvmCompilerOptions = compilation.compilerOptions.options as KotlinJvmCompilerOptions
KotlinJvmCompilerOptionsHelper.syncOptionsAsConvention(
targetCompilerOptions,
jvmCompilerOptions
)
jvmCompilerOptions.moduleName.convention(
moduleNameForCompilation(
compilation.compilationName,
targetCompilerOptions.moduleName
).orElse(compilation.moduleNameForCompilation())
)
}
}
@@ -12,8 +12,11 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.AttributeContainer
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptionsDefault
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
import org.jetbrains.kotlin.gradle.utils.forAllAndroidVariants
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
@@ -327,5 +330,19 @@ abstract class KotlinAndroidTarget @Inject constructor(
private fun filterOutAndroidAgpVersionAttribute(
attribute: Attribute<*>,
): Boolean = attribute.name != "com.android.build.api.attributes.AgpVersionAttr"
@ExperimentalKotlinGradlePluginApi
override val compilerOptions: KotlinJvmCompilerOptions = project.objects
.newInstance<KotlinJvmCompilerOptionsDefault>()
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: KotlinJvmCompilerOptions.() -> Unit) {
configure(compilerOptions)
}
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: Action<KotlinJvmCompilerOptions>) {
configure.execute(compilerOptions)
}
}
@@ -11,7 +11,9 @@ import org.jetbrains.kotlin.gradle.plugin.hierarchy.KotlinSourceSetTreeClassifie
import org.jetbrains.kotlin.gradle.plugin.hierarchy.KotlinSourceSetTreeClassifier.Property
import org.jetbrains.kotlin.gradle.plugin.hierarchy.sourceSetTreeClassifier
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.DefaultKotlinCompilationFriendPathsResolver
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.DefaultKotlinCompilationPostConfigure
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinAndroidCompilationAssociator
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationJvmCompilerOptionsFromTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.AndroidCompilationSourceSetsContainerFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinCompilationImplFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinJvmCompilerOptionsFactory
@@ -35,7 +37,11 @@ class KotlinJvmAndroidCompilationFactory internal constructor(
)
),
compilationAssociator = KotlinAndroidCompilationAssociator,
compilationSourceSetsContainerFactory = AndroidCompilationSourceSetsContainerFactory(target, variant)
compilationSourceSetsContainerFactory = AndroidCompilationSourceSetsContainerFactory(target, variant),
postConfigureAction = KotlinCompilationImplFactory.PostConfigure.composite(
DefaultKotlinCompilationPostConfigure,
KotlinCompilationJvmCompilerOptionsFromTargetConfigurator(target.compilerOptions)
)
)
override fun create(name: String): KotlinJvmAndroidCompilation {
@@ -6,19 +6,25 @@
@file:Suppress("PackageDirectoryMismatch") // Old package for compatibility
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.DefaultKotlinCompilationPostConfigure
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationJvmCompilerOptionsFromTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinJvmCompilationAssociator
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinCompilationImplFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinJvmCompilerOptionsFactory
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
open class KotlinJvmCompilationFactory internal constructor(
override val target: KotlinJvmTarget
final override val target: KotlinJvmTarget
) : KotlinCompilationFactory<KotlinJvmCompilation> {
private val compilationImplFactory: KotlinCompilationImplFactory =
KotlinCompilationImplFactory(
compilerOptionsFactory = KotlinJvmCompilerOptionsFactory,
compilationAssociator = KotlinJvmCompilationAssociator
compilationAssociator = KotlinJvmCompilationAssociator,
postConfigureAction = KotlinCompilationImplFactory.PostConfigure.composite(
DefaultKotlinCompilationPostConfigure,
KotlinCompilationJvmCompilerOptionsFromTargetConfigurator(target.compilerOptions)
)
)
override val itemClass: Class<KotlinJvmCompilation>
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.gradle.targets.jvm
import org.gradle.api.Action
import org.gradle.api.InvalidUserCodeException
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
@@ -20,6 +21,8 @@ import org.gradle.jvm.tasks.Jar
import org.gradle.language.jvm.tasks.ProcessResources
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptionsDefault
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinaliseDsl
@@ -34,8 +37,8 @@ import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmRunDsl
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmRunDslImpl
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.registerMainRunTask
import org.jetbrains.kotlin.gradle.tasks.withType
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.Future
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
import org.jetbrains.kotlin.gradle.utils.findAppliedAndroidPluginIdOrNull
import org.jetbrains.kotlin.gradle.utils.future
import org.jetbrains.kotlin.utils.addToStdlib.cast
@@ -331,5 +334,19 @@ abstract class KotlinJvmTarget @Inject constructor(
*/
private fun areRuntimeOrCompileConfigurationsAvailable(): Boolean =
GradleVersion.version(project.gradle.gradleVersion) <= GradleVersion.version("6.8.3")
@ExperimentalKotlinGradlePluginApi
override val compilerOptions: KotlinJvmCompilerOptions = project.objects
.newInstance<KotlinJvmCompilerOptionsDefault>()
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: KotlinJvmCompilerOptions.() -> Unit) {
configure(compilerOptions)
}
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: Action<KotlinJvmCompilerOptions>) {
configure.execute(compilerOptions)
}
}
@@ -9,7 +9,6 @@ import org.gradle.api.Task
import org.gradle.api.plugins.JavaBasePlugin
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.moduleNameForCompilation
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import org.jetbrains.kotlin.gradle.tasks.dependsOn
@@ -27,16 +26,6 @@ open class KotlinJvmTargetConfigurator :
super<KotlinTargetWithTestsConfigurator>.configurePlatformSpecificModel(target)
}
override fun configureCompilations(target: KotlinJvmTarget) {
super.configureCompilations(target)
target.compilations.configureEach {
it.compilerOptions.options.moduleName.convention(
it.moduleNameForCompilation()
)
}
}
override val testRunClass: Class<KotlinJvmTestRun>
get() = KotlinJvmTestRun::class.java
@@ -8,8 +8,13 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.DefaultKotlinCompilationPostConfigure
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.DefaultKotlinCompilationPreConfigure
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationJsCompilerOptionsFromTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationJvmCompilerOptionsFromTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinJvmCompilationAssociator
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.JvmWithJavaCompilationDependencyConfigurationsFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.JvmWithJavaCompilationTaskNamesContainerFactory
@@ -57,7 +62,17 @@ class KotlinWithJavaCompilationFactory<KotlinOptionsType : KotlinCommonOptions,
preConfigureAction = DefaultKotlinCompilationPreConfigure + { compilation ->
compilation.compileDependencyFiles = project.filesProvider { javaSourceSet.compileClasspath }
compilation.runtimeDependencyFiles = project.filesProvider { javaSourceSet.runtimeClasspath }
}
},
postConfigureAction = KotlinCompilationImplFactory.PostConfigure.composite(
DefaultKotlinCompilationPostConfigure,
if (target.platformType == KotlinPlatformType.js || target.platformType == KotlinPlatformType.common) {
// JS/Legacy or Common/legacy (KotlinCommonPlugin) targets uses KotlinWithJavaCompilation,
// but as they are deprecated - we are ignoring it
null
} else {
KotlinCompilationJvmCompilerOptionsFromTargetConfigurator(target.compilerOptions)
}
)
)
return project.objects.newInstance(
@@ -6,6 +6,7 @@
@file:Suppress("PackageDirectoryMismatch") // Old package for compatibility
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
@@ -14,12 +15,14 @@ import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
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.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.newInstance
import java.io.File
import javax.inject.Inject
@@ -58,6 +61,20 @@ abstract class KotlinWithJavaTarget<KotlinOptionsType : KotlinCommonOptions, CO
}
internal val buildDir: Provider<Directory> = layout.buildDirectory.dir(KOTLIN_BUILD_DIR_NAME)
@ExperimentalKotlinGradlePluginApi
override val compilerOptions: KotlinJvmCompilerOptions = project.objects
.newInstance<KotlinJvmCompilerOptionsDefault>()
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: KotlinJvmCompilerOptions.() -> Unit) {
configure(compilerOptions)
}
@ExperimentalKotlinGradlePluginApi
fun compilerOptions(configure: Action<KotlinJvmCompilerOptions>) {
configure.execute(compilerOptions)
}
}
private fun sanitizeFileName(candidate: String): String = candidate.filter { it.isLetterOrDigit() }