Expose task input to control jvm target validation mode

^KT-56971 Fixed
This commit is contained in:
Yahor Berdnikau
2023-04-18 19:49:18 +02:00
committed by Space Team
parent 861e9392de
commit 50f5fadfd8
7 changed files with 110 additions and 12 deletions
@@ -563,6 +563,14 @@ public final class org/jetbrains/kotlin/gradle/dsl/KotlinVersion$Companion {
public final fun getDEFAULT ()Lorg/jetbrains/kotlin/gradle/dsl/KotlinVersion;
}
public final class org/jetbrains/kotlin/gradle/dsl/jvm/JvmTargetValidationMode : java/lang/Enum {
public static final field ERROR Lorg/jetbrains/kotlin/gradle/dsl/jvm/JvmTargetValidationMode;
public static final field IGNORE Lorg/jetbrains/kotlin/gradle/dsl/jvm/JvmTargetValidationMode;
public static final field WARNING Lorg/jetbrains/kotlin/gradle/dsl/jvm/JvmTargetValidationMode;
public static fun valueOf (Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/dsl/jvm/JvmTargetValidationMode;
public static fun values ()[Lorg/jetbrains/kotlin/gradle/dsl/jvm/JvmTargetValidationMode;
}
public abstract class org/jetbrains/kotlin/gradle/plugin/AbstractCompileWithDependenciesTracking : org/gradle/api/tasks/compile/AbstractCompile {
public fun <init> ()V
public fun isDependentTaskOutOfDate (Lorg/gradle/api/Task;)Z
@@ -1607,6 +1615,7 @@ public final class org/jetbrains/kotlin/gradle/tasks/KotlinJavaToolchain$JdkSett
}
public abstract interface class org/jetbrains/kotlin/gradle/tasks/KotlinJvmCompile : org/jetbrains/kotlin/gradle/dsl/KotlinCompile, org/jetbrains/kotlin/gradle/tasks/BaseKotlinCompile, org/jetbrains/kotlin/gradle/tasks/KotlinCompilationTask {
public abstract fun getJvmTargetValidationMode ()Lorg/gradle/api/provider/Property;
public abstract fun getModuleName ()Lorg/gradle/api/provider/Property;
public abstract fun getParentKotlinOptions ()Lorg/gradle/api/provider/Property;
}
@@ -0,0 +1,30 @@
/*
* 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.dsl.jvm
/**
* Controls JVM target validation mode between Kotlin JVM compilation task from this plugin and related Java compilation task from Gradle.
*
* See [org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile.jvmTargetValidationMode] for more details.
*
* @since 1.9.0
*/
enum class JvmTargetValidationMode {
/**
* Ignores JVM target mismatches and proceeds with compilation.
*/
IGNORE,
/**
* Produces a warning message in the console output on JVM target mismatch and proceeds with compilation.
*/
WARNING,
/**
* Throws an exception on JVM target mismatch and stops execution.
*/
ERROR,
}
@@ -16,6 +16,7 @@ import org.gradle.api.tasks.util.PatternFilterable
import org.gradle.work.Incremental
import org.gradle.work.NormalizeLineEndings
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.jvm.JvmTargetValidationMode
import org.jetbrains.kotlin.gradle.plugin.CompilerPluginConfig
interface KotlinCompileTool : PatternFilterable, Task {
@@ -96,6 +97,28 @@ interface KotlinJvmCompile : BaseKotlinCompile,
replaceWith = ReplaceWith("compilerOptions")
)
val parentKotlinOptions: Property<KotlinJvmOptionsDeprecated>
/**
* Controls JVM target validation mode between this task and the Java compilation task from Gradle for the same source set.
*
* The same JVM targets ensure that the produced jar file contains class files of the same JVM bytecode version,
* which is important to avoid compatibility issues for the code consumers.
*
* Also, Gradle Java compilation task [org.gradle.api.tasks.compile.JavaCompile.targetCompatibility] controls value
* of "org.gradle.jvm.version" [attribute](https://docs.gradle.org/current/javadoc/org/gradle/api/attributes/java/TargetJvmVersion.html)
* which itself controls the produced artifact minimal supported JVM version via
* [Gradle Module Metadata](https://docs.gradle.org/current/userguide/publishing_gradle_module_metadata.html).
* This allows Gradle to check compatibility of dependencies at dependency resolution time.
*
* To avoid problems with different targets we advise to use [JDK Toolchain](https://kotl.in/gradle/jvm/toolchain) feature.
*
* Default value for builds with Gradle <8.0 is [JvmTargetValidationMode.WARNING],
* while for builds with Gradle 8.0+ it is [JvmTargetValidationMode.ERROR].
*
* @since 1.9.0
*/
@get:Input
val jvmTargetValidationMode: Property<JvmTargetValidationMode>
}
interface KaptGenerateStubs : KotlinJvmCompile {
@@ -51,6 +51,45 @@ class JvmTargetValidationTest : KGPBaseTest() {
}
}
@DisplayName("Should allow to override validation mode for specific task")
@GradleTest
internal fun overrideModeForTask(gradleVersion: GradleVersion) {
project(
projectName = "kotlinJavaProject".fullProjectName,
gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.WARN)
) {
setJavaCompilationCompatibility(JavaVersion.VERSION_1_8)
useToolchainToCompile(11)
gradleProperties.append(
"""
kotlin.jvm.target.validation.mode = error
""".trimIndent()
)
buildGradle.appendText(
//language=groovy
"""
|
|tasks.named("compileKotlin", org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile.class) {
| jvmTargetValidationMode.set(org.jetbrains.kotlin.gradle.dsl.jvm.JvmTargetValidationMode.IGNORE)
|}
""".trimMargin()
)
build("assemble") {
assertOutputDoesNotContain(
"'compileJava' task (current target is 1.8) and 'compileKotlin' task (current target is 11) jvm target compatibility " +
"should be set to the same Java version.\n" +
"By default will become an error since Gradle 8.0+! " +
"Read more: https://kotl.in/gradle/jvm/target-validation\n" +
"Consider using JVM toolchain: https://kotl.in/gradle/jvm/toolchain"
)
}
}
}
@DisplayName("Should warn in the build log if verification mode is 'warning' and kotlin and java targets are different")
@GradleTest
internal fun shouldWarnBuildIfJavaAndKotlinJvmTargetsAreDifferent(gradleVersion: GradleVersion) {
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.cli.common.toBooleanLenient
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
import org.jetbrains.kotlin.gradle.dsl.NativeCacheOrchestration
import org.jetbrains.kotlin.gradle.dsl.jvm.JvmTargetValidationMode
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessageOutputStreamHandler.Companion.IGNORE_TCSM_OVERFLOW
import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.Companion.jsCompilerProperty
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_JS_STDLIB_DOM_API_INCLUDED
@@ -479,10 +480,6 @@ internal class PropertiesProvider private constructor(private val project: Proje
val kotlinOptionsSuppressFreeArgsModificationWarning: Boolean
get() = booleanProperty(PropertyNames.KOTLIN_OPTIONS_SUPPRESS_FREEARGS_MODIFICATION_WARNING) ?: false
enum class JvmTargetValidationMode {
IGNORE, WARNING, ERROR
}
val jvmTargetValidationMode: JvmTargetValidationMode
get() = enumProperty(
"kotlin.jvm.target.validation.mode",
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptionsHelper
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
import org.jetbrains.kotlin.gradle.dsl.jvm.JvmTargetValidationMode
import org.jetbrains.kotlin.gradle.dsl.usesK2
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
import org.jetbrains.kotlin.gradle.logging.GradleErrorMessageCollector
@@ -39,7 +40,6 @@ import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.CreateCompilerArgumentsContext.Companion.create
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
import org.jetbrains.kotlin.gradle.report.BuildReportMode
import org.jetbrains.kotlin.gradle.tasks.internal.KotlinJvmOptionsCompat
@@ -165,9 +165,6 @@ abstract class KotlinCompile @Inject constructor(
@get:Internal
internal abstract val associatedJavaCompileTaskName: Property<String>
@get:Input
internal abstract val jvmTargetValidationMode: Property<PropertiesProvider.JvmTargetValidationMode>
@get:Internal
internal val nagTaskModuleNameUsage: Property<Boolean> = objectFactory.propertyWithConvention(false)
@@ -368,6 +365,9 @@ abstract class KotlinCompile @Inject constructor(
private fun validateKotlinAndJavaHasSameTargetCompatibility(
args: K2JVMCompilerArguments,
) {
val jvmTargetValidationMode: JvmTargetValidationMode = jvmTargetValidationMode.get()
if (jvmTargetValidationMode == JvmTargetValidationMode.IGNORE) return
associatedJavaCompileTaskTargetCompatibility.orNull?.let { targetCompatibility ->
val normalizedJavaTarget = when (targetCompatibility) {
"6" -> "1.6"
@@ -392,9 +392,9 @@ abstract class KotlinCompile @Inject constructor(
appendLine("Consider using JVM toolchain: https://kotl.in/gradle/jvm/toolchain")
}
when (jvmTargetValidationMode.get()) {
PropertiesProvider.JvmTargetValidationMode.ERROR -> throw GradleException(errorMessage)
PropertiesProvider.JvmTargetValidationMode.WARNING -> logger.warn(errorMessage)
when (jvmTargetValidationMode) {
JvmTargetValidationMode.ERROR -> throw GradleException(errorMessage)
JvmTargetValidationMode.WARNING -> logger.warn(errorMessage)
else -> Unit
}
}
@@ -43,7 +43,7 @@ internal open class BaseKotlinCompileConfig<TASK : KotlinCompile> : AbstractKotl
taskProvider.configure { task ->
task.incremental = propertiesProvider.incrementalJvm ?: true
task.usePreciseJavaTracking = propertiesProvider.usePreciseJavaTracking ?: true
task.jvmTargetValidationMode.set(propertiesProvider.jvmTargetValidationMode)
task.jvmTargetValidationMode.convention(propertiesProvider.jvmTargetValidationMode).finalizeValueOnRead()
task.useKotlinAbiSnapshot.value(propertiesProvider.useKotlinAbiSnapshot).disallowChanges()
task.classpathSnapshotProperties.useClasspathSnapshot.value(useClasspathSnapshot).disallowChanges()