From 8e1c420c9f3007c46b38f22a9a6ac7153c6177df Mon Sep 17 00:00:00 2001 From: Yahor Berdnikau Date: Wed, 19 May 2021 17:43:18 +0200 Subject: [PATCH] Allow to set non-default JDK for tasks via java toolchain. Has to split jdk/toolchain setters, because, when toolchain setter is in the 'UsesKotlinJavaToolchain', Groovy fails to create meta class on - /** - * Set JDK to use for Kotlin compilation. - * - * Major JDK version is considered as compile task input. - * - * @param jdkHomeLocation path to JDK. - * *Note*: project build will fail on providing here JRE instead of JDK! - * @param jdkVersion provided JDK version - */ - fun setJdkHome( - jdkHomeLocation: File, - jdkVersion: JavaVersion - ) + @get:Internal + val jdk: JdkSetter - /** - * Set JDK to use for Kotlin compilation. - * - * @see [setJdkHome] - */ - fun setJdkHome( - jdkHomeLocation: String, - jdkVersion: JavaVersion - ) = setJdkHome(File(jdkHomeLocation), jdkVersion) + @get:Internal + val toolchain: JavaToolchainSetter + + interface JdkSetter { + /** + * Set JDK to use for Kotlin compilation. + * + * Major JDK version is considered as compile task input. + * + * @param jdkHomeLocation path to JDK. + * *Note*: project build will fail on providing here JRE instead of JDK! + * @param jdkVersion provided JDK version + */ + fun use( + jdkHomeLocation: File, + jdkVersion: JavaVersion + ) + + /** + * Set JDK to use for Kotlin compilation. + * + * @see [use] + */ + fun use( + jdkHomeLocation: String, + jdkVersion: JavaVersion + ) = use(File(jdkHomeLocation), jdkVersion) + } + + interface JavaToolchainSetter { + /** + * Set JDK obtained from [org.gradle.jvm.toolchain.JavaToolchainService] to use for Kotlin compilation. + */ + fun use( + javaLauncher: Provider + ) + } } 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 69cf00b866e..a5965ce7466 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 @@ -243,6 +243,22 @@ class KotlinJavaToolchainTest : KGPBaseTest() { } } + @DisplayName("Should allow to set JDK version for tasks via Java toolchain") + @GradleTestVersions(minVersion = "6.7") + @GradleTest + internal fun setJdkUsingJavaToolchain(gradleVersion: GradleVersion) { + project( + projectName = "simple".fullProjectName, + gradleVersion = gradleVersion, + forceOutput = true + ) { + useToolchainToCompile(11) + build("assemble") { + assertDaemonIsUsingJdk(getToolchainExecPathFromLogs()) + } + } + } + private fun BuildResult.assertDaemonIsUsingJdk( javaexecPath: String ) = assertOutputContains("i: connected to the daemon. Daemon is using following 'java' executable to run itself: $javaexecPath") @@ -270,7 +286,7 @@ class KotlinJavaToolchainTest : KGPBaseTest() { project.tasks .withType(UsesKotlinJavaToolchain.class) .configureEach { - it.kotlinJavaToolchain.setJdkHome( + it.kotlinJavaToolchain.jdk.use( "${getJdk9Path()}", JavaVersion.VERSION_1_9 ) @@ -278,4 +294,42 @@ class KotlinJavaToolchainTest : KGPBaseTest() { """.trimIndent() ) } + + private fun TestProject.useToolchainToCompile( + jdkVersion: Int + ) { + //language=Groovy + rootBuildGradle.append( + """ + import org.jetbrains.kotlin.gradle.tasks.UsesKotlinJavaToolchain + + java { + toolchain { + languageVersion.set(JavaLanguageVersion.of($jdkVersion)) + } + } + + def toolchain = project.extensions.getByType(JavaPluginExtension.class).toolchain + def service = project.extensions.getByType(JavaToolchainService.class) + def defaultLauncher = service.launcherFor(toolchain) + + project.tasks + .withType(UsesKotlinJavaToolchain.class) + .configureEach { + it.kotlinJavaToolchain.toolchain.use( + defaultLauncher + ) + } + + afterEvaluate { + logger.info("Toolchain exec path: ${'$'}{defaultLauncher.get().executablePath.asFile.absolutePath}") + } + """.trimIndent() + ) + } + + private fun BuildResult.getToolchainExecPathFromLogs() = output + .lineSequence() + .first { it.startsWith("Toolchain exec path:") } + .substringAfter("Toolchain exec path: ") } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJavaToolchainProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJavaToolchainProvider.kt index 31dc5a7abbb..adcf3e874b2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJavaToolchainProvider.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJavaToolchainProvider.kt @@ -14,6 +14,7 @@ import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.Internal import org.gradle.internal.jvm.Jvm +import org.gradle.jvm.toolchain.JavaLauncher import org.jetbrains.kotlin.gradle.utils.chainedFinalizeValueOnRead import org.jetbrains.kotlin.gradle.utils.property import org.jetbrains.kotlin.gradle.utils.propertyWithConvention @@ -82,14 +83,38 @@ abstract class KotlinJavaToolchainProvider @Inject constructor( objects.propertyWithConvention(null) }) - override fun setJdkHome( - jdkHomeLocation: File, - jdkVersion: JavaVersion - ) { - val jvm = Jvm.forHome(jdkHomeLocation) as Jvm + override val jdk: KotlinJavaToolchain.JdkSetter = DefaultJdkSetter() - javaExecutable.set(jvm.javaExecutable) - _jdkToolsJar.set(jvm.toolsJar) - _javaVersion.set(jdkVersion) + override val toolchain: KotlinJavaToolchain.JavaToolchainSetter = DefaultJavaToolchainSetter() + + private inner class DefaultJdkSetter : KotlinJavaToolchain.JdkSetter { + override fun use( + jdkHomeLocation: File, + jdkVersion: JavaVersion + ) { + val jvm = Jvm.forHome(jdkHomeLocation) as Jvm + + javaExecutable.set(jvm.javaExecutable) + _jdkToolsJar.set(jvm.toolsJar) + _javaVersion.set(jdkVersion) + } + } + + private inner class DefaultJavaToolchainSetter : KotlinJavaToolchain.JavaToolchainSetter { + override fun use( + javaLauncher: Provider + ) { + javaExecutable.set(javaLauncher.map { it.executablePath }) + _javaVersion.set( + javaLauncher.map { + JavaVersion.toVersion(it.metadata.languageVersion) + } + ) + _jdkToolsJar.set( + javaLauncher.map { + Jvm.forHome(it.metadata.installationPath.asFile).toolsJar + } + ) + } } } \ No newline at end of file