Optionally make java executable path contribute to the daemon id.
This change will allow to start Kotlin daemon instances using different from the current user JDK version and use it to compile Kotlin files. Old behaviour, when java executable path is not set, is still working and still,by default, using current user JDK version. For example, user for some reason wants to use JDK 1.8 as active one, but compile current project using JDK 16. Main goal is to support Gradle toolchains. ^KT-45611 In Progress
This commit is contained in:
committed by
TeamCityServer
parent
1d47f4ad2b
commit
ac86ad252f
+9
-3
@@ -367,8 +367,14 @@ object KotlinCompilerClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun startDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, reportingTargets: DaemonReportingTargets): Boolean {
|
private fun startDaemon(
|
||||||
val javaExecutable = File(File(CompilerSystemProperties.JAVA_HOME.safeValue, "bin"), "java")
|
compilerId: CompilerId,
|
||||||
|
daemonJVMOptions: DaemonJVMOptions,
|
||||||
|
daemonOptions: DaemonOptions,
|
||||||
|
reportingTargets: DaemonReportingTargets
|
||||||
|
): Boolean {
|
||||||
|
val daemonJavaExecutable = compilerId.javaExecutable
|
||||||
|
?: File(File(CompilerSystemProperties.JAVA_HOME.safeValue, "bin"), "java")
|
||||||
val serverHostname = CompilerSystemProperties.JAVA_RMI_SERVER_HOSTNAME.value ?: error("${CompilerSystemProperties.JAVA_RMI_SERVER_HOSTNAME.property} is not set!")
|
val serverHostname = CompilerSystemProperties.JAVA_RMI_SERVER_HOSTNAME.value ?: error("${CompilerSystemProperties.JAVA_RMI_SERVER_HOSTNAME.property} is not set!")
|
||||||
val platformSpecificOptions = listOf(
|
val platformSpecificOptions = listOf(
|
||||||
// hide daemon window
|
// hide daemon window
|
||||||
@@ -380,7 +386,7 @@ object KotlinCompilerClient {
|
|||||||
listOf("--illegal-access=permit")
|
listOf("--illegal-access=permit")
|
||||||
else emptyList()
|
else emptyList()
|
||||||
val args = listOf(
|
val args = listOf(
|
||||||
javaExecutable.absolutePath, "-cp", compilerId.compilerClasspath.joinToString(File.pathSeparator)) +
|
daemonJavaExecutable.absolutePath, "-cp", compilerId.compilerClasspath.joinToString(File.pathSeparator)) +
|
||||||
platformSpecificOptions +
|
platformSpecificOptions +
|
||||||
daemonJVMOptions.mappers.flatMap { it.toArgs("-") } +
|
daemonJVMOptions.mappers.flatMap { it.toArgs("-") } +
|
||||||
javaIllegalAccessWorkaround +
|
javaIllegalAccessWorkaround +
|
||||||
|
|||||||
+33
-3
@@ -231,15 +231,36 @@ fun ByteArray.toHexString(): String = joinToString("", transform = { "%02x".form
|
|||||||
|
|
||||||
data class CompilerId(
|
data class CompilerId(
|
||||||
var compilerClasspath: List<String> = listOf(),
|
var compilerClasspath: List<String> = listOf(),
|
||||||
var compilerVersion: String = ""
|
var compilerVersion: String = "",
|
||||||
|
var javaExecutable: File? = null
|
||||||
) : OptionsGroup {
|
) : OptionsGroup {
|
||||||
|
|
||||||
override val mappers: List<PropMapper<*, *, *>>
|
override val mappers: List<PropMapper<*, *, *>>
|
||||||
get() = listOf(PropMapper(this, CompilerId::compilerClasspath, toString = { it.joinToString(File.pathSeparator) }, fromString = { it.trimQuotes().split(File.pathSeparator) }),
|
get() = listOf(
|
||||||
StringPropMapper(this, CompilerId::compilerVersion))
|
PropMapper(
|
||||||
|
dest = this,
|
||||||
|
prop = CompilerId::compilerClasspath,
|
||||||
|
toString = { it.joinToString(File.pathSeparator) },
|
||||||
|
fromString = { it.trimQuotes().split(File.pathSeparator) }
|
||||||
|
),
|
||||||
|
StringPropMapper(
|
||||||
|
dest = this,
|
||||||
|
prop = CompilerId::compilerVersion
|
||||||
|
),
|
||||||
|
PropMapper(
|
||||||
|
dest = this,
|
||||||
|
prop = CompilerId::javaExecutable,
|
||||||
|
toString = { it?.absolutePath },
|
||||||
|
fromString = { File(it.trimQuotes()) },
|
||||||
|
skipIf = { it == null }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
fun digest(): String = compilerClasspath
|
fun digest(): String = compilerClasspath
|
||||||
.map { File(it).absolutePath }
|
.map { File(it).absolutePath }
|
||||||
|
.run {
|
||||||
|
javaExecutable?.let { plus(it.absolutePath) } ?: this
|
||||||
|
}
|
||||||
.distinctStringsDigest()
|
.distinctStringsDigest()
|
||||||
.toHexString()
|
.toHexString()
|
||||||
|
|
||||||
@@ -250,6 +271,15 @@ data class CompilerId(
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun makeCompilerId(paths: Iterable<File>): CompilerId =
|
fun makeCompilerId(paths: Iterable<File>): CompilerId =
|
||||||
CompilerId(compilerClasspath = paths.map { it.absolutePath })
|
CompilerId(compilerClasspath = paths.map { it.absolutePath })
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun makeCompilerId(
|
||||||
|
paths: Iterable<File>,
|
||||||
|
javaExecutable: File
|
||||||
|
): CompilerId = CompilerId(
|
||||||
|
compilerClasspath = paths.map { it.absolutePath },
|
||||||
|
javaExecutable = javaExecutable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.daemon
|
package org.jetbrains.kotlin.daemon
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.SystemInfo
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.openapi.util.io.FileUtilRt
|
import com.intellij.openapi.util.io.FileUtilRt
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
@@ -277,6 +278,129 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getJdk8Location() = System.getenv("JDK_18") ?: System.getenv("JAVA_HOME")
|
||||||
|
|
||||||
|
fun testNewDaemonIsNotStartedForSameJavaExecutable() {
|
||||||
|
withFlagFile(getTestName(true), "-client1.alive") { flagFile1 ->
|
||||||
|
withFlagFile(getTestName(true), "-client2.alive") { flagFile2 ->
|
||||||
|
val daemonOptions = makeTestDaemonOptions(getTestName(true))
|
||||||
|
val compilerIdJdk8 = CompilerId.makeCompilerId(
|
||||||
|
compilerClassPath +
|
||||||
|
File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-compiler-sources.jar"),
|
||||||
|
File(getJdk8Location()).resolve("bin/java")
|
||||||
|
)
|
||||||
|
|
||||||
|
withLogFile("kotlin-daemon-test-1") { logFile ->
|
||||||
|
val daemonJVMOptions = makeTestDaemonJvmOptions(logFile)
|
||||||
|
assertTrue(logFile.length() == 0L)
|
||||||
|
|
||||||
|
val daemon1 = KotlinCompilerClient.connectToCompileService(
|
||||||
|
compilerIdJdk8,
|
||||||
|
flagFile1,
|
||||||
|
daemonJVMOptions,
|
||||||
|
daemonOptions,
|
||||||
|
DaemonReportingTargets(out = System.err),
|
||||||
|
autostart = true
|
||||||
|
)
|
||||||
|
assertNotNull("failed to connect daemon", daemon1)
|
||||||
|
logFile.assertLogContainsSequence("INFO: starting daemon")
|
||||||
|
|
||||||
|
|
||||||
|
val daemon2 = KotlinCompilerClient.connectToCompileService(
|
||||||
|
compilerIdJdk8,
|
||||||
|
flagFile2,
|
||||||
|
daemonJVMOptions,
|
||||||
|
daemonOptions,
|
||||||
|
DaemonReportingTargets(out = System.err),
|
||||||
|
autostart = true
|
||||||
|
)
|
||||||
|
assertNotNull("failed to connect daemon", daemon2)
|
||||||
|
|
||||||
|
val logContent = logFile.readText().lines()
|
||||||
|
assert(
|
||||||
|
logContent.filter { it.contains("INFO: starting daemon") }.size == 1
|
||||||
|
) {
|
||||||
|
"Second daemon instance was started!"
|
||||||
|
}
|
||||||
|
assert(
|
||||||
|
logContent.filter {
|
||||||
|
it.contains("INFO: Registered a client alive file: ${flagFile2.absolutePath}")
|
||||||
|
}.size == 1
|
||||||
|
) {
|
||||||
|
"Second client was not connected to the same instance!"
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinCompilerClient.shutdownCompileService(compilerIdJdk8, daemonOptions)
|
||||||
|
|
||||||
|
Thread.sleep(100)
|
||||||
|
|
||||||
|
logFile.assertLogContainsSequence("Shutdown started")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignored on Windows OS due to https://bugs.openjdk.java.net/browse/JDK-8189953 bug in JDK 9
|
||||||
|
// Should be unignored once JDK10+ will be available by default on CI agents
|
||||||
|
fun testNewDaemonIsStartedOnJavaExecutableChange() {
|
||||||
|
if (SystemInfo.isWindows) return
|
||||||
|
|
||||||
|
withFlagFile(getTestName(true), "-client1.alive") { flagFile1 ->
|
||||||
|
withFlagFile(getTestName(true), "-client2.alive") { flagFile2 ->
|
||||||
|
val daemonOptions = makeTestDaemonOptions(getTestName(true))
|
||||||
|
val compilerIdJdk8 = CompilerId.makeCompilerId(
|
||||||
|
compilerClassPath +
|
||||||
|
File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-compiler-sources.jar"),
|
||||||
|
File(getJdk8Location()).resolve("bin/java")
|
||||||
|
)
|
||||||
|
val compilerIdJdk9 = CompilerId.makeCompilerId(
|
||||||
|
compilerClassPath +
|
||||||
|
File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-compiler-sources.jar"),
|
||||||
|
File(System.getenv("JDK_9")).resolve("bin/java")
|
||||||
|
)
|
||||||
|
|
||||||
|
withLogFile("kotlin-daemon-test-1") { logFile1 ->
|
||||||
|
withLogFile("kotlin-daemon-test-2") { logFile2 ->
|
||||||
|
val daemonJdk8JVMOptions = makeTestDaemonJvmOptions(logFile1)
|
||||||
|
assertTrue(logFile1.length() == 0L)
|
||||||
|
val daemonJdk9JVMOptions = makeTestDaemonJvmOptions(logFile2)
|
||||||
|
assertTrue(logFile2.length() == 0L)
|
||||||
|
|
||||||
|
val daemonJdk7 = KotlinCompilerClient.connectToCompileService(
|
||||||
|
compilerIdJdk8,
|
||||||
|
flagFile1,
|
||||||
|
daemonJdk8JVMOptions,
|
||||||
|
daemonOptions,
|
||||||
|
DaemonReportingTargets(out = System.err),
|
||||||
|
autostart = true
|
||||||
|
)
|
||||||
|
assertNotNull("failed to connect daemon", daemonJdk7)
|
||||||
|
logFile1.assertLogContainsSequence("INFO: starting daemon")
|
||||||
|
|
||||||
|
val daemonJdk9 = KotlinCompilerClient.connectToCompileService(
|
||||||
|
compilerIdJdk9,
|
||||||
|
flagFile2,
|
||||||
|
daemonJdk9JVMOptions,
|
||||||
|
daemonOptions,
|
||||||
|
DaemonReportingTargets(out = System.err),
|
||||||
|
autostart = true
|
||||||
|
)
|
||||||
|
assertNotNull("failed to connect daemon", daemonJdk9)
|
||||||
|
logFile2.assertLogContainsSequence("INFO: starting daemon")
|
||||||
|
|
||||||
|
KotlinCompilerClient.shutdownCompileService(compilerIdJdk8, daemonOptions)
|
||||||
|
KotlinCompilerClient.shutdownCompileService(compilerIdJdk9, daemonOptions)
|
||||||
|
|
||||||
|
Thread.sleep(100)
|
||||||
|
|
||||||
|
logFile1.assertLogContainsSequence("Shutdown started")
|
||||||
|
logFile2.assertLogContainsSequence("Shutdown started")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun testDaemonRunError() {
|
fun testDaemonRunError() {
|
||||||
withFlagFile(getTestName(true), ".alive") { flagFile ->
|
withFlagFile(getTestName(true), ".alive") { flagFile ->
|
||||||
val daemonOptions = DaemonOptions(shutdownDelayMilliseconds = 1, verbose = true, runFilesPath = File(testTempDir, getTestName(true)).absolutePath)
|
val daemonOptions = DaemonOptions(shutdownDelayMilliseconds = 1, verbose = true, runFilesPath = File(testTempDir, getTestName(true)).absolutePath)
|
||||||
|
|||||||
Reference in New Issue
Block a user