diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinDaemonIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinDaemonIT.kt index b24c5a43ee0..ffe8c400ba0 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinDaemonIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinDaemonIT.kt @@ -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 diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/build.gradle new file mode 100644 index 00000000000..8bd0d74957b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/build.gradle @@ -0,0 +1,6 @@ +subprojects { + repositories { + mavenLocal() + mavenCentral() + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jsLib/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jsLib/build.gradle new file mode 100644 index 00000000000..e6294cb97b6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jsLib/build.gradle @@ -0,0 +1,3 @@ +plugins { + id "org.jetbrains.kotlin.js" +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jsLib/src/main/kotlin/helloWorld.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jsLib/src/main/kotlin/helloWorld.kt new file mode 100644 index 00000000000..83ec10efe65 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jsLib/src/main/kotlin/helloWorld.kt @@ -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!") +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jvmLib/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jvmLib/build.gradle new file mode 100644 index 00000000000..546933fb729 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jvmLib/build.gradle @@ -0,0 +1,3 @@ +plugins { + id "org.jetbrains.kotlin.jvm" +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jvmLib/src/main/kotlin/helloPrinter.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jvmLib/src/main/kotlin/helloPrinter.kt new file mode 100644 index 00000000000..5c680dc0d36 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/jvmLib/src/main/kotlin/helloPrinter.kt @@ -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!") +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/settings.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/settings.gradle new file mode 100644 index 00000000000..8a29fef72ac --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvmAndJsProject/settings.gradle @@ -0,0 +1 @@ +include "jsLib", "jvmLib" \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/DefaultKotlinJavaToolchain.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/DefaultKotlinJavaToolchain.kt index b74f3cc20e4..704159a5ac1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/DefaultKotlinJavaToolchain.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/DefaultKotlinJavaToolchain.kt @@ -79,20 +79,19 @@ internal abstract class DefaultKotlinJavaToolchain @Inject constructor( ): Provider { 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(null) - } - }) } @get:Internal diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt index 82df41432b8..33828fdc70a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt @@ -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(objectFactory), +) : AbstractKotlinCompile(objectFactory, workerExecutor), KotlinCommonCompile { - override val compilerRunner: Provider = - objectFactory.propertyWithConvention( - gradleCompileTaskProvider.map { - GradleCompilerRunnerWithWorkers( - it, - null, - normalizedKotlinDaemonJvmArguments.orNull, - metrics.get(), - compilerExecutionStrategy.get(), - workerExecutor - ) - } - ) - override fun createCompilerArgs(): K2MetadataCompilerArguments = K2MetadataCompilerArguments() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index e712114f0b4..c700b8fd3f1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -153,7 +153,7 @@ abstract class AbstractKotlinCompileTool @Inject constr } @get:Internal - override val metrics: Property = project.objects + final override val metrics: Property = project.objects .property(BuildMetricsReporterImpl()) /** @@ -228,7 +228,8 @@ abstract class GradleCompileTaskProvider @Inject constructor( } abstract class AbstractKotlinCompile @Inject constructor( - objectFactory: ObjectFactory + objectFactory: ObjectFactory, + workerExecutor: WorkerExecutor ) : AbstractKotlinCompileTool(objectFactory), CompileUsingKotlinDaemonWithNormalization, BaseKotlinCompile { @@ -323,16 +324,31 @@ abstract class AbstractKotlinCompile @Inject constr ) @get:Internal - internal open val compilerRunner: Provider = + internal open val defaultKotlinJavaToolchain: Provider = objectFactory + .propertyWithNewInstance({ null }) + + @get:Internal + internal val compilerRunner: Provider = 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(objectFactory), +) : AbstractKotlinCompile(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 = objectFactory + final override val defaultKotlinJavaToolchain: Provider = objectFactory .propertyWithNewInstance({ this }) final override val kotlinJavaToolchainProvider: Provider = defaultKotlinJavaToolchain.cast() - @get:Internal - override val compilerRunner: Provider = 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 @@ -866,7 +865,7 @@ abstract class Kotlin2JsCompile @Inject constructor( override val kotlinOptions: KotlinJsOptions, objectFactory: ObjectFactory, workerExecutor: WorkerExecutor -) : AbstractKotlinCompile(objectFactory), +) : AbstractKotlinCompile(objectFactory, workerExecutor), KotlinJsCompile { init { @@ -923,20 +922,6 @@ abstract class Kotlin2JsCompile @Inject constructor( @get:Optional abstract val optionalOutputFile: RegularFileProperty - override val compilerRunner: Provider = - objectFactory.propertyWithConvention( - gradleCompileTaskProvider.map { - GradleCompilerRunnerWithWorkers( - it, - null, - normalizedKotlinDaemonJvmArguments.orNull, - metrics.get(), - compilerExecutionStrategy.get(), - workerExecutor - ) - } - ) - override fun createCompilerArgs(): K2JSCompilerArguments = K2JSCompilerArguments()