Allow to configure non-default JDK using toolchain via extension.
Add method into "kotlin" extension to set toolchain for all tasks. This will also set toolchain for java compile tasks. Also user may set toolchain via "java" extension and it will be applied to Kotlin tasks as well. ^KT-43092 In Progress
This commit is contained in:
+5
@@ -11,6 +11,7 @@ import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.Nested
|
||||
import org.gradle.jvm.toolchain.JavaLauncher
|
||||
import org.gradle.util.GradleVersion
|
||||
import java.io.File
|
||||
|
||||
interface UsesKotlinJavaToolchain {
|
||||
@@ -66,4 +67,8 @@ interface KotlinJavaToolchain {
|
||||
javaLauncher: Provider<JavaLauncher>
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TOOLCHAIN_SUPPORTED_VERSION: GradleVersion = GradleVersion.version("6.7")
|
||||
}
|
||||
}
|
||||
|
||||
+119
-14
@@ -12,12 +12,14 @@ import org.gradle.testkit.runner.BuildResult
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.kotlin.gradle.testbase.*
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.io.File
|
||||
|
||||
@SimpleGradlePluginPTests
|
||||
@DisplayName("Kotlin Java Toolchain support")
|
||||
class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
|
||||
@GradleTestVersions(additionalVersions = ["6.7.1"])
|
||||
@GradleTest
|
||||
@DisplayName("Should use by default same jvm as Gradle daemon")
|
||||
internal fun byDefaultShouldUseGradleJDK(gradleVersion: GradleVersion) {
|
||||
@@ -31,6 +33,28 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@GradleTestVersions(minVersion = "6.7.1")
|
||||
@GradleTest
|
||||
@DisplayName("Default Kotlin toolchain should still allow to set Java source and target compatibility")
|
||||
internal fun shouldNotFailWithDefaultJdkAndCompatibility(gradleVersion: GradleVersion) {
|
||||
project(
|
||||
projectName = "simple".fullProjectName,
|
||||
gradleVersion = gradleVersion
|
||||
) {
|
||||
//lang=Groovy
|
||||
rootBuildGradle.append(
|
||||
"""
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
build("assemble")
|
||||
}
|
||||
}
|
||||
|
||||
@GradleTestVersions(maxVersion = "6.6.1")
|
||||
@GradleTest
|
||||
@DisplayName("Should use provided jdk location to compile Kotlin sources")
|
||||
internal fun customJdkHomeLocation(gradleVersion: GradleVersion) {
|
||||
@@ -46,6 +70,18 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
@@ -57,7 +93,11 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true)
|
||||
) {
|
||||
enableLocalBuildCache(buildCache)
|
||||
useJdk9ToCompile()
|
||||
if (shouldUseToolchain(gradleVersion)) {
|
||||
useToolchainExtension(11)
|
||||
} else {
|
||||
useJdk9ToCompile()
|
||||
}
|
||||
|
||||
build("assemble")
|
||||
}
|
||||
@@ -69,7 +109,11 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true)
|
||||
) {
|
||||
enableLocalBuildCache(buildCache)
|
||||
useJdk9ToCompile()
|
||||
if (shouldUseToolchain(gradleVersion)) {
|
||||
useToolchainExtension(11)
|
||||
} else {
|
||||
useJdk9ToCompile()
|
||||
}
|
||||
|
||||
build("assemble") {
|
||||
assertTasksFromCache(":compileKotlin")
|
||||
@@ -90,7 +134,11 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
) {
|
||||
enableLocalBuildCache(buildCache)
|
||||
enableBuildCacheDebug()
|
||||
useJdk9ToCompile()
|
||||
if (shouldUseToolchain(gradleVersion)) {
|
||||
useToolchainExtension(11)
|
||||
} else {
|
||||
useJdk9ToCompile()
|
||||
}
|
||||
build("assemble")
|
||||
}
|
||||
|
||||
@@ -116,13 +164,23 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
projectName = "simpleWithKapt".fullProjectName,
|
||||
gradleVersion = gradleVersion,
|
||||
) {
|
||||
useJdk9ToCompile()
|
||||
if (shouldUseToolchain(gradleVersion)) {
|
||||
useToolchainExtension(11)
|
||||
} else {
|
||||
useJdk9ToCompile()
|
||||
}
|
||||
gradleProperties.append(
|
||||
"kapt.workers.isolation = none"
|
||||
)
|
||||
|
||||
build("assemble") {
|
||||
assertDaemonIsUsingJdk(getJdk9().javaExecutableRealPath)
|
||||
assertDaemonIsUsingJdk(
|
||||
if (shouldUseToolchain(gradleVersion)) {
|
||||
getToolchainExecPathFromLogs()
|
||||
} else {
|
||||
getJdk9().javaExecutableRealPath
|
||||
}
|
||||
)
|
||||
|
||||
assertOutputContains("Using workers PROCESS isolation mode to run kapt")
|
||||
assertOutputContains("Using non-default Kotlin java toolchain - 'kapt.workers.isolation == none' property is ignored!")
|
||||
@@ -155,7 +213,11 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true)
|
||||
) {
|
||||
enableLocalBuildCache(buildCache)
|
||||
useJdk9ToCompile()
|
||||
if (shouldUseToolchain(gradleVersion)) {
|
||||
useToolchainExtension(11)
|
||||
} else {
|
||||
useJdk9ToCompile()
|
||||
}
|
||||
|
||||
build("assemble")
|
||||
}
|
||||
@@ -167,7 +229,11 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
buildOptions = defaultBuildOptions.copy(buildCacheEnabled = true),
|
||||
) {
|
||||
enableLocalBuildCache(buildCache)
|
||||
useJdk9ToCompile()
|
||||
if (shouldUseToolchain(gradleVersion)) {
|
||||
useToolchainExtension(11)
|
||||
} else {
|
||||
useJdk9ToCompile()
|
||||
}
|
||||
|
||||
build("assemble") {
|
||||
assertTasksFromCache(
|
||||
@@ -244,7 +310,7 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
}
|
||||
|
||||
@DisplayName("Should allow to set JDK version for tasks via Java toolchain")
|
||||
@GradleTestVersions(minVersion = "6.7")
|
||||
@GradleTestVersions(minVersion = "6.7.1")
|
||||
@GradleTest
|
||||
internal fun setJdkUsingJavaToolchain(gradleVersion: GradleVersion) {
|
||||
project(
|
||||
@@ -259,6 +325,22 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("Should allow to set Java toolchain via extension")
|
||||
@GradleTestVersions(minVersion = "6.7.1")
|
||||
@GradleTest
|
||||
internal fun setJdkUsingJavaToolchainViaExtension(gradleVersion: GradleVersion) {
|
||||
project(
|
||||
projectName = "simple".fullProjectName,
|
||||
gradleVersion = gradleVersion,
|
||||
forceOutput = true
|
||||
) {
|
||||
useToolchainExtension(11)
|
||||
build("assemble") {
|
||||
assertDaemonIsUsingJdk(getToolchainExecPathFromLogs())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun BuildResult.assertDaemonIsUsingJdk(
|
||||
javaexecPath: String
|
||||
) = assertOutputContains("i: connected to the daemon. Daemon is using following 'java' executable to run itself: $javaexecPath")
|
||||
@@ -303,13 +385,8 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
"""
|
||||
import org.jetbrains.kotlin.gradle.tasks.UsesKotlinJavaToolchain
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of($jdkVersion))
|
||||
}
|
||||
}
|
||||
|
||||
def toolchain = project.extensions.getByType(JavaPluginExtension.class).toolchain
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of($jdkVersion))
|
||||
def service = project.extensions.getByType(JavaToolchainService.class)
|
||||
def defaultLauncher = service.launcherFor(toolchain)
|
||||
|
||||
@@ -328,6 +405,34 @@ class KotlinJavaToolchainTest : KGPBaseTest() {
|
||||
)
|
||||
}
|
||||
|
||||
private fun TestProject.useToolchainExtension(
|
||||
jdkVersion: Int
|
||||
) {
|
||||
//language=Groovy
|
||||
rootBuildGradle.append(
|
||||
"""
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import org.gradle.jvm.toolchain.JavaToolchainService
|
||||
|
||||
kotlin {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of($jdkVersion))
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
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}")
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
private fun shouldUseToolchain(gradleVersion: GradleVersion) = gradleVersion >= GradleVersion.version("6.7")
|
||||
|
||||
private fun BuildResult.getToolchainExecPathFromLogs() = output
|
||||
.lineSequence()
|
||||
.first { it.startsWith("Toolchain exec path:") }
|
||||
|
||||
+13
-1
@@ -6,9 +6,11 @@
|
||||
package org.jetbrains.kotlin.gradle.dsl
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.internal.plugins.DslObject
|
||||
import org.gradle.jvm.toolchain.JavaToolchainSpec
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
|
||||
@@ -53,13 +55,23 @@ internal val Project.multiplatformExtension: KotlinMultiplatformExtension
|
||||
internal val Project.pm20Extension: KotlinPm20ProjectExtension
|
||||
get() = extensions.getByName(KOTLIN_PROJECT_EXTENSION_NAME) as KotlinPm20ProjectExtension
|
||||
|
||||
|
||||
open class KotlinTopLevelExtension (internal val project: Project) {
|
||||
val experimental: ExperimentalExtension
|
||||
get() = DslObject(this).extensions.getByType(ExperimentalExtension::class.java)
|
||||
|
||||
lateinit var coreLibrariesVersion: String
|
||||
|
||||
private val toolchainSupport = ToolchainSupport.createToolchain(project)
|
||||
|
||||
/**
|
||||
* Configures [Java toolchain](https://docs.gradle.org/current/userguide/toolchains.html) both for Kotlin and Java tasks.
|
||||
*
|
||||
* @param action - action to configure [JavaToolchainSpec]. You could safely cast `Any` into `JavaToolchainSpec`.
|
||||
*/
|
||||
fun toolchain(action: Action<Any>) {
|
||||
toolchainSupport.applyToolchain(action)
|
||||
}
|
||||
|
||||
var explicitApi: ExplicitApiMode? = null
|
||||
|
||||
fun explicitApi() {
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.dsl
|
||||
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.ExtensionContainer
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.internal.jvm.Jvm
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import org.gradle.jvm.toolchain.JavaToolchainService
|
||||
import org.gradle.jvm.toolchain.JavaToolchainSpec
|
||||
import org.gradle.jvm.toolchain.internal.DefaultToolchainSpec
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinJavaToolchain.Companion.TOOLCHAIN_SUPPORTED_VERSION
|
||||
import org.jetbrains.kotlin.gradle.tasks.UsesKotlinJavaToolchain
|
||||
import org.jetbrains.kotlin.gradle.tasks.withType
|
||||
import org.jetbrains.kotlin.gradle.utils.newInstance
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface ToolchainSupport {
|
||||
fun applyToolchain(action: Action<Any>)
|
||||
|
||||
companion object {
|
||||
internal fun createToolchain(
|
||||
project: Project
|
||||
): ToolchainSupport {
|
||||
val currentVersion = GradleVersion.version(project.gradle.gradleVersion)
|
||||
return when {
|
||||
currentVersion < TOOLCHAIN_SUPPORTED_VERSION -> project.objects.newInstance<NonExistingToolchainSupport>()
|
||||
else -> project.objects.newInstance<DefaultToolchainSupport>(project.extensions).also {
|
||||
configureDefaultToolchain(project)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureDefaultToolchain(project: Project) {
|
||||
project.plugins.withId("org.gradle.java-base") {
|
||||
project
|
||||
.tasks
|
||||
.withType<UsesKotlinJavaToolchain>()
|
||||
.configureEach {
|
||||
val javaToolchainService = project
|
||||
.extensions
|
||||
.findByType(JavaToolchainService::class.java)!!
|
||||
val javaToolchainSpec = project
|
||||
.extensions
|
||||
.getByType(JavaPluginExtension::class.java)
|
||||
.toolchain
|
||||
|
||||
val toolchainSpec = if (!javaToolchainSpec.languageVersion.isPresent) {
|
||||
// We can't reuse java toolchain and just set 'languageVersion' to it
|
||||
// as build will fail when java source and/or target compatibility is set
|
||||
project.objects.newInstance<DefaultToolchainSpec>().apply {
|
||||
languageVersion.set(
|
||||
JavaLanguageVersion.of(
|
||||
Jvm.current().javaVersion!!.majorVersion
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
javaToolchainSpec
|
||||
}
|
||||
|
||||
it.kotlinJavaToolchain.toolchain.use(
|
||||
javaToolchainService.launcherFor(toolchainSpec)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class NonExistingToolchainSupport : ToolchainSupport {
|
||||
override fun applyToolchain(
|
||||
action: Action<Any>
|
||||
) {
|
||||
throw GradleException("JavaToolchain support is only available from Gradle 6.7")
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class DefaultToolchainSupport @Inject constructor(
|
||||
private val extensions: ExtensionContainer
|
||||
) : ToolchainSupport {
|
||||
private val toolchainSpec: JavaToolchainSpec
|
||||
get() = extensions
|
||||
.getByType(JavaPluginExtension::class.java)
|
||||
.toolchain
|
||||
|
||||
override fun applyToolchain(
|
||||
action: Action<Any>
|
||||
) {
|
||||
action.execute(toolchainSpec)
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -7,7 +7,6 @@ import org.gradle.api.internal.ConventionTask
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.ProviderFactory
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
|
||||
@@ -121,8 +120,10 @@ abstract class KaptTask @Inject constructor(
|
||||
@get:Internal
|
||||
abstract val classpath: ConfigurableFileCollection
|
||||
|
||||
final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchainProvider> =
|
||||
objectFactory.propertyWithNewInstance()
|
||||
final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchainProvider> = objectFactory
|
||||
.propertyWithNewInstance(
|
||||
project.gradle
|
||||
)
|
||||
|
||||
@Suppress("unused", "DeprecatedCallableAddReplaceWith")
|
||||
@Deprecated(
|
||||
|
||||
+2
-2
@@ -114,8 +114,8 @@ abstract class KaptWithKotlincTask @Inject constructor(
|
||||
|
||||
val compilerRunner = GradleCompilerRunner(
|
||||
taskProvider,
|
||||
kotlinJavaToolchainProvider.get().javaExecutable.get().asFile,
|
||||
kotlinJavaToolchainProvider.get().jdkToolsJar.orNull
|
||||
kotlinJavaToolchainProvider.get().jdkProvider.javaExecutable.get().asFile,
|
||||
kotlinJavaToolchainProvider.get().jdkProvider.jdkToolsJar.orNull
|
||||
)
|
||||
compilerRunner.runJvmCompilerAsync(
|
||||
sourcesToCompile = emptyList(),
|
||||
|
||||
+12
-6
@@ -160,7 +160,9 @@ abstract class KaptWithoutKotlincTask @Inject constructor(
|
||||
val kaptClasspath = kaptJars.toList() + kotlinStdlibClasspath
|
||||
val isolationMode = getWorkerIsolationMode()
|
||||
logger.info("Using workers $isolationMode isolation mode to run kapt")
|
||||
val toolsJarURLSpec = kotlinJavaToolchainProvider.get().jdkToolsJar.orNull?.toURI()?.toURL()?.toString().orEmpty()
|
||||
val toolsJarURLSpec = kotlinJavaToolchainProvider.get()
|
||||
.jdkProvider
|
||||
.jdkToolsJar.orNull?.toURI()?.toURL()?.toString().orEmpty()
|
||||
|
||||
submitWork(
|
||||
isolationMode,
|
||||
@@ -171,12 +173,12 @@ abstract class KaptWithoutKotlincTask @Inject constructor(
|
||||
}
|
||||
|
||||
private fun getWorkerIsolationMode(): IsolationMode {
|
||||
val kotlinJavaToolchain = kotlinJavaToolchainProvider.get()
|
||||
val gradleJvm = kotlinJavaToolchain.currentJvm.get()
|
||||
val jdkProvider = kotlinJavaToolchainProvider.get().jdkProvider
|
||||
val gradleJvm = jdkProvider.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 == kotlinJavaToolchain.javaVersion.get() &&
|
||||
gradleJvm.javaExecutable.absolutePath == kotlinJavaToolchain.javaExecutable.get().asFile.absolutePath
|
||||
val isRunningOnGradleJvm = gradleJvm.javaVersion == jdkProvider.javaVersion.get() &&
|
||||
gradleJvm.javaExecutable.absolutePath == jdkProvider.javaExecutable.get().asFile.absolutePath
|
||||
val isolationModeStr = getValue("kapt.workers.isolation")?.toLowerCase()
|
||||
return when {
|
||||
(isolationModeStr == null || isolationModeStr == "none") && isRunningOnGradleJvm -> IsolationMode.NONE
|
||||
@@ -201,7 +203,11 @@ abstract class KaptWithoutKotlincTask @Inject constructor(
|
||||
// for tests
|
||||
it.forkOptions.jvmArgs("-verbose:class")
|
||||
}
|
||||
it.forkOptions.executable = kotlinJavaToolchainProvider.get().javaExecutable.asFile.get().absolutePath
|
||||
it.forkOptions.executable = kotlinJavaToolchainProvider.get()
|
||||
.jdkProvider
|
||||
.javaExecutable
|
||||
.asFile.get()
|
||||
.absolutePath
|
||||
logger.info("Kapt worker classpath: ${it.classpath}")
|
||||
}
|
||||
IsolationMode.NONE -> workerExecutor.noIsolation()
|
||||
|
||||
+161
-69
@@ -9,12 +9,15 @@ 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.invocation.Gradle
|
||||
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.gradle.jvm.toolchain.JavaLauncher
|
||||
import org.gradle.jvm.toolchain.*
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinJavaToolchain.Companion.TOOLCHAIN_SUPPORTED_VERSION
|
||||
import org.jetbrains.kotlin.gradle.utils.chainedFinalizeValueOnRead
|
||||
import org.jetbrains.kotlin.gradle.utils.property
|
||||
import org.jetbrains.kotlin.gradle.utils.propertyWithConvention
|
||||
@@ -23,98 +26,187 @@ import javax.inject.Inject
|
||||
|
||||
abstract class KotlinJavaToolchainProvider @Inject constructor(
|
||||
objects: ObjectFactory,
|
||||
files: ProjectLayout
|
||||
projectLayout: ProjectLayout,
|
||||
gradle: Gradle
|
||||
) : KotlinJavaToolchain {
|
||||
@get:Internal
|
||||
internal 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()
|
||||
)
|
||||
}
|
||||
private val defaultJdkSetter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
DefaultJdkSetter(
|
||||
objects,
|
||||
projectLayout,
|
||||
GradleVersion.version(gradle.gradleVersion)
|
||||
)
|
||||
}
|
||||
|
||||
private val defaultJavaToolchainSetter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
if (GradleVersion.version(gradle.gradleVersion) >= TOOLCHAIN_SUPPORTED_VERSION) {
|
||||
DefaultJavaToolchainSetter(objects)
|
||||
} 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() = _javaVersion
|
||||
get() = jdkProvider.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()
|
||||
)
|
||||
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 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
|
||||
)
|
||||
.chainedFinalizeValueOnRead()
|
||||
|
||||
private val _jdkToolsJar = objects
|
||||
.propertyWithConvention(
|
||||
currentJvm.flatMap { jvm ->
|
||||
objects.propertyWithConvention(jvm.toolsJar)
|
||||
}
|
||||
override val jdkToolsJar: Provider<File?> = JdkProvider.defaultJdkToolsJarProvider(
|
||||
objectsFactory,
|
||||
javaVersion,
|
||||
_jdkToolsJar
|
||||
)
|
||||
.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 val jdk: KotlinJavaToolchain.JdkSetter = DefaultJdkSetter()
|
||||
|
||||
override val toolchain: KotlinJavaToolchain.JavaToolchainSetter = DefaultJavaToolchainSetter()
|
||||
|
||||
private inner class DefaultJdkSetter : KotlinJavaToolchain.JdkSetter {
|
||||
override fun use(
|
||||
jdkHomeLocation: File,
|
||||
jdkVersion: JavaVersion
|
||||
) {
|
||||
if (currentGradleVersion >= TOOLCHAIN_SUPPORTED_VERSION) {
|
||||
throw GradleException(
|
||||
"Please use Java toolchains instead"
|
||||
)
|
||||
}
|
||||
|
||||
val jvm = Jvm.forHome(jdkHomeLocation) as Jvm
|
||||
|
||||
javaExecutable.set(jvm.javaExecutable)
|
||||
_jdkToolsJar.set(jvm.toolsJar)
|
||||
_javaVersion.set(jdkVersion)
|
||||
javaVersion.set(jdkVersion)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class DefaultJavaToolchainSetter : KotlinJavaToolchain.JavaToolchainSetter {
|
||||
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
|
||||
)
|
||||
|
||||
override fun use(
|
||||
javaLauncher: Provider<JavaLauncher>
|
||||
) {
|
||||
javaExecutable.set(javaLauncher.map { it.executablePath })
|
||||
_javaVersion.set(
|
||||
javaLauncher.map {
|
||||
JavaVersion.toVersion(it.metadata.languageVersion)
|
||||
}
|
||||
)
|
||||
_jdkToolsJar.set(
|
||||
javaLauncher.map {
|
||||
Jvm.forHome(it.metadata.installationPath.asFile).toolsJar
|
||||
}
|
||||
)
|
||||
this.javaLauncher.set(javaLauncher)
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-4
@@ -245,16 +245,18 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
|
||||
|
||||
private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
|
||||
|
||||
final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchainProvider> =
|
||||
objects.propertyWithNewInstance()
|
||||
final override val kotlinJavaToolchainProvider: Provider<KotlinJavaToolchainProvider> = objects
|
||||
.propertyWithNewInstance(
|
||||
project.gradle
|
||||
)
|
||||
|
||||
@get:Internal
|
||||
internal val compilerRunner: Provider<GradleCompilerRunner> =
|
||||
objects.propertyWithConvention(
|
||||
kotlinJavaToolchainProvider.map {
|
||||
compilerRunner(
|
||||
it.javaExecutable.get().asFile,
|
||||
it.jdkToolsJar.orNull
|
||||
it.jdkProvider.javaExecutable.get().asFile,
|
||||
it.jdkProvider.jdkToolsJar.orNull
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
+6
-1
@@ -42,6 +42,8 @@ internal inline fun <reified T : Any?> ObjectFactory.property() = property(T::cl
|
||||
|
||||
internal inline fun <reified T : Any?> ObjectFactory.property(initialValue: T) = property<T>().value(initialValue)
|
||||
|
||||
internal inline fun <reified T : Any?> ObjectFactory.property(initialValue: Provider<T>) = property<T>().value(initialValue)
|
||||
|
||||
internal inline fun <reified T : Any?> ObjectFactory.propertyWithConvention(
|
||||
conventionValue: Provider<T>
|
||||
) = property<T>().convention(conventionValue)
|
||||
@@ -52,9 +54,12 @@ internal inline fun <reified T : Any?> ObjectFactory.propertyWithConvention(
|
||||
|
||||
internal inline fun <reified T : Any> ObjectFactory.newInstance() = newInstance(T::class.java)
|
||||
|
||||
internal inline fun <reified T : Any> ObjectFactory.newInstance(vararg parameters: Any) =
|
||||
newInstance(T::class.java, *parameters)
|
||||
|
||||
internal inline fun <reified T : Any> ObjectFactory.propertyWithNewInstance(
|
||||
vararg parameters: Any
|
||||
) = propertyWithConvention(newInstance(T::class.java, parameters))
|
||||
) = propertyWithConvention(newInstance(T::class.java, *parameters))
|
||||
|
||||
internal inline fun <reified T : Any> ObjectFactory.propertyWithNewInstance() =
|
||||
propertyWithConvention(newInstance<T>())
|
||||
|
||||
Reference in New Issue
Block a user