From 800e382ba98b60a1308ebe76187639555030bc1b Mon Sep 17 00:00:00 2001 From: Yahor Berdnikau Date: Thu, 6 May 2021 17:28:19 +0200 Subject: [PATCH] Warn on using 'jdkHome' option in Gradle builds. User should instead use KotlinJavaToolchain that will take care of tracking major java version and provide nicer API. Gradle will still pass jdkHome value to the compiler, but it should be changed in Kotlin 1.6 release. ^KT-45611 Fixed --- .../arguments/K2JVMCompilerArguments.kt | 5 +++ .../kotlin/gradle/KotlinJavaToolchainTest.kt | 36 ++++++++++++++++-- .../kotlin/gradle/dsl/KotlinJvmOptions.kt | 1 + .../internal/CompilerArgumentsContributor.kt | 38 ++++++++++++++++++- .../internal/CompilerArgumentsGradleInput.kt | 2 +- .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 2 +- 6 files changed, 76 insertions(+), 8 deletions(-) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt index f27e5d0a231..4bb6c83365a 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt @@ -30,6 +30,11 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { @Argument(value = "-include-runtime", description = "Include Kotlin runtime into the resulting JAR") var includeRuntime: Boolean by FreezableVar(false) + @DeprecatedOption( + message = "This option is not working well with Gradle caching and will be removed in the future.", + removeAfter = "1.7", + level = DeprecationLevel.WARNING + ) @GradleOption(DefaultValues.StringNullDefault::class) @Argument( value = "-jdk-home", diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinJavaToolchainTest.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinJavaToolchainTest.kt index 389466a8c14..813deb9378b 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinJavaToolchainTest.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinJavaToolchainTest.kt @@ -5,13 +5,13 @@ package org.jetbrains.kotlin.gradle +import org.gradle.api.logging.LogLevel import org.gradle.internal.jvm.JavaInfo import org.gradle.internal.jvm.Jvm import org.gradle.testkit.runner.BuildResult import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.testbase.* import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test import java.io.File class KotlinJavaToolchainTest : KGPBaseTest() { @@ -213,12 +213,42 @@ class KotlinJavaToolchainTest : KGPBaseTest() { } } + @DisplayName("jdkHome Kotlin option should produce deprecation warning on Gradle builds") + @GradleTest + internal fun jdkHomeIsDeprecated(gradleVersion: GradleVersion) { + project( + projectName = "simple".fullProjectName, + gradleVersion = gradleVersion, + buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG) + ) { + //language=Groovy + rootBuildGradle.append( + """ + import org.jetbrains.kotlin.gradle.dsl.KotlinCompile + + tasks.withType(KotlinCompile).configureEach { + kotlinOptions { + jdkHome = "${getJdk9Path()}" + } + } + """.trimIndent() + ) + build("assemble") { + assertDaemonIsUsingJdk(getUserJdk().javaExecutableRealPath) + assertOutputContains("'kotlinOptions.jdkHome' is deprecated and will ignored in Kotlin 1.6!") + assertOutputContains("-jdk-home ${getJdk9().javaHome.absolutePath}") + } + } + } + private fun BuildResult.assertDaemonIsUsingJdk( javaexecPath: String ) = assertOutputContains("i: connected to the daemon. Daemon is using following 'java' executable to run itself: $javaexecPath") private fun getUserJdk(): JavaInfo = Jvm.forHome(File(System.getenv("JAVA_HOME"))) private fun getJdk9(): JavaInfo = Jvm.forHome(File(System.getenv("JDK_9"))) + // replace required for windows paths so Groovy will not complain about unexpected char '\' + private fun getJdk9Path(): String = getJdk9().javaHome.absolutePath.replace("\\", "\\\\") private val JavaInfo.javaExecutableRealPath get() = javaExecutable .toPath() @@ -229,8 +259,6 @@ class KotlinJavaToolchainTest : KGPBaseTest() { private val String.fullProjectName get() = "kotlin-java-toolchain/$this" private fun TestProject.useJdk9ToCompile() { - // replace required for windows paths so Groovy will not complain about unexpected char '\' - val jdk9Path = getJdk9().javaHome.absolutePath.replace("\\", "\\\\") //language=Groovy rootBuildGradle.append( """ @@ -241,7 +269,7 @@ class KotlinJavaToolchainTest : KGPBaseTest() { .withType(UsesKotlinJavaToolchain.class) .configureEach { it.kotlinJavaToolchain.setJdkHome( - "$jdk9Path", + "${getJdk9Path()}", JavaVersion.VERSION_1_9 ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptions.kt index f4904ee5917..c5c3fc3766d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptions.kt @@ -21,6 +21,7 @@ interface KotlinJvmOptions : org.jetbrains.kotlin.gradle.dsl.KotlinCommonOption * Include a custom JDK from the specified location into the classpath instead of the default JAVA_HOME * Default value: null */ + @Deprecated(message = "This option is not working well with Gradle caching and will be removed in the future.", level = DeprecationLevel.WARNING) var jdkHome: kotlin.String? /** diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsContributor.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsContributor.kt index a96aea2d896..898a60a0ca9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsContributor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsContributor.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.gradle.internal import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments -import org.jetbrains.kotlin.gradle.dsl.Coroutines +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl import org.jetbrains.kotlin.gradle.dsl.fillDefaultValues import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile @@ -103,6 +103,40 @@ internal open class KotlinJvmCompilerArgumentsContributor( } args.destinationAsFile = destinationDir - kotlinOptions.forEach { it?.updateArguments(args) } + warnJdkHomeNotUsed(kotlinOptions) + + kotlinOptions.forEach { it.updateArguments(args) } + } + + private fun warnJdkHomeNotUsed(kotlinOptions: List) { + kotlinOptions + .firstOrNull { it.jdkHome != null } + ?.run { + logger.warn( + """ + 'kotlinOptions.jdkHome' is deprecated and will ignored in Kotlin 1.6! + + Consider using KotlinJavaToolchain: + - Kotlin DSL: + project.tasks + .withType() + .configureEach { + it.kotlinJavaToolchain.setJdkHome( + "/path/to/your/jdk", + JavaVersion. + ) + } + - Groovy DSL + project.tasks + .withType(UsesKotlinJavaToolchain.class) + .configureEach { + it.kotlinJavaToolchain.setJdkHome( + '/path/to/your/jdk', + JavaVersion. + ) + } + """.trimIndent() + ) + } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsGradleInput.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsGradleInput.kt index 8e354fbed73..44e23cd08ba 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsGradleInput.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsGradleInput.kt @@ -51,7 +51,7 @@ internal object CompilerArgumentsGradleInput { K2JVMCompilerArguments::destination, // handled by destinationDir K2JVMCompilerArguments::classpath, // handled by classpath of the Gradle tasks K2JVMCompilerArguments::friendPaths, // is part of the classpath - K2JVMCompilerArguments::jdkHome, // JDK can be both placed differently and contain different files on user machines + K2JVMCompilerArguments::jdkHome, // Gradle takes care of running Kotlin compilation with user specified JDK K2JVMCompilerArguments::buildFile, // in Gradle build, these XMLs are transient and provide no useful info K2JVMCompilerArguments::pluginOptions, // handled specially in the task K2JVMCompilerArguments::pluginClasspaths, // handled in the task as classpath diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index dac78cd7dec..2f46d9d28cf 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -375,7 +375,7 @@ class KotlinJvmCompilerArgumentsProvider val friendPaths: FileCollection = taskProvider.friendPaths val compileClasspath: Iterable = taskProvider.classpath val destinationDir: File = taskProvider.destinationDir - internal val kotlinOptions: List = listOfNotNull( + internal val kotlinOptions: List = listOfNotNull( taskProvider.parentKotlinOptionsImpl.orNull as? KotlinJvmOptionsImpl, taskProvider.kotlinOptions as KotlinJvmOptionsImpl )