From c6fc393417c7d9bc15a4cc7c36d9a37cb5f0f7bc Mon Sep 17 00:00:00 2001 From: Yahor Berdnikau Date: Tue, 4 May 2021 17:21:36 +0200 Subject: [PATCH] Enable kotlin java toolchain support for kapt task. With this change 'KaptWithoutKotlincTask' will also support overriding default Gradle JDK to run kapt. In such case only 'in-process' kapt worker isolation mode is supported. If user does not provide custom JDK, kapt worker isolation mode will be 'no-isolation' as before. ^KT-45611 In Progress --- .../kotlin/gradle/KotlinJavaToolchainTest.kt | 107 ++++++++++++++++++ .../gradle/testbase/projectSetupDefaults.kt | 1 + .../simpleWithKapt/build.gradle | 18 +++ .../simpleWithKapt/gradle.properties | 1 + .../src/main/java/foo/InternalDummy.kt | 5 + .../src/main/java/foo/InternalDummyUser.kt | 7 ++ .../src/main/java/foo/topLevelDummyFun.kt | 3 + .../src/main/java/javaPackage/JavaClass.java | 28 +++++ .../simpleWithKapt/src/main/java/test.kt | 15 +++ .../src/test/java/example/JavaTest.java | 12 ++ .../src/test/java/foo/InternalDummyTest.kt | 12 ++ .../kotlin/gradle/internal/kapt/KaptTask.kt | 15 ++- .../internal/kapt/KaptWithKotlincTask.kt | 13 +-- .../internal/kapt/KaptWithoutKotlincTask.kt | 47 +++++--- .../tasks/KotlinJavaToolchainProvider.kt | 3 +- .../kotlin/gradle/tasks/jarSearchingUtil.kt | 16 --- 16 files changed, 255 insertions(+), 48 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/build.gradle create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/gradle.properties create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/InternalDummy.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/InternalDummyUser.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/topLevelDummyFun.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/javaPackage/JavaClass.java create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/test.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/test/java/example/JavaTest.java create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/test/java/foo/InternalDummyTest.kt 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 4172a4764ef..389466a8c14 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 @@ -11,6 +11,7 @@ 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() { @@ -106,6 +107,112 @@ class KotlinJavaToolchainTest : KGPBaseTest() { } } + @DisplayName("Kapt task should use only process worker isolation when kotlin java toolchain is set") + @GradleTest + internal fun kaptTasksShouldUseProcessWorkersIsolation(gradleVersion: GradleVersion) { + project( + projectName = "simpleWithKapt".fullProjectName, + gradleVersion = gradleVersion, + ) { + useJdk9ToCompile() + gradleProperties.append( + "kapt.workers.isolation = none" + ) + + build("assemble") { + assertDaemonIsUsingJdk(getJdk9().javaExecutableRealPath) + + assertOutputContains("Using workers PROCESS isolation mode to run kapt") + assertOutputContains("Using non-default Kotlin java toolchain - 'kapt.workers.isolation == none' property is ignored!") + } + } + } + + @DisplayName("Kapt task should use worker no-isolation mode when build is using Gradle JDK") + @GradleTest + internal fun kaptTasksShouldUseNoIsolationModeOnDefaultJvm(gradleVersion: GradleVersion) { + project( + projectName = "simpleWithKapt".fullProjectName, + gradleVersion = gradleVersion, + ) { + build("assemble") { + assertOutputContains("Using workers NONE isolation mode to run kapt") + assertOutputDoesNotContain("Using non-default Kotlin java toolchain - 'kapt.workers.isolation == none' property is ignored!") + } + } + } + + @DisplayName("Kapt tasks with custom JDK should be cacheable") + @GradleTest + internal fun kaptTasksWithCustomJdkCacheable(gradleVersion: GradleVersion) { + val buildCache = workingDir.resolve("custom-jdk-build-cache") + project( + projectName = "simpleWithKapt".fullProjectName, + gradleVersion = gradleVersion, + projectPathAdditionalSuffix = "1/cache-test", + buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true) + ) { + enableLocalBuildCache(buildCache) + useJdk9ToCompile() + + build("assemble") + } + + project( + projectName = "simpleWithKapt".fullProjectName, + gradleVersion = gradleVersion, + projectPathAdditionalSuffix = "2/cache-test", + buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true), + ) { + enableLocalBuildCache(buildCache) + useJdk9ToCompile() + + build("assemble") { + assertTasksFromCache( + ":kaptGenerateStubsKotlin", + ":kaptKotlin", + ":compileKotlin" + ) + } + } + } + + @DisplayName("Kapt tasks with default JDK and different isolation modes should be cacheable") + @GradleTest + internal fun kaptCacheableOnSwitchingIsolationModeAndDefaultJDK(gradleVersion: GradleVersion) { + val buildCache = workingDir.resolve("custom-jdk-build-cache") + project( + projectName = "simpleWithKapt".fullProjectName, + gradleVersion = gradleVersion, + projectPathAdditionalSuffix = "1/cache-test", + buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true) + ) { + enableLocalBuildCache(buildCache) + + build("assemble") + } + + project( + projectName = "simpleWithKapt".fullProjectName, + gradleVersion = gradleVersion, + projectPathAdditionalSuffix = "2/cache-test", + buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true), + ) { + enableLocalBuildCache(buildCache) + gradleProperties.append( + "kapt.workers.isolation = process" + ) + + build("assemble") { + assertTasksFromCache( + ":kaptGenerateStubsKotlin", + ":kaptKotlin", + ":compileKotlin" + ) + } + } + } + private fun BuildResult.assertDaemonIsUsingJdk( javaexecPath: String ) = assertOutputContains("i: connected to the daemon. Daemon is using following 'java' executable to run itself: $javaexecPath") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/projectSetupDefaults.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/projectSetupDefaults.kt index 8b06d3e6d85..0603c31f346 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/projectSetupDefaults.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/projectSetupDefaults.kt @@ -18,6 +18,7 @@ internal val DEFAULT_GROOVY_SETTINGS_FILE = plugins { id "org.jetbrains.kotlin.jvm" version "${'$'}kotlin_version" + id "org.jetbrains.kotlin.kapt" version "${'$'}kotlin_version" } } """.trimIndent() diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/build.gradle new file mode 100644 index 00000000000..432bbfa4ce3 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/build.gradle @@ -0,0 +1,18 @@ +plugins { + id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.kapt" + id "java" +} + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version" + kapt "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version" + testImplementation 'junit:junit:4.12' +} + +compileKotlin.kotlinOptions.allWarningsAsErrors = true \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/gradle.properties new file mode 100644 index 00000000000..dc3793168f1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/gradle.properties @@ -0,0 +1 @@ +kapt.verbose=true \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/InternalDummy.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/InternalDummy.kt new file mode 100644 index 00000000000..53727c8fd38 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/InternalDummy.kt @@ -0,0 +1,5 @@ +package foo + +internal class InternalDummy { + internal val x = "InternalDummy.x" +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/InternalDummyUser.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/InternalDummyUser.kt new file mode 100644 index 00000000000..91c469098cf --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/InternalDummyUser.kt @@ -0,0 +1,7 @@ +package foo + +internal class InternalDummyUser { + internal fun use(dummy: InternalDummy) { + if (dummy.x != "InternalDummy.x") throw AssertionError("dummy.x = ${dummy.x}") + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/topLevelDummyFun.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/topLevelDummyFun.kt new file mode 100644 index 00000000000..c8a64f12f02 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/foo/topLevelDummyFun.kt @@ -0,0 +1,3 @@ +package foo + +fun topLevelDummyFun() {} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/javaPackage/JavaClass.java b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/javaPackage/JavaClass.java new file mode 100644 index 00000000000..e0f3f6ab1e7 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/javaPackage/JavaClass.java @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javaPackage; + +public class JavaClass { + + public void test() { + System.out.println(example.TestClassGenerated.class.getName()); + System.out.println(example.SourceAnnotatedTestClassGenerated.class.getName()); + System.out.println(example.BinaryAnnotatedTestClassGenerated.class.getName()); + System.out.println(example.RuntimeAnnotatedTestClassGenerated.class.getName()); + } + +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/test.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/test.kt new file mode 100644 index 00000000000..e864bd0b3bb --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/main/java/test.kt @@ -0,0 +1,15 @@ +package example + +@example.ExampleAnnotation +@example.ExampleSourceAnnotation +@example.ExampleBinaryAnnotation +@example.ExampleRuntimeAnnotation +public class TestClass { + + @example.ExampleAnnotation + public val testVal: String = "text" + + @example.ExampleAnnotation + public fun testFunction(): TestClassGenerated = TestClassGenerated() + +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/test/java/example/JavaTest.java b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/test/java/example/JavaTest.java new file mode 100644 index 00000000000..02f59df5730 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/test/java/example/JavaTest.java @@ -0,0 +1,12 @@ +package example; + +import org.junit.Assert; +import org.junit.Test; + +public class JavaTest { + @Test + public void test() { + TestClass testClass = new TestClass(); + Assert.assertEquals("text", testClass.getTestVal()); + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/test/java/foo/InternalDummyTest.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/test/java/foo/InternalDummyTest.kt new file mode 100644 index 00000000000..bbaeb443edf --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-java-toolchain/simpleWithKapt/src/test/java/foo/InternalDummyTest.kt @@ -0,0 +1,12 @@ +package foo + +import org.junit.Test + +class InternalDummyTest { + @Test + fun testDummy() { + val dummy = InternalDummy() + val dummyUser = InternalDummyUser() + dummyUser.use(dummy) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt index 51844f37217..ece818ebc6c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt @@ -4,9 +4,11 @@ import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection import org.gradle.api.internal.ConventionTask +import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.provider.ProviderFactory +import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.api.tasks.incremental.IncrementalTaskInputs import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter @@ -17,10 +19,11 @@ import org.jetbrains.kotlin.gradle.internal.kapt.incremental.KaptIncrementalChan import org.jetbrains.kotlin.gradle.internal.kapt.incremental.UnknownSnapshot import org.jetbrains.kotlin.gradle.internal.tasks.TaskConfigurator import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.tasks.cacheOnlyIfEnabledForKotlin import org.jetbrains.kotlin.gradle.tasks.clearLocalState import org.jetbrains.kotlin.gradle.utils.getValue +import org.jetbrains.kotlin.gradle.utils.propertyWithNewInstance import java.io.File import java.util.concurrent.Callable import java.util.jar.JarFile @@ -28,9 +31,10 @@ import javax.inject.Inject @CacheableTask abstract class KaptTask @Inject constructor( - @get:Internal - protected val providerFactory: ProviderFactory -): ConventionTask(), TaskWithLocalState { + objectFactory: ObjectFactory +) : ConventionTask(), + TaskWithLocalState, + UsesKotlinJavaToolchain { open class Configurator(protected val kotlinCompileTask: KotlinCompile) : TaskConfigurator { override fun configure(task: T) { @@ -117,6 +121,9 @@ abstract class KaptTask @Inject constructor( @get:Internal abstract val classpath: ConfigurableFileCollection + final override val kotlinJavaToolchainProvider: Provider = + objectFactory.propertyWithNewInstance() + @Suppress("unused", "DeprecatedCallableAddReplaceWith") @Deprecated( message = "Don't use directly. Used only for up-to-date checks", diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithKotlincTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithKotlincTask.kt index 776e90abdaa..7e3ea01938a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithKotlincTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithKotlincTask.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.gradle.internal import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property -import org.gradle.api.provider.ProviderFactory import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.api.tasks.incremental.IncrementalTaskInputs @@ -22,17 +21,14 @@ import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector import org.jetbrains.kotlin.gradle.report.ReportingSettings import org.jetbrains.kotlin.gradle.tasks.* -import org.jetbrains.kotlin.gradle.utils.* import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray import java.io.File import javax.inject.Inject abstract class KaptWithKotlincTask @Inject constructor( - objectFactory: ObjectFactory, - providerFactory: ProviderFactory -) : KaptTask(providerFactory), - CompilerArgumentAwareWithInput, - UsesKotlinJavaToolchain{ + objectFactory: ObjectFactory +) : KaptTask(objectFactory), + CompilerArgumentAwareWithInput { class Configurator(kotlinCompileTask: KotlinCompile): KaptTask.Configurator(kotlinCompileTask) { override fun configure(task: KaptWithKotlincTask) { @@ -56,9 +52,6 @@ abstract class KaptWithKotlincTask @Inject constructor( @get:Internal val taskProvider by lazy { GradleCompileTaskProvider(this) } - final override val kotlinJavaToolchainProvider: Provider = - objectFactory.propertyWithNewInstance() - override fun createCompilerArgs(): K2JVMCompilerArguments = K2JVMCompilerArguments() @get:Internal diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt index d4cfefcc274..fd1126dcd77 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.gradle.internal import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property import org.gradle.api.provider.ProviderFactory import org.gradle.api.tasks.* @@ -23,7 +24,6 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.findKotlinStdlibClasspath -import org.jetbrains.kotlin.gradle.tasks.findToolsJar import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import org.jetbrains.kotlin.utils.PathUtil import org.slf4j.LoggerFactory @@ -34,9 +34,10 @@ import java.net.URLClassLoader import javax.inject.Inject abstract class KaptWithoutKotlincTask @Inject constructor( - providerFactory: ProviderFactory, + objectFactory: ObjectFactory, + private val providerFactory: ProviderFactory, private val workerExecutor: WorkerExecutor -) : KaptTask(providerFactory) { +) : KaptTask(objectFactory) { class Configurator(kotlinCompileTask: KotlinCompile): KaptTask.Configurator(kotlinCompileTask) { override fun configure(task: KaptWithoutKotlincTask) { @@ -157,15 +158,9 @@ abstract class KaptWithoutKotlincTask @Inject constructor( } val kaptClasspath = kaptJars.toList() + kotlinStdlibClasspath - - //TODO for gradle < 6.5 - val isolationModeStr = getValue("kapt.workers.isolation") ?: "none" - val isolationMode = when (isolationModeStr.toLowerCase()) { - "process" -> IsolationMode.PROCESS - "none" -> IsolationMode.NONE - else -> IsolationMode.NONE - } - val toolsJarURLSpec = findToolsJar()?.toURI()?.toURL()?.toString().orEmpty() + val isolationMode = getWorkerIsolationMode() + logger.info("Using workers $isolationMode isolation mode to run kapt") + val toolsJarURLSpec = kotlinJavaToolchainProvider.get().jdkToolsJar.orNull?.toURI()?.toURL()?.toString().orEmpty() submitWork( isolationMode, @@ -175,6 +170,25 @@ abstract class KaptWithoutKotlincTask @Inject constructor( ) } + private fun getWorkerIsolationMode(): IsolationMode { + val kotlinJavaToolchain = kotlinJavaToolchainProvider.get() + val gradleJvm = kotlinJavaToolchain.currentJvm.get() + // Ensuring Gradle build JDK is set to kotlin toolchain by also comparing javaExecutable paths, + // as user may set JDK with same major Java version, but from different vendor + val isRunningOnGradleJvm = gradleJvm.javaVersion == kotlinJavaToolchain.javaVersion.get() && + gradleJvm.javaExecutable.absolutePath == kotlinJavaToolchain.javaExecutable.get().asFile.absolutePath + val isolationModeStr = getValue("kapt.workers.isolation")?.toLowerCase() + return when { + (isolationModeStr == null || isolationModeStr == "none") && isRunningOnGradleJvm -> IsolationMode.NONE + else -> { + if (isolationModeStr == "none") { + logger.warn("Using non-default Kotlin java toolchain - 'kapt.workers.isolation == none' property is ignored!") + } + IsolationMode.PROCESS + } + } + } + private fun submitWork( isolationMode: IsolationMode, optionsForWorker: KaptOptionsForWorker, @@ -187,14 +201,13 @@ abstract class KaptWithoutKotlincTask @Inject constructor( // for tests it.forkOptions.jvmArgs("-verbose:class") } - logger.info("Kapt worker classpath: ${it.classpath}") - } - IsolationMode.CLASSLOADER -> workerExecutor.classLoaderIsolation() { + it.forkOptions.executable = kotlinJavaToolchainProvider.get().javaExecutable.asFile.get().absolutePath logger.info("Kapt worker classpath: ${it.classpath}") } IsolationMode.NONE -> workerExecutor.noIsolation() - IsolationMode.AUTO -> throw UnsupportedOperationException( - "Kapt worker compilation does not support $isolationMode" + IsolationMode.AUTO, IsolationMode.CLASSLOADER -> throw UnsupportedOperationException( + "Kapt worker compilation does not support class loader isolation. " + + "Please use either \"none\" or \"process\" in gradle.properties." ) } 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 f5177e7ded7..31dc5a7abbb 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 @@ -24,7 +24,8 @@ abstract class KotlinJavaToolchainProvider @Inject constructor( objects: ObjectFactory, files: ProjectLayout ) : KotlinJavaToolchain { - private val currentJvm: Property = objects + @get:Internal + internal val currentJvm: Property = objects .property(Jvm.current()) .chainedFinalizeValueOnRead() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt index 066d981b157..8ca8627f877 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.gradle.tasks -import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ResolvedDependency @@ -104,21 +103,6 @@ internal fun findKotlinScriptRuntimeClasspath(project: Project): List = internal fun findKotlinReflectClasspath(project: Project): List = findKotlinModuleJar(project, KOTLIN_REFLECT_EXPECTED_CLASS, KOTLIN_REFLECT) -internal fun findToolsJar(): File? { - val javacUtilContextClass = - try { - Class.forName("com.sun.tools.javac.util.Context") - } catch (classNotFound: ClassNotFoundException) { - val javaHome = System.getProperty("java.home") // current Java installation path - throw GradleException( - "Kotlin could not find the required JDK tools in the Java installation ${javaHome?.let { "'$it' " }.orEmpty()}" + - "used by Gradle. Make sure Gradle is running on a JDK, not JRE.", - classNotFound - ) - } - return javacUtilContextClass?.let(::findJarByClass) -} - internal fun findJarByClass(klass: Class<*>): File? { val classFileName = klass.name.substringAfterLast(".") + ".class" val resource = klass.getResource(classFileName) ?: return null