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 package org.jetbrains.kotlin.gradle
import org.gradle.api.JavaVersion
import org.gradle.api.logging.LogLevel import org.gradle.api.logging.LogLevel
import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.BuildResult
import org.gradle.tooling.internal.consumer.ConnectorServices 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() { private fun BuildResult.assertGradleClasspathNotLeaked() {
assertOutputContains("Kotlin compiler classpath:") assertOutputContains("Kotlin compiler classpath:")
val daemonClasspath = output 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?> { ): Provider<File?> {
return objects return objects
.propertyWithConvention( .propertyWithConvention(
jvmProvider.flatMap { jvm -> javaVersionProvider.flatMap { javaVersion ->
objects.propertyWithConvention(jvm.toolsJar) 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 @get:Internal
@@ -18,19 +18,15 @@ package org.jetbrains.kotlin.gradle.tasks
import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.model.ObjectFactory import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.* import org.gradle.api.tasks.*
import org.gradle.work.InputChanges import org.gradle.work.InputChanges
import org.gradle.workers.WorkerExecutor import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments
import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment 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.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
import org.jetbrains.kotlin.gradle.utils.propertyWithConvention
import java.io.File import java.io.File
import javax.inject.Inject import javax.inject.Inject
@@ -39,23 +35,9 @@ abstract class KotlinCompileCommon @Inject constructor(
override val kotlinOptions: KotlinMultiplatformCommonOptions, override val kotlinOptions: KotlinMultiplatformCommonOptions,
workerExecutor: WorkerExecutor, workerExecutor: WorkerExecutor,
objectFactory: ObjectFactory objectFactory: ObjectFactory
) : AbstractKotlinCompile<K2MetadataCompilerArguments>(objectFactory), ) : AbstractKotlinCompile<K2MetadataCompilerArguments>(objectFactory, workerExecutor),
KotlinCommonCompile { KotlinCommonCompile {
override val compilerRunner: Provider<GradleCompilerRunner> =
objectFactory.propertyWithConvention(
gradleCompileTaskProvider.map {
GradleCompilerRunnerWithWorkers(
it,
null,
normalizedKotlinDaemonJvmArguments.orNull,
metrics.get(),
compilerExecutionStrategy.get(),
workerExecutor
)
}
)
override fun createCompilerArgs(): K2MetadataCompilerArguments = override fun createCompilerArgs(): K2MetadataCompilerArguments =
K2MetadataCompilerArguments() K2MetadataCompilerArguments()
@@ -153,7 +153,7 @@ abstract class AbstractKotlinCompileTool<T : CommonToolArguments> @Inject constr
} }
@get:Internal @get:Internal
override val metrics: Property<BuildMetricsReporter> = project.objects final override val metrics: Property<BuildMetricsReporter> = project.objects
.property(BuildMetricsReporterImpl()) .property(BuildMetricsReporterImpl())
/** /**
@@ -228,7 +228,8 @@ abstract class GradleCompileTaskProvider @Inject constructor(
} }
abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constructor( abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constructor(
objectFactory: ObjectFactory objectFactory: ObjectFactory,
workerExecutor: WorkerExecutor
) : AbstractKotlinCompileTool<T>(objectFactory), ) : AbstractKotlinCompileTool<T>(objectFactory),
CompileUsingKotlinDaemonWithNormalization, CompileUsingKotlinDaemonWithNormalization,
BaseKotlinCompile { BaseKotlinCompile {
@@ -323,16 +324,31 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constr
) )
@get:Internal @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( objectFactory.propertyWithConvention(
gradleCompileTaskProvider.map { gradleCompileTaskProvider.flatMap { taskProvider ->
GradleCompilerRunner( compilerExecutionStrategy
it, .zip(metrics) { executionStrategy, metrics ->
null, metrics to executionStrategy
normalizedKotlinDaemonJvmArguments.orNull, }
metrics.get(), .flatMap { params ->
compilerExecutionStrategy.get(), 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, override val kotlinOptions: KotlinJvmOptions,
workerExecutor: WorkerExecutor, workerExecutor: WorkerExecutor,
private val objectFactory: ObjectFactory private val objectFactory: ObjectFactory
) : AbstractKotlinCompile<K2JVMCompilerArguments>(objectFactory), ) : AbstractKotlinCompile<K2JVMCompilerArguments>(objectFactory, workerExecutor),
@Suppress("TYPEALIAS_EXPANSION_DEPRECATION") KotlinJvmCompileDsl, @Suppress("TYPEALIAS_EXPANSION_DEPRECATION") KotlinJvmCompileDsl,
UsesKotlinJavaToolchain { UsesKotlinJavaToolchain {
@@ -575,28 +591,11 @@ abstract class KotlinCompile @Inject constructor(
get() = classpathSnapshotProperties.classpathSnapshotDir.orNull?.asFile?.let { listOf(it) } ?: emptyList() get() = classpathSnapshotProperties.classpathSnapshotDir.orNull?.asFile?.let { listOf(it) } ?: emptyList()
@get:Internal @get:Internal
internal val defaultKotlinJavaToolchain: Provider<DefaultKotlinJavaToolchain> = objectFactory final override val defaultKotlinJavaToolchain: Provider<DefaultKotlinJavaToolchain> = objectFactory
.propertyWithNewInstance({ this }) .propertyWithNewInstance({ this })
final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchain> = defaultKotlinJavaToolchain.cast() 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 @get:Internal
internal abstract val associatedJavaCompileTaskTargetCompatibility: Property<String> internal abstract val associatedJavaCompileTaskTargetCompatibility: Property<String>
@@ -866,7 +865,7 @@ abstract class Kotlin2JsCompile @Inject constructor(
override val kotlinOptions: KotlinJsOptions, override val kotlinOptions: KotlinJsOptions,
objectFactory: ObjectFactory, objectFactory: ObjectFactory,
workerExecutor: WorkerExecutor workerExecutor: WorkerExecutor
) : AbstractKotlinCompile<K2JSCompilerArguments>(objectFactory), ) : AbstractKotlinCompile<K2JSCompilerArguments>(objectFactory, workerExecutor),
KotlinJsCompile { KotlinJsCompile {
init { init {
@@ -923,20 +922,6 @@ abstract class Kotlin2JsCompile @Inject constructor(
@get:Optional @get:Optional
abstract val optionalOutputFile: RegularFileProperty 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 = override fun createCompilerArgs(): K2JSCompilerArguments =
K2JSCompilerArguments() K2JSCompilerArguments()