Introduce KotlinJavaToolchain compile tasks input.

This task input provides a way to set different from current Gradle
JDK and use it for Kotlin files compilation. By default it provides
current Gradle JDK.

Provided JDK major version is used as task input, so on providing
different JDK user will see cache miss.

All required interfaces are located inside api module.

^KT-45611 In Progress
This commit is contained in:
Yahor Berdnikau
2021-04-26 11:01:01 +02:00
committed by TeamCityServer
parent 201b6dfa60
commit 816e955c61
13 changed files with 401 additions and 60 deletions
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2021 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 org.jetbrains.kotlin.gradle.tasks
import org.gradle.api.JavaVersion
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Nested
import java.io.File
interface UsesKotlinJavaToolchain {
@get:Nested
val kotlinJavaToolchainProvider: Provider<out KotlinJavaToolchain>
@get:Internal
val kotlinJavaToolchain: KotlinJavaToolchain
get() = kotlinJavaToolchainProvider.get()
}
interface KotlinJavaToolchain {
@get:Input
val javaVersion: Provider<JavaVersion>
/**
* 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
)
/**
* Set JDK to use for Kotlin compilation.
*
* @see [setJdkHome]
*/
fun setJdkHome(
jdkHomeLocation: String,
jdkVersion: JavaVersion
) = setJdkHome(File(jdkHomeLocation), jdkVersion)
}
@@ -0,0 +1,144 @@
/*
* Copyright 2010-2021 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 org.jetbrains.kotlin.gradle
import org.gradle.internal.jvm.JavaInfo
import org.gradle.internal.jvm.Jvm
import org.gradle.testkit.runner.BuildResult
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.testbase.*
import org.junit.jupiter.api.DisplayName
import java.io.File
class KotlinJavaToolchainTest : KGPBaseTest() {
@GradleTest
@DisplayName("Should use by default same jvm as Gradle daemon")
internal fun byDefaultShouldUseGradleJDK(gradleVersion: GradleVersion) {
project(
projectName = "simple".fullProjectName,
gradleVersion = gradleVersion,
) {
build("assemble") {
assertDaemonIsUsingJdk(getUserJdk().javaExecutableRealPath)
}
}
}
@GradleTest
@DisplayName("Should use provided jdk location to compile Kotlin sources")
internal fun customJdkHomeLocation(gradleVersion: GradleVersion) {
project(
projectName = "simple".fullProjectName,
gradleVersion = gradleVersion,
) {
useJdk9ToCompile()
build("assemble") {
assertDaemonIsUsingJdk(getJdk9().javaExecutableRealPath)
}
}
}
@GradleTest
@DisplayName("KotlinCompile task should use build cache when using provided JDK")
internal fun customJdkBuildCache(gradleVersion: GradleVersion) {
val buildCache = workingDir.resolve("custom-jdk-build-cache")
project(
projectName = "simple".fullProjectName,
gradleVersion = gradleVersion,
projectPathAdditionalSuffix = "1/cache-test",
buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true)
) {
enableLocalBuildCache(buildCache)
useJdk9ToCompile()
build("assemble")
}
project(
projectName = "simple".fullProjectName,
gradleVersion = gradleVersion,
projectPathAdditionalSuffix = "2/cache-test",
buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true)
) {
enableLocalBuildCache(buildCache)
useJdk9ToCompile()
build("assemble") {
assertTasksFromCache(":compileKotlin")
}
}
}
@GradleTest
@DisplayName("Kotlin compile task should not use build cache on using different JDK versions")
internal fun differentJdkBuildCacheMiss(gradleVersion: GradleVersion) {
val buildCache = workingDir.resolve("custom-jdk-build-cache")
project(
projectName = "simple".fullProjectName,
gradleVersion = gradleVersion,
projectPathAdditionalSuffix = "1/cache-test",
forceOutput = true,
buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true)
) {
enableLocalBuildCache(buildCache)
enableBuildCacheDebug()
useJdk9ToCompile()
build("assemble")
}
project(
projectName = "simple".fullProjectName,
gradleVersion = gradleVersion,
projectPathAdditionalSuffix = "2/cache-test",
forceOutput = true,
buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true)
) {
enableLocalBuildCache(buildCache)
enableBuildCacheDebug()
build("assemble") {
assertTasksExecuted(":compileKotlin")
}
}
}
private fun BuildResult.assertDaemonIsUsingJdk(
javaexecPath: String
) = assertOutputContains("i: connected to the daemon. Daemon is using following 'java' executable to run itself: $javaexecPath")
private fun getUserJdk(): JavaInfo = Jvm.forHome(File(System.getenv("JAVA_HOME")))
private fun getJdk9(): JavaInfo = Jvm.forHome(File(System.getenv("JDK_9")))
private val JavaInfo.javaExecutableRealPath
get() = javaExecutable
.toPath()
.toRealPath()
.toAbsolutePath()
.toString()
private val String.fullProjectName get() = "kotlin-java-toolchain/$this"
private fun TestProject.useJdk9ToCompile() {
// replace required for windows paths so Groovy will not complain about unexpected char '\'
val jdk9Path = getJdk9().javaHome.absolutePath.replace("\\", "\\\\")
//language=Groovy
rootBuildGradle.append(
"""
import org.gradle.api.JavaVersion
import org.jetbrains.kotlin.gradle.tasks.UsesKotlinJavaToolchain
project.tasks
.withType(UsesKotlinJavaToolchain.class)
.configureEach {
it.kotlinJavaToolchain.setJdkHome(
"$jdk9Path",
JavaVersion.VERSION_1_9
)
}
""".trimIndent()
)
}
}
@@ -0,0 +1,8 @@
plugins {
id("org.jetbrains.kotlin.jvm")
}
repositories {
mavenLocal()
mavenCentral()
}
@@ -0,0 +1,3 @@
fun main() {
println("I know what you've done last summer...")
}
@@ -9,7 +9,6 @@ import org.gradle.api.file.FileCollection
import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
import org.jetbrains.kotlin.gradle.report.ReportingSettings import org.jetbrains.kotlin.gradle.report.ReportingSettings
import org.jetbrains.kotlin.gradle.tasks.findToolsJar
import java.io.File import java.io.File
internal class GradleCompilerEnvironment( internal class GradleCompilerEnvironment(
@@ -21,9 +20,9 @@ internal class GradleCompilerEnvironment(
val incrementalCompilationEnvironment: IncrementalCompilationEnvironment? = null, val incrementalCompilationEnvironment: IncrementalCompilationEnvironment? = null,
val kotlinScriptExtensions: Array<String> = emptyArray() val kotlinScriptExtensions: Array<String> = emptyArray()
) : CompilerEnvironment(Services.EMPTY, messageCollector, outputItemsCollector) { ) : CompilerEnvironment(Services.EMPTY, messageCollector, outputItemsCollector) {
val toolsJar: File? by lazy { findToolsJar() }
val compilerFullClasspath: List<File> fun compilerFullClasspath(
get() = (compilerClasspath + toolsJar).filterNotNull() toolsJar: File?
): List<File> = if (toolsJar != null ) compilerClasspath + toolsJar else compilerClasspath.toList()
} }
@@ -11,14 +11,17 @@ import org.gradle.workers.WorkParameters
import org.gradle.workers.WorkerExecutor import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.logging.kotlinDebug
import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider
import java.io.File
/** /**
* Uses Gradle worker api to run kotlin compilation. * Uses Gradle worker api to run kotlin compilation.
*/ */
internal class GradleCompilerRunnerWithWorkers( internal class GradleCompilerRunnerWithWorkers(
taskProvider: GradleCompileTaskProvider, taskProvider: GradleCompileTaskProvider,
javaExecutable: File,
jdkToolsJar: File?,
private val workerExecutor: WorkerExecutor private val workerExecutor: WorkerExecutor
) : GradleCompilerRunner(taskProvider) { ) : GradleCompilerRunner(taskProvider, javaExecutable, jdkToolsJar) {
override fun runCompilerAsync(workArgs: GradleKotlinCompilerWorkArguments) { override fun runCompilerAsync(workArgs: GradleKotlinCompilerWorkArguments) {
loggerProvider.kotlinDebug { "Starting Kotlin compiler work from task '${pathProvider}'" } loggerProvider.kotlinDebug { "Starting Kotlin compiler work from task '${pathProvider}'" }
@@ -57,7 +57,11 @@ Using real taskProvider cause "field 'taskProvider' from type 'org.jetbrains.kot
value 'fixed(class org.jetbrains.kotlin.gradle.tasks.KotlinCompile_Decorated, task ':compileKotlin')' value 'fixed(class org.jetbrains.kotlin.gradle.tasks.KotlinCompile_Decorated, task ':compileKotlin')'
is not assignable to 'org.gradle.api.tasks.TaskProvider'" exception is not assignable to 'org.gradle.api.tasks.TaskProvider'" exception
*/ */
internal open class GradleCompilerRunner(protected val taskProvider: GradleCompileTaskProvider) { internal open class GradleCompilerRunner(
protected val taskProvider: GradleCompileTaskProvider,
protected val javaExecutable: File,
protected val jdkToolsJar: File?
) {
internal val pathProvider = taskProvider.path internal val pathProvider = taskProvider.path
internal val loggerProvider = taskProvider.logger internal val loggerProvider = taskProvider.logger
@@ -152,7 +156,7 @@ internal open class GradleCompilerRunner(protected val taskProvider: GradleCompi
projectRootDirProvider, projectRootDirProvider,
sessionDirProvider sessionDirProvider
), ),
compilerFullClasspath = environment.compilerFullClasspath, compilerFullClasspath = environment.compilerFullClasspath(jdkToolsJar),
compilerClassName = compilerClassName, compilerClassName = compilerClassName,
compilerArgs = argsArray, compilerArgs = argsArray,
isVerbose = compilerArgs.verbose, isVerbose = compilerArgs.verbose,
@@ -162,7 +166,8 @@ internal open class GradleCompilerRunner(protected val taskProvider: GradleCompi
taskPath = pathProvider, taskPath = pathProvider,
reportingSettings = environment.reportingSettings, reportingSettings = environment.reportingSettings,
kotlinScriptExtensions = environment.kotlinScriptExtensions, kotlinScriptExtensions = environment.kotlinScriptExtensions,
allWarningsAsErrors = compilerArgs.allWarningsAsErrors allWarningsAsErrors = compilerArgs.allWarningsAsErrors,
javaExecutable = javaExecutable
) )
TaskLoggers.put(pathProvider, loggerProvider) TaskLoggers.put(pathProvider, loggerProvider)
runCompilerAsync(workArgs) runCompilerAsync(workArgs)
@@ -179,10 +184,11 @@ internal open class GradleCompilerRunner(protected val taskProvider: GradleCompi
clientIsAliveFlagFile: File, clientIsAliveFlagFile: File,
sessionIsAliveFlagFile: File, sessionIsAliveFlagFile: File,
compilerFullClasspath: List<File>, compilerFullClasspath: List<File>,
javaExecutable: File,
messageCollector: MessageCollector, messageCollector: MessageCollector,
isDebugEnabled: Boolean isDebugEnabled: Boolean
): CompileServiceSession? { ): CompileServiceSession? {
val compilerId = CompilerId.makeCompilerId(compilerFullClasspath) val compilerId = CompilerId.makeCompilerId(compilerFullClasspath, javaExecutable)
val additionalJvmParams = arrayListOf<String>() val additionalJvmParams = arrayListOf<String>()
return KotlinCompilerRunnerUtils.newDaemonConnection( return KotlinCompilerRunnerUtils.newDaemonConnection(
compilerId, clientIsAliveFlagFile, sessionIsAliveFlagFile, compilerId, clientIsAliveFlagFile, sessionIsAliveFlagFile,
@@ -64,7 +64,8 @@ internal class GradleKotlinCompilerWorkArguments(
val taskPath: String, val taskPath: String,
val reportingSettings: ReportingSettings, val reportingSettings: ReportingSettings,
val kotlinScriptExtensions: Array<String>, val kotlinScriptExtensions: Array<String>,
val allWarningsAsErrors: Boolean val allWarningsAsErrors: Boolean,
val javaExecutable: File
) : Serializable { ) : Serializable {
companion object { companion object {
const val serialVersionUID: Long = 0 const val serialVersionUID: Long = 0
@@ -107,6 +108,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
private val buildDir = config.projectFiles.buildDir private val buildDir = config.projectFiles.buildDir
private val metrics = if (reportingSettings.reportMetrics) BuildMetricsReporterImpl() else DoNothingBuildMetricsReporter private val metrics = if (reportingSettings.reportMetrics) BuildMetricsReporterImpl() else DoNothingBuildMetricsReporter
private var icLogLines: List<String> = emptyList() private var icLogLines: List<String> = emptyList()
private val javaExecutable = config.javaExecutable
private val log: KotlinLogger = private val log: KotlinLogger =
TaskLoggers.get(taskPath)?.let { GradleKotlinLogger(it).apply { debug("Using '$taskPath' logger") } } TaskLoggers.get(taskPath)?.let { GradleKotlinLogger(it).apply { debug("Using '$taskPath' logger") } }
@@ -176,6 +178,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
clientIsAliveFlagFile, clientIsAliveFlagFile,
sessionFlagFile, sessionFlagFile,
compilerFullClasspath, compilerFullClasspath,
javaExecutable,
daemonMessageCollector, daemonMessageCollector,
isDebugEnabled = isDebugEnabled isDebugEnabled = isDebugEnabled
) )
@@ -5,14 +5,10 @@
package org.jetbrains.kotlin.gradle.internal package org.jetbrains.kotlin.gradle.internal
import com.intellij.openapi.util.SystemInfo
import org.gradle.api.GradleException
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.model.ObjectFactory import org.gradle.api.model.ObjectFactory
import org.gradle.api.tasks.Classpath import org.gradle.api.provider.Provider
import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.*
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.incremental.IncrementalTaskInputs import org.gradle.api.tasks.incremental.IncrementalTaskInputs
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment
@@ -22,9 +18,8 @@ import org.jetbrains.kotlin.gradle.internal.kapt.incremental.KaptIncrementalChan
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.getValue
import org.jetbrains.kotlin.gradle.utils.optionalProvider import org.jetbrains.kotlin.gradle.utils.optionalProvider
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
import java.io.File import java.io.File
@@ -32,7 +27,10 @@ import javax.inject.Inject
abstract class KaptWithKotlincTask @Inject constructor( abstract class KaptWithKotlincTask @Inject constructor(
objectFactory: ObjectFactory objectFactory: ObjectFactory
) : KaptTask(objectFactory), CompilerArgumentAwareWithInput<K2JVMCompilerArguments> { ) : KaptTask(objectFactory),
CompilerArgumentAwareWithInput<K2JVMCompilerArguments>,
UsesKotlinJavaToolchain {
@get:Internal @get:Internal
internal val pluginOptions = CompilerPluginOptions() internal val pluginOptions = CompilerPluginOptions()
@@ -43,6 +41,9 @@ abstract class KaptWithKotlincTask @Inject constructor(
@get:Internal @get:Internal
val taskProvider = GradleCompileTaskProvider(this) val taskProvider = GradleCompileTaskProvider(this)
final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchainProvider> =
objectFactory.propertyWithNewInstance()
override fun createCompilerArgs(): K2JVMCompilerArguments = K2JVMCompilerArguments() override fun createCompilerArgs(): K2JVMCompilerArguments = K2JVMCompilerArguments()
private val compileKotlinArgumentsContributor by project.provider { private val compileKotlinArgumentsContributor by project.provider {
@@ -103,11 +104,12 @@ abstract class KaptWithKotlincTask @Inject constructor(
reportingSettings = reportingSettings, reportingSettings = reportingSettings,
outputFiles = allOutputFiles() outputFiles = allOutputFiles()
) )
if (environment.toolsJar == null && !isAtLeastJava9) {
throw GradleException("Could not find tools.jar in system classpath, which is required for kapt to work")
}
val compilerRunner = GradleCompilerRunner(taskProvider) val compilerRunner = GradleCompilerRunner(
taskProvider,
kotlinJavaToolchainProvider.get().javaExecutable.get().asFile,
kotlinJavaToolchainProvider.get().jdkToolsJar.orNull
)
compilerRunner.runJvmCompilerAsync( compilerRunner.runJvmCompilerAsync(
sourcesToCompile = emptyList(), sourcesToCompile = emptyList(),
commonSources = emptyList(), commonSources = emptyList(),
@@ -117,7 +119,4 @@ abstract class KaptWithKotlincTask @Inject constructor(
environment = environment environment = environment
) )
} }
}
private val isAtLeastJava9: Boolean
get() = SystemInfo.isJavaVersionAtLeast(9, 0, 0)
}
@@ -10,6 +10,7 @@ import org.gradle.api.tasks.CacheableTask
import org.gradle.workers.WorkerExecutor import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers
import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider
import java.io.File
import javax.inject.Inject import javax.inject.Inject
@CacheableTask @CacheableTask
@@ -19,9 +20,13 @@ constructor(
objectFactory: ObjectFactory, objectFactory: ObjectFactory,
private val workerExecutor: WorkerExecutor private val workerExecutor: WorkerExecutor
) : KotlinJsIrLink(objectFactory) { ) : KotlinJsIrLink(objectFactory) {
override fun compilerRunner() = override fun compilerRunner(
GradleCompilerRunnerWithWorkers( javaExecutable: File,
GradleCompileTaskProvider(this), jdkToolsJar: File?
workerExecutor ) = GradleCompilerRunnerWithWorkers(
) GradleCompileTaskProvider(this),
javaExecutable,
jdkToolsJar,
workerExecutor
)
} }
@@ -113,7 +113,7 @@ open class KotlinCompileCommon : AbstractKotlinCompile<K2MetadataCompilerArgumen
override fun callCompilerAsync(args: K2MetadataCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) { override fun callCompilerAsync(args: K2MetadataCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) {
val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors) val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors)
val outputItemCollector = OutputItemsCollectorImpl() val outputItemCollector = OutputItemsCollectorImpl()
val compilerRunner = compilerRunner val compilerRunner = compilerRunner.get()
val environment = GradleCompilerEnvironment( val environment = GradleCompilerEnvironment(
computedCompilerClasspath, messageCollector, outputItemCollector, computedCompilerClasspath, messageCollector, outputItemCollector,
reportingSettings = reportingSettings, reportingSettings = reportingSettings,
@@ -0,0 +1,94 @@
/*
* Copyright 2010-2021 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 org.jetbrains.kotlin.gradle.tasks
import org.gradle.api.GradleException
import org.gradle.api.JavaVersion
import org.gradle.api.file.ProjectLayout
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.model.ObjectFactory
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.jetbrains.kotlin.gradle.utils.chainedFinalizeValueOnRead
import org.jetbrains.kotlin.gradle.utils.property
import org.jetbrains.kotlin.gradle.utils.propertyWithConvention
import java.io.File
import javax.inject.Inject
abstract class KotlinJavaToolchainProvider @Inject constructor(
objects: ObjectFactory,
files: ProjectLayout
) : KotlinJavaToolchain {
private val currentJvm: Property<Jvm> = objects
.property<Jvm>(Jvm.current())
.chainedFinalizeValueOnRead()
private val _javaVersion: Property<JavaVersion> = objects
.propertyWithConvention(
currentJvm.map { jvm ->
jvm.javaVersion
?: throw GradleException(
"Kotlin could not get java version for the JDK installation: " +
jvm.javaHome?.let { "'$it' " }.orEmpty()
)
}
)
final override val javaVersion: Provider<JavaVersion>
get() = _javaVersion
@get:Internal
internal val javaExecutable: RegularFileProperty = objects
.fileProperty()
.convention(
currentJvm.flatMap { jvm ->
files.file(
objects.property<File>(
jvm.javaExecutable
?: throw GradleException(
"Kotlin could not find 'java' executable in the JDK installation: " +
jvm.javaHome?.let { "'$it' " }.orEmpty()
)
)
)
}
)
.chainedFinalizeValueOnRead()
private val _jdkToolsJar = objects
.propertyWithConvention(
currentJvm.flatMap { jvm ->
objects.propertyWithConvention(jvm.toolsJar)
}
)
.chainedFinalizeValueOnRead()
@get:Internal
internal val jdkToolsJar: Provider<File?> = _jdkToolsJar
.orElse(javaVersion.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."
)
}
objects.propertyWithConvention<File?>(null)
})
override fun setJdkHome(
jdkHomeLocation: File,
jdkVersion: JavaVersion
) {
val jvm = Jvm.forHome(jdkHomeLocation) as Jvm
javaExecutable.set(jvm.javaExecutable)
_jdkToolsJar.set(jvm.toolsJar)
_javaVersion.set(jdkVersion)
}
}
@@ -44,7 +44,7 @@ import org.jetbrains.kotlin.gradle.logging.kotlinWarn
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.report.ReportingSettings import org.jetbrains.kotlin.gradle.report.ReportingSettings
import org.jetbrains.kotlin.gradle.targets.js.ir.isProduceUnzippedKlib import org.jetbrains.kotlin.gradle.targets.js.ir.isProduceUnzippedKlib
import org.jetbrains.kotlin.gradle.utils.getValue import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.isParentOf import org.jetbrains.kotlin.gradle.utils.isParentOf
import org.jetbrains.kotlin.gradle.utils.pathsAsStringRelativeTo import org.jetbrains.kotlin.gradle.utils.pathsAsStringRelativeTo
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
@@ -165,7 +165,7 @@ public class GradleCompileTaskProvider {
val buildModulesInfo: Provider<out IncrementalModuleInfoProvider> /*= GradleCompilerRunner.buildModulesInfo(project.gradle)*/ val buildModulesInfo: Provider<out IncrementalModuleInfoProvider> /*= GradleCompilerRunner.buildModulesInfo(project.gradle)*/
} }
abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKotlinCompileTool<T>() { abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotlinCompileTool<T>(), UsesKotlinJavaToolchain {
init { init {
cacheOnlyIfEnabledForKotlin() cacheOnlyIfEnabledForKotlin()
@@ -318,11 +318,28 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
private val kotlinLogger by lazy { GradleKotlinLogger(logger) } private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
/** Keep lazy to avoid computing before all projects are evaluated. */ final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchainProvider> =
@get:Internal objects.propertyWithNewInstance()
internal val compilerRunner by lazy { compilerRunner() }
internal open fun compilerRunner(): GradleCompilerRunner = GradleCompilerRunner(GradleCompileTaskProvider(this)) @get:Internal
internal val compilerRunner: Provider<GradleCompilerRunner> =
objects.propertyWithConvention(
kotlinJavaToolchainProvider.map {
compilerRunner(
it.javaExecutable.get().asFile,
it.jdkToolsJar.orNull
)
}
)
internal open fun compilerRunner(
javaExecutable: File,
jdkToolsJar: File?
): GradleCompilerRunner = GradleCompilerRunner(
GradleCompileTaskProvider(this),
javaExecutable,
jdkToolsJar
)
private val systemPropertiesService = CompilerSystemPropertiesService.registerIfAbsent(project.gradle) private val systemPropertiesService = CompilerSystemPropertiesService.registerIfAbsent(project.gradle)
@@ -365,9 +382,6 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
private val projectDir = project.rootProject.projectDir private val projectDir = project.rootProject.projectDir
private fun executeImpl(inputs: IncrementalTaskInputs) { private fun executeImpl(inputs: IncrementalTaskInputs) {
// Check that the JDK tools are available in Gradle (fail-fast, instead of a fail during the compiler run):
findToolsJar()
val sourceRoots = getSourceRoots() val sourceRoots = getSourceRoots()
val allKotlinSources = sourceRoots.kotlinSourceFiles val allKotlinSources = sourceRoots.kotlinSourceFiles
@@ -529,7 +543,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors) val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors)
val outputItemCollector = OutputItemsCollectorImpl() val outputItemCollector = OutputItemsCollectorImpl()
val compilerRunner = compilerRunner val compilerRunner = compilerRunner.get()
val icEnv = if (isIncrementalCompilationEnabled()) { val icEnv = if (isIncrementalCompilationEnabled()) {
logger.info(USING_JVM_INCREMENTAL_COMPILATION_MESSAGE) logger.info(USING_JVM_INCREMENTAL_COMPILATION_MESSAGE)
@@ -605,11 +619,15 @@ internal open class KotlinCompileWithWorkers @Inject constructor(
private val workerExecutor: WorkerExecutor private val workerExecutor: WorkerExecutor
) : KotlinCompile() { ) : KotlinCompile() {
override fun compilerRunner() = override fun compilerRunner(
GradleCompilerRunnerWithWorkers( javaExecutable: File,
GradleCompileTaskProvider(this), jdkToolsJar: File?
workerExecutor ) = GradleCompilerRunnerWithWorkers(
) GradleCompileTaskProvider(this),
javaExecutable,
jdkToolsJar,
workerExecutor
)
} }
@CacheableTask @CacheableTask
@@ -618,22 +636,30 @@ internal open class Kotlin2JsCompileWithWorkers @Inject constructor(
private val workerExecutor: WorkerExecutor private val workerExecutor: WorkerExecutor
) : Kotlin2JsCompile(objectFactory) { ) : Kotlin2JsCompile(objectFactory) {
override fun compilerRunner() = override fun compilerRunner(
GradleCompilerRunnerWithWorkers( javaExecutable: File,
GradleCompileTaskProvider(this), jdkToolsJar: File?
workerExecutor ) = GradleCompilerRunnerWithWorkers(
) GradleCompileTaskProvider(this),
javaExecutable,
jdkToolsJar,
workerExecutor
)
} }
@CacheableTask @CacheableTask
internal open class KotlinCompileCommonWithWorkers @Inject constructor( internal open class KotlinCompileCommonWithWorkers @Inject constructor(
private val workerExecutor: WorkerExecutor private val workerExecutor: WorkerExecutor
) : KotlinCompileCommon() { ) : KotlinCompileCommon() {
override fun compilerRunner() = override fun compilerRunner(
GradleCompilerRunnerWithWorkers( javaExecutable: File,
GradleCompileTaskProvider(this), jdkToolsJar: File?
workerExecutor ) = GradleCompilerRunnerWithWorkers(
) GradleCompileTaskProvider(this),
javaExecutable,
jdkToolsJar,
workerExecutor
)
} }
@CacheableTask @CacheableTask
@@ -789,7 +815,7 @@ open class Kotlin2JsCompile @Inject constructor(
val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors) val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors)
val outputItemCollector = OutputItemsCollectorImpl() val outputItemCollector = OutputItemsCollectorImpl()
val compilerRunner = compilerRunner val compilerRunner = compilerRunner.get()
val icEnv = if (isIncrementalCompilationEnabled()) { val icEnv = if (isIncrementalCompilationEnabled()) {
logger.info(USING_JS_INCREMENTAL_COMPILATION_MESSAGE) logger.info(USING_JS_INCREMENTAL_COMPILATION_MESSAGE)