Fix Kotlin common or js compilation could spawn second Kotlin daemon

Kotlin's daemons spawned by js/common compilation where incompatible
on JDK 1.8, because of 'tools.jar' presence mismatch. Now KGP always
passes tools.jar location to Kotlin daemon.

^KT-52622 Fixed
This commit is contained in:
Yahor Berdnikau
2022-07-04 12:24:26 +02:00
committed by Space
parent 99844be96c
commit 6a8da8f9eb
10 changed files with 93 additions and 76 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.gradle
import org.gradle.api.JavaVersion
import org.gradle.api.logging.LogLevel
import org.gradle.testkit.runner.BuildResult
import org.gradle.tooling.internal.consumer.ConnectorServices
@@ -119,6 +120,23 @@ class KotlinDaemonIT : KGPDaemonsBaseTest() {
}
}
@DisplayName("Kotlin daemon should be reused in mixed Kotlin JVM/JS project")
@JdkVersions(versions = [JavaVersion.VERSION_1_8, JavaVersion.VERSION_11])
@GradleWithJdkTest
fun jsAndJvmCompatibleDaemons(gradleVersion: GradleVersion, jdk: JdkVersions.ProvidedJdk) {
project(
"jvmAndJsProject",
gradleVersion,
buildJdk = jdk.location
) {
build(":jsLib:assemble")
build("jvmLib:assemble") {
assertKotlinDaemonReusesOnlyOneSession()
}
}
}
private fun BuildResult.assertGradleClasspathNotLeaked() {
assertOutputContains("Kotlin compiler classpath:")
val daemonClasspath = output
@@ -0,0 +1,6 @@
subprojects {
repositories {
mavenLocal()
mavenCentral()
}
}
@@ -0,0 +1,3 @@
plugins {
id "org.jetbrains.kotlin.js"
}
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2022 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 hello.printer
fun printHelloInJs(name: String) {
println("Hello, ${name}-nil!")
}
@@ -0,0 +1,3 @@
plugins {
id "org.jetbrains.kotlin.jvm"
}
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2022 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 hello.printer
fun printHello(name: String) {
println("Hello, $name!")
}
@@ -79,20 +79,19 @@ internal abstract class DefaultKotlinJavaToolchain @Inject constructor(
): Provider<File?> {
return objects
.propertyWithConvention(
jvmProvider.flatMap { jvm ->
objects.propertyWithConvention(jvm.toolsJar)
javaVersionProvider.flatMap { javaVersion ->
jvmProvider.map { jvm ->
jvm.toolsJar.also {
if (it == null && javaVersion < JavaVersion.VERSION_1_9) {
throw GradleException(
"Kotlin could not find the required JDK tools in the Java installation. " +
"Make sure Kotlin compilation is running on a JDK, not JRE."
)
}
}
}
}
)
.orElse(javaVersionProvider.flatMap {
if (it < JavaVersion.VERSION_1_9) {
throw GradleException(
"Kotlin could not find the required JDK tools in the Java installation. " +
"Make sure Kotlin compilation is running on a JDK, not JRE."
)
} else {
objects.propertyWithConvention<File?>(null)
}
})
}
@get:Internal
@@ -18,19 +18,15 @@ package org.jetbrains.kotlin.gradle.tasks
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
import org.gradle.work.InputChanges
import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments
import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
import org.jetbrains.kotlin.gradle.utils.propertyWithConvention
import java.io.File
import javax.inject.Inject
@@ -39,23 +35,9 @@ abstract class KotlinCompileCommon @Inject constructor(
override val kotlinOptions: KotlinMultiplatformCommonOptions,
workerExecutor: WorkerExecutor,
objectFactory: ObjectFactory
) : AbstractKotlinCompile<K2MetadataCompilerArguments>(objectFactory),
) : AbstractKotlinCompile<K2MetadataCompilerArguments>(objectFactory, workerExecutor),
KotlinCommonCompile {
override val compilerRunner: Provider<GradleCompilerRunner> =
objectFactory.propertyWithConvention(
gradleCompileTaskProvider.map {
GradleCompilerRunnerWithWorkers(
it,
null,
normalizedKotlinDaemonJvmArguments.orNull,
metrics.get(),
compilerExecutionStrategy.get(),
workerExecutor
)
}
)
override fun createCompilerArgs(): K2MetadataCompilerArguments =
K2MetadataCompilerArguments()
@@ -153,7 +153,7 @@ abstract class AbstractKotlinCompileTool<T : CommonToolArguments> @Inject constr
}
@get:Internal
override val metrics: Property<BuildMetricsReporter> = project.objects
final override val metrics: Property<BuildMetricsReporter> = project.objects
.property(BuildMetricsReporterImpl())
/**
@@ -228,7 +228,8 @@ abstract class GradleCompileTaskProvider @Inject constructor(
}
abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constructor(
objectFactory: ObjectFactory
objectFactory: ObjectFactory,
workerExecutor: WorkerExecutor
) : AbstractKotlinCompileTool<T>(objectFactory),
CompileUsingKotlinDaemonWithNormalization,
BaseKotlinCompile {
@@ -323,16 +324,31 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constr
)
@get:Internal
internal open val compilerRunner: Provider<GradleCompilerRunner> =
internal open val defaultKotlinJavaToolchain: Provider<DefaultKotlinJavaToolchain> = objectFactory
.propertyWithNewInstance({ null })
@get:Internal
internal val compilerRunner: Provider<GradleCompilerRunner> =
objectFactory.propertyWithConvention(
gradleCompileTaskProvider.map {
GradleCompilerRunner(
it,
null,
normalizedKotlinDaemonJvmArguments.orNull,
metrics.get(),
compilerExecutionStrategy.get(),
)
gradleCompileTaskProvider.flatMap { taskProvider ->
compilerExecutionStrategy
.zip(metrics) { executionStrategy, metrics ->
metrics to executionStrategy
}
.flatMap { params ->
defaultKotlinJavaToolchain
.map {
val toolsJar = it.currentJvmJdkToolsJar.orNull
GradleCompilerRunnerWithWorkers(
taskProvider,
toolsJar,
normalizedKotlinDaemonJvmArguments.orNull,
params.first,
params.second,
workerExecutor
)
}
}
}
)
@@ -502,7 +518,7 @@ abstract class KotlinCompile @Inject constructor(
override val kotlinOptions: KotlinJvmOptions,
workerExecutor: WorkerExecutor,
private val objectFactory: ObjectFactory
) : AbstractKotlinCompile<K2JVMCompilerArguments>(objectFactory),
) : AbstractKotlinCompile<K2JVMCompilerArguments>(objectFactory, workerExecutor),
@Suppress("TYPEALIAS_EXPANSION_DEPRECATION") KotlinJvmCompileDsl,
UsesKotlinJavaToolchain {
@@ -575,28 +591,11 @@ abstract class KotlinCompile @Inject constructor(
get() = classpathSnapshotProperties.classpathSnapshotDir.orNull?.asFile?.let { listOf(it) } ?: emptyList()
@get:Internal
internal val defaultKotlinJavaToolchain: Provider<DefaultKotlinJavaToolchain> = objectFactory
final override val defaultKotlinJavaToolchain: Provider<DefaultKotlinJavaToolchain> = objectFactory
.propertyWithNewInstance({ this })
final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchain> = defaultKotlinJavaToolchain.cast()
@get:Internal
override val compilerRunner: Provider<GradleCompilerRunner> = objectFactory.propertyWithConvention(
// From Gradle 6.6 better to replace flatMap with provider.zip()
defaultKotlinJavaToolchain.flatMap { toolchain ->
objectFactory.property(gradleCompileTaskProvider.map {
GradleCompilerRunnerWithWorkers(
it,
toolchain.currentJvmJdkToolsJar.orNull,
normalizedKotlinDaemonJvmArguments.orNull,
metrics.get(),
compilerExecutionStrategy.get(),
workerExecutor
)
})
}
)
@get:Internal
internal abstract val associatedJavaCompileTaskTargetCompatibility: Property<String>
@@ -866,7 +865,7 @@ abstract class Kotlin2JsCompile @Inject constructor(
override val kotlinOptions: KotlinJsOptions,
objectFactory: ObjectFactory,
workerExecutor: WorkerExecutor
) : AbstractKotlinCompile<K2JSCompilerArguments>(objectFactory),
) : AbstractKotlinCompile<K2JSCompilerArguments>(objectFactory, workerExecutor),
KotlinJsCompile {
init {
@@ -923,20 +922,6 @@ abstract class Kotlin2JsCompile @Inject constructor(
@get:Optional
abstract val optionalOutputFile: RegularFileProperty
override val compilerRunner: Provider<GradleCompilerRunner> =
objectFactory.propertyWithConvention(
gradleCompileTaskProvider.map {
GradleCompilerRunnerWithWorkers(
it,
null,
normalizedKotlinDaemonJvmArguments.orNull,
metrics.get(),
compilerExecutionStrategy.get(),
workerExecutor
)
}
)
override fun createCompilerArgs(): K2JSCompilerArguments =
K2JSCompilerArguments()