Consider toolchain only as input for 'jdkHome' compilation option.

This change will limit toolchain scope only to the JVM compilations,
as Kotlin compiler itself does not care about JDK version it is running
 on and should always produce same output for non-JVM backends.
For JVM backend there is one condition - 'jdkHome' should always point
 to the same JDK version.

Few additional changes:
- allow to set specific JDK location even on Gradle versions 6.7+
- Fix typo in deprecation message

^KT-45611 In Progress
^KT-43095 In Progress
This commit is contained in:
Yahor Berdnikau
2021-06-15 12:04:57 +02:00
committed by Space
parent 1bb64ffa22
commit 46d5df4991
11 changed files with 223 additions and 285 deletions
@@ -21,14 +21,15 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
@GradleTestVersions(additionalVersions = ["6.7.1"])
@GradleTest
@DisplayName("Should use by default same jvm as Gradle daemon")
@DisplayName("Should use by default same jvm as Gradle daemon for jdkHome")
internal fun byDefaultShouldUseGradleJDK(gradleVersion: GradleVersion) {
project(
projectName = "simple".fullProjectName,
gradleVersion = gradleVersion,
gradleVersion = gradleVersion
) {
build("assemble") {
assertDaemonIsUsingJdk(getUserJdk().javaExecutableRealPath)
build("assemble", enableGradleDebug = true) {
assertOutputDoesNotContain("'kotlinOptions.jdkHome' is deprecated and will be ignored in Kotlin 1.7!")
assertJdkHomeIsUsingJdk(getUserJdk().javaHomeRealPath)
}
}
}
@@ -41,7 +42,7 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
projectName = "simple".fullProjectName,
gradleVersion = gradleVersion
) {
//lang=Groovy
//language=Groovy
rootBuildGradle.append(
"""
@@ -65,23 +66,11 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
useJdk9ToCompile()
build("assemble") {
assertDaemonIsUsingJdk(getJdk9().javaExecutableRealPath)
assertJdkHomeIsUsingJdk(getJdk9().javaHomeRealPath)
}
}
}
@Test
@DisplayName("Should fail the build on setting custom JDK when toolchain is available")
internal fun errorOnSettingJdkWhenToolchainIsAvailable() {
project(
projectName = "simple".fullProjectName,
gradleVersion = GradleVersion.version("6.7.1"),
) {
useJdk9ToCompile()
buildAndFail("assemble")
}
}
@GradleTest
@DisplayName("KotlinCompile task should use build cache when using provided JDK")
internal fun customJdkBuildCache(gradleVersion: GradleVersion) {
@@ -174,11 +163,11 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
)
build("assemble") {
assertDaemonIsUsingJdk(
assertJdkHomeIsUsingJdk(
if (shouldUseToolchain(gradleVersion)) {
getToolchainExecPathFromLogs()
} else {
getJdk9().javaExecutableRealPath
getJdk9().javaHomeRealPath
}
)
@@ -281,7 +270,7 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
}
}
@DisplayName("jdkHome Kotlin option should produce deprecation warning on Gradle builds")
@DisplayName("User provided jdkHome Kotlin option should produce deprecation warning on Gradle builds")
@GradleTest
internal fun jdkHomeIsDeprecated(gradleVersion: GradleVersion) {
project(
@@ -302,9 +291,8 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
""".trimIndent()
)
build("assemble") {
assertDaemonIsUsingJdk(getUserJdk().javaExecutableRealPath)
assertOutputContains("'kotlinOptions.jdkHome' is deprecated and will ignored in Kotlin 1.6!")
assertOutputContains("-jdk-home ${getJdk9().javaHome.absolutePath}")
assertJdkHomeIsUsingJdk(getJdk9().javaHomeRealPath)
assertOutputContains("'kotlinOptions.jdkHome' is deprecated and will be ignored in Kotlin 1.7!")
}
}
}
@@ -320,7 +308,7 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
) {
useToolchainToCompile(11)
build("assemble") {
assertDaemonIsUsingJdk(getToolchainExecPathFromLogs())
assertJdkHomeIsUsingJdk(getToolchainExecPathFromLogs())
}
}
}
@@ -336,21 +324,21 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
) {
useToolchainExtension(11)
build("assemble") {
assertDaemonIsUsingJdk(getToolchainExecPathFromLogs())
assertJdkHomeIsUsingJdk(getToolchainExecPathFromLogs())
}
}
}
private fun BuildResult.assertDaemonIsUsingJdk(
private fun BuildResult.assertJdkHomeIsUsingJdk(
javaexecPath: String
) = assertOutputContains("i: connected to the daemon. Daemon is using following 'java' executable to run itself: $javaexecPath")
) = assertOutputContains("[KOTLIN] Kotlin compilation 'jdkHome' argument: $javaexecPath")
private fun getUserJdk(): JavaInfo = Jvm.forHome(File(System.getenv("JAVA_HOME")))
private fun getJdk9(): JavaInfo = Jvm.forHome(File(System.getenv("JDK_9")))
// replace required for windows paths so Groovy will not complain about unexpected char '\'
private fun getJdk9Path(): String = getJdk9().javaHome.absolutePath.replace("\\", "\\\\")
private val JavaInfo.javaExecutableRealPath
get() = javaExecutable
private val JavaInfo.javaHomeRealPath
get() = javaHome
.toPath()
.toRealPath()
.toAbsolutePath()
@@ -399,7 +387,7 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
}
afterEvaluate {
logger.info("Toolchain exec path: ${'$'}{defaultLauncher.get().executablePath.asFile.absolutePath}")
logger.info("Toolchain jdk path: ${'$'}{defaultLauncher.get().metadata.installationPath.asFile.absolutePath}")
}
""".trimIndent()
)
@@ -425,7 +413,7 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
def toolchain = project.extensions.getByType(JavaPluginExtension.class).toolchain
def service = project.extensions.getByType(JavaToolchainService.class)
def defaultLauncher = service.launcherFor(toolchain)
logger.info("Toolchain exec path: ${'$'}{defaultLauncher.get().executablePath.asFile.absolutePath}")
logger.info("Toolchain jdk path: ${'$'}{defaultLauncher.get().metadata.installationPath.asFile.absolutePath}")
}
""".trimIndent()
)
@@ -435,6 +423,6 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
private fun BuildResult.getToolchainExecPathFromLogs() = output
.lineSequence()
.first { it.startsWith("Toolchain exec path:") }
.substringAfter("Toolchain exec path: ")
.first { it.startsWith("Toolchain jdk path:") }
.substringAfter("Toolchain jdk path: ")
}
@@ -18,10 +18,9 @@ import java.io.File
*/
internal class GradleCompilerRunnerWithWorkers(
taskProvider: GradleCompileTaskProvider,
javaExecutable: File,
jdkToolsJar: File?,
private val workerExecutor: WorkerExecutor
) : GradleCompilerRunner(taskProvider, javaExecutable, jdkToolsJar) {
) : GradleCompilerRunner(taskProvider, jdkToolsJar) {
override fun runCompilerAsync(workArgs: GradleKotlinCompilerWorkArguments) {
loggerProvider.kotlinDebug { "Starting Kotlin compiler work from task '${pathProvider}'" }
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.daemon.common.CompilerId
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
@@ -55,7 +56,6 @@ is not assignable to 'org.gradle.api.tasks.TaskProvider'" exception
*/
internal open class GradleCompilerRunner(
protected val taskProvider: GradleCompileTaskProvider,
protected val javaExecutable: File,
protected val jdkToolsJar: File?
) {
@@ -78,12 +78,15 @@ internal open class GradleCompilerRunner(
javaSourceRoots: Iterable<File>,
javaPackagePrefix: String?,
args: K2JVMCompilerArguments,
environment: GradleCompilerEnvironment
environment: GradleCompilerEnvironment,
jdkHome: File
) {
args.freeArgs += sourcesToCompile.map { it.absolutePath }
args.commonSources = commonSources.map { it.absolutePath }.toTypedArray()
args.javaSourceRoots = javaSourceRoots.map { it.absolutePath }.toTypedArray()
args.javaPackagePrefix = javaPackagePrefix
if (args.jdkHome == null) args.jdkHome = jdkHome.absolutePath
loggerProvider.kotlinInfo("Kotlin compilation 'jdkHome' argument: ${args.jdkHome}")
runCompilerAsync(KotlinCompilerClass.JVM, args, environment)
}
@@ -165,8 +168,7 @@ internal open class GradleCompilerRunner(
taskPath = pathProvider,
reportingSettings = environment.reportingSettings,
kotlinScriptExtensions = environment.kotlinScriptExtensions,
allWarningsAsErrors = compilerArgs.allWarningsAsErrors,
javaExecutable = javaExecutable
allWarningsAsErrors = compilerArgs.allWarningsAsErrors
)
TaskLoggers.put(pathProvider, loggerProvider)
runCompilerAsync(workArgs)
@@ -183,11 +185,10 @@ internal open class GradleCompilerRunner(
clientIsAliveFlagFile: File,
sessionIsAliveFlagFile: File,
compilerFullClasspath: List<File>,
javaExecutable: File,
messageCollector: MessageCollector,
isDebugEnabled: Boolean
): CompileServiceSession? {
val compilerId = CompilerId.makeCompilerId(compilerFullClasspath, javaExecutable)
val compilerId = CompilerId.makeCompilerId(compilerFullClasspath)
val additionalJvmParams = arrayListOf<String>()
return KotlinCompilerRunnerUtils.newDaemonConnection(
compilerId, clientIsAliveFlagFile, sessionIsAliveFlagFile,
@@ -5,9 +5,7 @@
package org.jetbrains.kotlin.compilerRunner
import org.gradle.api.Project
import org.gradle.api.logging.Logger
import org.jetbrains.kotlin.build.ExecutionStrategy
import org.jetbrains.kotlin.build.report.metrics.*
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
@@ -64,8 +62,7 @@ internal class GradleKotlinCompilerWorkArguments(
val taskPath: String,
val reportingSettings: ReportingSettings,
val kotlinScriptExtensions: Array<String>,
val allWarningsAsErrors: Boolean,
val javaExecutable: File
val allWarningsAsErrors: Boolean
) : Serializable {
companion object {
const val serialVersionUID: Long = 0
@@ -108,7 +105,6 @@ internal class GradleKotlinCompilerWork @Inject constructor(
private val buildDir = config.projectFiles.buildDir
private val metrics = if (reportingSettings.reportMetrics) BuildMetricsReporterImpl() else DoNothingBuildMetricsReporter
private var icLogLines: List<String> = emptyList()
private val javaExecutable = config.javaExecutable
private val log: KotlinLogger =
TaskLoggers.get(taskPath)?.let { GradleKotlinLogger(it).apply { debug("Using '$taskPath' logger") } }
@@ -178,7 +174,6 @@ internal class GradleKotlinCompilerWork @Inject constructor(
clientIsAliveFlagFile,
sessionFlagFile,
compilerFullClasspath,
javaExecutable,
daemonMessageCollector,
isDebugEnabled = isDebugEnabled
)
@@ -114,7 +114,7 @@ internal open class KotlinJvmCompilerArgumentsContributor(
?.run {
logger.warn(
"""
'kotlinOptions.jdkHome' is deprecated and will ignored in Kotlin 1.6!
'kotlinOptions.jdkHome' is deprecated and will be ignored in Kotlin 1.7!
Consider using JavaToolchain on Gradle 6.7+:
kotlin {
@@ -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.Provider
import org.gradle.api.tasks.*
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
@@ -113,8 +112,7 @@ abstract class KaptWithKotlincTask @Inject constructor(
val compilerRunner = GradleCompilerRunner(
taskProvider,
kotlinJavaToolchainProvider.get().jdkProvider.javaExecutable.get().asFile,
kotlinJavaToolchainProvider.get().jdkProvider.jdkToolsJar.orNull
kotlinJavaToolchainProvider.get().currentJvmJdkToolsJar.orNull
)
compilerRunner.runJvmCompilerAsync(
sourcesToCompile = emptyList(),
@@ -122,7 +120,8 @@ abstract class KaptWithKotlincTask @Inject constructor(
javaSourceRoots = source.files,
javaPackagePrefix = javaPackagePrefix.orNull,
args = args,
environment = environment
environment = environment,
jdkHome = kotlinJavaToolchainProvider.get().providedJvm.get().javaHome
)
}
}
@@ -158,7 +158,6 @@ abstract class KaptWithoutKotlincTask @Inject constructor(
val isolationMode = getWorkerIsolationMode()
logger.info("Using workers $isolationMode isolation mode to run kapt")
val toolsJarURLSpec = kotlinJavaToolchainProvider.get()
.jdkProvider
.jdkToolsJar.orNull?.toURI()?.toURL()?.toString().orEmpty()
submitWork(
@@ -170,12 +169,12 @@ abstract class KaptWithoutKotlincTask @Inject constructor(
}
private fun getWorkerIsolationMode(): IsolationMode {
val jdkProvider = kotlinJavaToolchainProvider.get().jdkProvider
val gradleJvm = jdkProvider.currentJvm.get()
val toolchainProvider = kotlinJavaToolchainProvider.get()
val gradleJvm = toolchainProvider.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 == jdkProvider.javaVersion.get() &&
gradleJvm.javaExecutable.absolutePath == jdkProvider.javaExecutable.get().asFile.absolutePath
val isRunningOnGradleJvm = gradleJvm.javaVersion == toolchainProvider.javaVersion.get() &&
gradleJvm.javaExecutable.absolutePath == toolchainProvider.javaExecutable.get().asFile.absolutePath
val isolationModeStr = getValue("kapt.workers.isolation")?.toLowerCase()
return when {
(isolationModeStr == null || isolationModeStr == "none") && isRunningOnGradleJvm -> IsolationMode.NONE
@@ -201,7 +200,6 @@ abstract class KaptWithoutKotlincTask @Inject constructor(
it.forkOptions.jvmArgs("-verbose:class")
}
it.forkOptions.executable = kotlinJavaToolchainProvider.get()
.jdkProvider
.javaExecutable
.asFile.get()
.absolutePath
@@ -6,11 +6,12 @@
package org.jetbrains.kotlin.gradle.targets.js.ir
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.CacheableTask
import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers
import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider
import java.io.File
import org.jetbrains.kotlin.gradle.utils.propertyWithConvention
import javax.inject.Inject
@CacheableTask
@@ -18,15 +19,16 @@ internal abstract class KotlinJsIrLinkWithWorkers
@Inject
constructor(
objectFactory: ObjectFactory,
private val workerExecutor: WorkerExecutor
workerExecutor: WorkerExecutor
) : KotlinJsIrLink(objectFactory) {
override fun compilerRunner(
javaExecutable: File,
jdkToolsJar: File?
) = GradleCompilerRunnerWithWorkers(
gradleCompileTaskProvider,
javaExecutable,
jdkToolsJar,
workerExecutor
)
override val compilerRunner: Provider<GradleCompilerRunner> =
objects.propertyWithConvention(
gradleCompileTaskProvider.map {
GradleCompilerRunnerWithWorkers(
it,
null,
workerExecutor
) as GradleCompilerRunner
}
)
}
@@ -23,190 +23,141 @@ import org.jetbrains.kotlin.gradle.utils.property
import org.jetbrains.kotlin.gradle.utils.propertyWithConvention
import java.io.File
import javax.inject.Inject
import kotlin.reflect.full.functions
abstract class KotlinJavaToolchainProvider @Inject constructor(
objects: ObjectFactory,
private val objects: ObjectFactory,
projectLayout: ProjectLayout,
gradle: Gradle
) : KotlinJavaToolchain {
private val defaultJdkSetter by lazy(LazyThreadSafetyMode.NONE) {
DefaultJdkSetter(
objects,
projectLayout,
GradleVersion.version(gradle.gradleVersion)
private val currentGradleVersion = GradleVersion.version(gradle.gradleVersion)
@get:Internal
internal val currentJvm: Provider<Jvm> = objects
.property(Jvm.current())
.chainedFinalizeValueOnRead()
@get:Internal
internal val providedJvm: Property<Jvm> = objects
.propertyWithConvention(currentJvm)
.chainedFinalizeValueOnRead()
final override val javaVersion: Provider<JavaVersion> = objects
.property(
providedJvm.map { jvm ->
jvm.javaVersion
?: throw GradleException(
"Kotlin could not get java version for the JDK installation: " +
jvm.javaHome?.let { "'$it' " }.orEmpty()
)
}
)
.chainedFinalizeValueOnRead()
@get:Internal
internal val javaExecutable: RegularFileProperty = objects
.fileProperty()
.value(
providedJvm.flatMap { jvm ->
projectLayout.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 fun getToolsJarFromJvm(jvmProvider: Provider<Jvm>): Provider<File?> {
return objects
.propertyWithConvention(
jvmProvider.flatMap { jvm ->
objects.propertyWithConvention(jvm.toolsJar)
}
)
.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."
)
} else {
objects.propertyWithConvention<File?>(null)
}
})
}
@get:Internal
internal val jdkToolsJar: Provider<File?> = getToolsJarFromJvm(providedJvm)
@get:Internal
internal val currentJvmJdkToolsJar: Provider<File?> = getToolsJarFromJvm(currentJvm)
final override val jdk: KotlinJavaToolchain.JdkSetter = DefaultJdkSetter(providedJvm, currentGradleVersion)
private val defaultJavaToolchainSetter by lazy(LazyThreadSafetyMode.NONE) {
if (GradleVersion.version(gradle.gradleVersion) >= TOOLCHAIN_SUPPORTED_VERSION) {
DefaultJavaToolchainSetter(objects)
if (currentGradleVersion >= TOOLCHAIN_SUPPORTED_VERSION) {
DefaultJavaToolchainSetter(providedJvm)
} else {
null
}
}
@get:Internal
internal val jdkProvider: JdkProvider =
if (GradleVersion.version(gradle.gradleVersion) < TOOLCHAIN_SUPPORTED_VERSION) {
defaultJdkSetter
} else {
defaultJavaToolchainSetter!!
}
final override val javaVersion: Provider<JavaVersion>
get() = jdkProvider.javaVersion
final override val jdk: KotlinJavaToolchain.JdkSetter get() = defaultJdkSetter
final override val toolchain: KotlinJavaToolchain.JavaToolchainSetter
get() = defaultJavaToolchainSetter
?: throw GradleException("Toolchain support is available from $TOOLCHAIN_SUPPORTED_VERSION")
internal interface JdkProvider {
val currentJvm: Property<Jvm>
val javaExecutable: RegularFileProperty
val javaVersion: Property<JavaVersion>
val jdkToolsJar: Provider<File?>
companion object {
fun jdkToolsProperty(
objectsFactory: ObjectFactory,
currentJvm: Provider<Jvm>
): Property<File?> = objectsFactory
.propertyWithConvention(
currentJvm.flatMap { jvm ->
objectsFactory.propertyWithConvention(jvm.toolsJar)
}
)
fun defaultJdkToolsJarProvider(
objectsFactory: ObjectFactory,
javaVersion: Property<JavaVersion>,
jdkTools: Property<File?>
): Provider<File?> = jdkTools
.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."
)
} else {
objectsFactory.propertyWithConvention<File?>(null)
}
})
}
}
private class DefaultJdkSetter(
private val objectsFactory: ObjectFactory,
projectLayout: ProjectLayout,
private val providedJvm: Property<Jvm>,
private val currentGradleVersion: GradleVersion
) : KotlinJavaToolchain.JdkSetter,
JdkProvider {
override val currentJvm: Property<Jvm> = objectsFactory
.property(Jvm.current())
.chainedFinalizeValueOnRead()
override val javaExecutable: RegularFileProperty = objectsFactory
.fileProperty()
.convention(
currentJvm.flatMap { jvm ->
projectLayout.file(
objectsFactory.property<File>(
jvm.javaExecutable
?: throw GradleException(
"Kotlin could not find 'java' executable in the JDK installation: " +
jvm.javaHome?.let { "'$it' " }.orEmpty()
)
)
)
}
)
.chainedFinalizeValueOnRead()
override val javaVersion: Property<JavaVersion> = objectsFactory
.propertyWithConvention(
currentJvm.map { jvm ->
jvm.javaVersion
?: throw GradleException(
"Kotlin could not get java version for the JDK installation: " +
jvm.javaHome?.let { "'$it' " }.orEmpty()
)
}
)
private val _jdkToolsJar: Property<File?> = JdkProvider.jdkToolsProperty(
objectsFactory,
currentJvm
)
override val jdkToolsJar: Provider<File?> = JdkProvider.defaultJdkToolsJarProvider(
objectsFactory,
javaVersion,
_jdkToolsJar
)
) : KotlinJavaToolchain.JdkSetter {
override fun use(
jdkHomeLocation: File,
jdkVersion: JavaVersion
) {
if (currentGradleVersion >= TOOLCHAIN_SUPPORTED_VERSION) {
throw GradleException(
"Please use Java toolchains instead"
)
require(jdkHomeLocation.isDirectory) {
"Supplied jdkHomeLocation must be a valid directory. You supplied: $jdkHomeLocation"
}
require(jdkHomeLocation.exists()) {
"Supplied jdkHomeLocation does not exists. You supplied: $jdkHomeLocation"
}
val jvm = Jvm.forHome(jdkHomeLocation) as Jvm
javaExecutable.set(jvm.javaExecutable)
_jdkToolsJar.set(jvm.toolsJar)
javaVersion.set(jdkVersion)
if (currentGradleVersion < GradleVersion.version("6.2.0")) {
// Before Gradle 6.2.0 'Jvm.discovered' does not have 'implementationJavaVersion' parameter
val jvm = Jvm::class.functions
.first { it.name == "discovered" }
.call(jdkHomeLocation, jdkVersion) as Jvm
providedJvm.set(jvm)
} else {
providedJvm.set(
Jvm.discovered(jdkHomeLocation, null, jdkVersion)
)
}
}
}
private class DefaultJavaToolchainSetter(
objectsFactory: ObjectFactory
) : KotlinJavaToolchain.JavaToolchainSetter,
JdkProvider {
private val javaLauncher: Property<JavaLauncher> = objectsFactory.property()
override val currentJvm: Property<Jvm> = objectsFactory
.propertyWithConvention(
javaLauncher.map {
Jvm.forHome(it.metadata.installationPath.asFile) as Jvm
}
)
override val javaExecutable: RegularFileProperty = objectsFactory
.fileProperty()
.apply {
set(javaLauncher.map { it.executablePath })
}
override val javaVersion: Property<JavaVersion> = objectsFactory
.property(
javaLauncher.map {
JavaVersion.toVersion(it.metadata.languageVersion.asInt())
}
)
private val _jdkToolsJar = JdkProvider.jdkToolsProperty(
objectsFactory,
currentJvm
)
override val jdkToolsJar: Provider<File?> = JdkProvider.defaultJdkToolsJarProvider(
objectsFactory,
javaVersion,
_jdkToolsJar
)
private inner class DefaultJavaToolchainSetter(
private val providedJvm: Property<Jvm>
) : KotlinJavaToolchain.JavaToolchainSetter {
override fun use(
javaLauncher: Provider<JavaLauncher>
) {
this.javaLauncher.set(javaLauncher)
providedJvm.set(
javaLauncher.map {
val metadata = javaLauncher.get().metadata
Jvm.discovered(
metadata.installationPath.asFile,
null,
JavaVersion.toVersion(metadata.languageVersion.asInt())
)
}
)
}
}
}
@@ -138,7 +138,7 @@ class GradleCompileTaskProvider(task: Task) {
}
}
abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotlinCompileTool<T>(), UsesKotlinJavaToolchain {
abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotlinCompileTool<T>() {
open class Configurator<T : AbstractKotlinCompile<*>>(protected val compilation: KotlinCompilationData<*>) : TaskConfigurator<T> {
override fun configure(task: T) {
@@ -256,40 +256,18 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchainProvider> = objects
.propertyWithNewInstance(
project.gradle
)
@get:Internal
protected val gradleCompileTaskProvider: Provider<GradleCompileTaskProvider> = objects
.providerWithLazyConvention { GradleCompileTaskProvider(this) }
@get:Internal
internal val compilerRunner: Provider<GradleCompilerRunner> =
internal open val compilerRunner: Provider<GradleCompilerRunner> =
objects.propertyWithConvention(
kotlinJavaToolchainProvider.map {
compilerRunner(
it.jdkProvider.javaExecutable.get().asFile,
it.jdkProvider.jdkToolsJar.orNull
)
gradleCompileTaskProvider.map {
GradleCompilerRunner(it, null)
}
)
// Moved creation here to not violate Gradle configuration cache as [compilerRunner] method is called
// at execution time
// by lazy is added so properties of task extending this one are captured - required for incremental
// compilation
@get:Internal
protected val gradleCompileTaskProvider by lazy {
GradleCompileTaskProvider(this)
}
internal open fun compilerRunner(
javaExecutable: File,
jdkToolsJar: File?
): GradleCompilerRunner = GradleCompilerRunner(
gradleCompileTaskProvider,
javaExecutable,
jdkToolsJar
)
private val systemPropertiesService = CompilerSystemPropertiesService.registerIfAbsent(project.gradle)
@TaskAction
@@ -403,7 +381,9 @@ internal inline val <reified T : Task> T.thisTaskProvider: TaskProvider<out T>
@CacheableTask
abstract class KotlinCompile @Inject constructor(
override val kotlinOptions: KotlinJvmOptions
) : AbstractKotlinCompile<K2JVMCompilerArguments>(), KotlinJvmCompile {
) : AbstractKotlinCompile<K2JVMCompilerArguments>(),
KotlinJvmCompile,
UsesKotlinJavaToolchain {
class Configurator(kotlinCompilation: KotlinCompilationData<*>) : AbstractKotlinCompile.Configurator<KotlinCompile>(kotlinCompilation) {
}
@@ -438,6 +418,24 @@ abstract class KotlinCompile @Inject constructor(
@get:Input
abstract val useClasspathSnapshot: Property<Boolean>
final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchainProvider> = objects
.propertyWithNewInstance(
project.gradle
)
@get:Internal
override val compilerRunner: Provider<GradleCompilerRunner> = objects.propertyWithConvention(
// From Gradle 6.6 better to replace flatMap with provider.zip()
kotlinJavaToolchainProvider.flatMap { toolchain ->
objects.property(gradleCompileTaskProvider.map {
GradleCompilerRunner(
it,
toolchain.currentJvmJdkToolsJar.orNull
)
})
}
)
init {
incremental = true
}
@@ -495,7 +493,8 @@ abstract class KotlinCompile @Inject constructor(
sourceRoots.javaSourceRoots,
javaPackagePrefix,
args,
environment
environment,
kotlinJavaToolchainProvider.get().providedJvm.get().javaHome
)
}
@@ -543,52 +542,53 @@ abstract class KotlinCompile @Inject constructor(
@CacheableTask
internal abstract class KotlinCompileWithWorkers @Inject constructor(
kotlinOptions: KotlinJvmOptions,
private val workerExecutor: WorkerExecutor
workerExecutor: WorkerExecutor
) : KotlinCompile(kotlinOptions) {
override fun compilerRunner(
javaExecutable: File,
jdkToolsJar: File?
) = GradleCompilerRunnerWithWorkers(
gradleCompileTaskProvider,
javaExecutable,
jdkToolsJar,
workerExecutor
)
override val compilerRunner: Provider<GradleCompilerRunner> =
objects.propertyWithConvention(
gradleCompileTaskProvider.map {
GradleCompilerRunnerWithWorkers(
it,
null,
workerExecutor
) as GradleCompilerRunner
}
)
}
@CacheableTask
internal abstract class Kotlin2JsCompileWithWorkers @Inject constructor(
kotlinOptions: KotlinJsOptions,
objectFactory: ObjectFactory,
private val workerExecutor: WorkerExecutor
workerExecutor: WorkerExecutor
) : Kotlin2JsCompile(kotlinOptions, objectFactory) {
override fun compilerRunner(
javaExecutable: File,
jdkToolsJar: File?
) = GradleCompilerRunnerWithWorkers(
gradleCompileTaskProvider,
javaExecutable,
jdkToolsJar,
workerExecutor
)
override val compilerRunner: Provider<GradleCompilerRunner> =
objects.propertyWithConvention(
gradleCompileTaskProvider.map {
GradleCompilerRunnerWithWorkers(
it,
null,
workerExecutor
) as GradleCompilerRunner
}
)
}
@CacheableTask
internal abstract class KotlinCompileCommonWithWorkers @Inject constructor(
kotlinOptions: KotlinMultiplatformCommonOptions,
private val workerExecutor: WorkerExecutor
workerExecutor: WorkerExecutor
) : KotlinCompileCommon(kotlinOptions) {
override fun compilerRunner(
javaExecutable: File,
jdkToolsJar: File?
) = GradleCompilerRunnerWithWorkers(
gradleCompileTaskProvider,
javaExecutable,
jdkToolsJar,
workerExecutor
)
override val compilerRunner: Provider<GradleCompilerRunner> =
objects.propertyWithConvention(
gradleCompileTaskProvider.map {
GradleCompilerRunnerWithWorkers(
it,
null,
workerExecutor
) as GradleCompilerRunner
}
)
}
@CacheableTask
@@ -601,7 +601,8 @@ abstract class Kotlin2JsCompile @Inject constructor(
incremental = true
}
open class Configurator<T : Kotlin2JsCompile>(compilation: KotlinCompilationData<*>) : AbstractKotlinCompile.Configurator<T>(compilation) {
open class Configurator<T : Kotlin2JsCompile>(compilation: KotlinCompilationData<*>) :
AbstractKotlinCompile.Configurator<T>(compilation) {
override fun configure(task: T) {
super.configure(task)
@@ -52,6 +52,10 @@ internal inline fun <reified T : Any?> ObjectFactory.propertyWithConvention(
conventionValue: T
) = property<T>().convention(conventionValue)
internal inline fun <reified T : Any?> ObjectFactory.providerWithLazyConvention(
noinline lazyConventionValue: () -> T
) = property(lazyConventionValue).map { it.invoke() }
internal inline fun <reified T : Any> ObjectFactory.newInstance() = newInstance(T::class.java)
internal inline fun <reified T : Any> ObjectFactory.newInstance(vararg parameters: Any) =