diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/Properties.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/Properties.kt index 1f0a64fa783..33b9a4ef343 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/Properties.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/Properties.kt @@ -16,8 +16,48 @@ package org.jetbrains.kotlin.cli.common -val KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY = "kotlin.environment.keepalive" +import com.intellij.util.LineSeparator +import java.util.* +enum class CompilerSystemProperties(val property: String) { + COMPILE_DAEMON_ENABLED_PROPERTY("kotlin.daemon.enabled"), + COMPILE_DAEMON_JVM_OPTIONS_PROPERTY("kotlin.daemon.jvm.options"), + COMPILE_DAEMON_OPTIONS_PROPERTY("kotlin.daemon.options"), + COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY("kotlin.daemon.client.options"), + COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY("kotlin.daemon.client.alive.path"), + COMPILE_DAEMON_LOG_PATH_PROPERTY("kotlin.daemon.log.path"), + COMPILE_DAEMON_REPORT_PERF_PROPERTY("kotlin.daemon.perf"), + COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY("kotlin.daemon.verbose"), + COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY("kotlin.daemon.startup.timeout"), + JAVA_RMI_SERVER_HOSTNAME("java.rmi.server.hostname"), + DAEMON_RMI_SOCKET_BACKLOG_SIZE_PROPERTY("kotlin.daemon.socket.backlog.size"), + DAEMON_RMI_SOCKET_CONNECT_ATTEMPTS_PROPERTY("kotlin.daemon.socket.connect.attempts"), + DAEMON_RMI_SOCKET_CONNECT_INTERVAL_PROPERTY("kotlin.daemon.socket.connect.interval"), + KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY("kotlin.environment.keepalive"), + COMPILE_DAEMON_CUSTOM_RUN_FILES_PATH_FOR_TESTS("kotlin.daemon.custom.run.files.path.for.tests"), + KOTLIN_COLORS_ENABLED_PROPERTY("kotlin.colors.enabled"), + OS_NAME("os.name") + ; + + var value + get() = systemPropertyGetter(property) + set(value) { + systemPropertySetter(property, value!!) + } + + companion object { + var systemPropertyGetter: (String) -> String? = { + System.getProperty(it) + } + + var systemPropertySetter: (String, String) -> String? = { key, value -> + System.setProperty(key, value) + } + } +} + +val isWindows: Boolean + get() = CompilerSystemProperties.OS_NAME.value!!.toLowerCase(Locale.ENGLISH).startsWith("windows") fun String?.toBooleanLenient(): Boolean? = when (this?.toLowerCase()) { null -> false diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt index dfea75bfe4d..d6a75fa5e1e 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt @@ -205,8 +205,8 @@ abstract class CLITool { if (System.getProperty("java.awt.headless") == null) { System.setProperty("java.awt.headless", "true") } - if (System.getProperty(PlainTextMessageRenderer.KOTLIN_COLORS_ENABLED_PROPERTY) == null) { - System.setProperty(PlainTextMessageRenderer.KOTLIN_COLORS_ENABLED_PROPERTY, "true") + if (CompilerSystemProperties.KOTLIN_COLORS_ENABLED_PROPERTY.value == null) { + CompilerSystemProperties.KOTLIN_COLORS_ENABLED_PROPERTY.value = "true" } setupIdeaStandaloneExecution() diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/PlainTextMessageRenderer.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/PlainTextMessageRenderer.java index 8f8c9a052cd..183a1ffc3af 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/PlainTextMessageRenderer.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/PlainTextMessageRenderer.java @@ -16,13 +16,13 @@ package org.jetbrains.kotlin.cli.common.messages; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.util.LineSeparator; import kotlin.text.StringsKt; import org.fusesource.jansi.Ansi; import org.fusesource.jansi.internal.CLibrary; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.cli.common.CompilerSystemProperties; +import org.jetbrains.kotlin.cli.common.PropertiesKt; import org.jetbrains.kotlin.util.capitalizeDecapitalize.CapitalizeDecapitalizeKt; import java.util.EnumSet; @@ -31,13 +31,12 @@ import java.util.Set; import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*; public abstract class PlainTextMessageRenderer implements MessageRenderer { - public static final String KOTLIN_COLORS_ENABLED_PROPERTY = "kotlin.colors.enabled"; public static final boolean COLOR_ENABLED; static { boolean colorEnabled = false; // TODO: investigate why ANSI escape codes on Windows only work in REPL for some reason - if (!SystemInfo.isWindows && "true".equals(System.getProperty(KOTLIN_COLORS_ENABLED_PROPERTY))) { + if (!PropertiesKt.isWindows() && "true".equals(CompilerSystemProperties.KOTLIN_COLORS_ENABLED_PROPERTY.getValue())) { try { // AnsiConsole doesn't check isatty() for stderr (see https://github.com/fusesource/jansi/pull/35). colorEnabled = CLibrary.isatty(CLibrary.STDERR_FILENO) != 0; @@ -49,7 +48,7 @@ public abstract class PlainTextMessageRenderer implements MessageRenderer { COLOR_ENABLED = colorEnabled; } - private static final String LINE_SEPARATOR = LineSeparator.getSystemLineSeparator().getSeparatorString(); + private static final String LINE_SEPARATOR = System.lineSeparator(); private static final Set IMPORTANT_MESSAGE_SEVERITIES = EnumSet.of(EXCEPTION, ERROR, STRONG_WARNING, WARNING); diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index 2b1ba524c7e..5caa291fbc6 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -58,7 +58,7 @@ import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.CliModuleVisibilityManagerImpl -import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY +import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.cli.common.config.ContentRoot import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots @@ -498,7 +498,7 @@ class KotlinCoreEnvironment private constructor( } // Disposing of the environment is unsafe in production then parallel builds are enabled, but turning it off universally // breaks a lot of tests, therefore it is disabled for production and enabled for tests - if (System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY).toBooleanLenient() != true) { + if (CompilerSystemProperties.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY.value.toBooleanLenient() != true) { // JPS may run many instances of the compiler in parallel (there's an option for compiling independent modules in parallel in IntelliJ) // All projects share the same ApplicationEnvironment, and when the last project is disposed, the ApplicationEnvironment is disposed as well @Suppress("ObjectLiteralToLambda") // Disposer tree depends on identity of disposables. diff --git a/compiler/daemon/daemon-client-new/src/org/jetbrains/kotlin/daemon/client/experimental/KotlinCompilerClient.kt b/compiler/daemon/daemon-client-new/src/org/jetbrains/kotlin/daemon/client/experimental/KotlinCompilerClient.kt index 16e26d29b41..3d7b73f38cc 100644 --- a/compiler/daemon/daemon-client-new/src/org/jetbrains/kotlin/daemon/client/experimental/KotlinCompilerClient.kt +++ b/compiler/daemon/daemon-client-new/src/org/jetbrains/kotlin/daemon/client/experimental/KotlinCompilerClient.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.Deferred import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking +import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.daemon.client.CompileServiceSessionAsync @@ -44,13 +45,13 @@ class KotlinCompilerClient : KotlinCompilerDaemonClient { val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L val DAEMON_CONNECT_CYCLE_ATTEMPTS = 3 - val verboseReporting = System.getProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY) != null + val verboseReporting = CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.value != null private val log = Logger.getLogger("KotlinCompilerClient") override fun getOrCreateClientFlagFile(daemonOptions: DaemonOptions): File = // for jps property is passed from IDEA to JPS in KotlinBuildProcessParametersProvider - System.getProperty(COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY) + CompilerSystemProperties.COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY.value ?.let(String::trimQuotes) ?.takeUnless(String::isBlank) ?.let(::File) @@ -210,8 +211,6 @@ class KotlinCompilerClient : KotlinCompilerDaemonClient { } } - val COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY: String = "kotlin.daemon.client.options" - data class ClientOptions( var stop: Boolean = false ) : OptionsGroup { @@ -220,11 +219,11 @@ class KotlinCompilerClient : KotlinCompilerDaemonClient { } private fun configureClientOptions(opts: ClientOptions): ClientOptions { - System.getProperty(COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY)?.let { + CompilerSystemProperties.COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY.value?.let { val unrecognized = it.trimQuotes().split(",").filterExtractProps(opts.mappers, "") if (unrecognized.any()) throw IllegalArgumentException( - "Unrecognized client options passed via property $COMPILE_DAEMON_OPTIONS_PROPERTY: " + unrecognized.joinToString(" ") + + "Unrecognized client options passed via property ${CompilerSystemProperties.COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY.property}: " + unrecognized.joinToString(" ") + "\nSupported options: " + opts.mappers.joinToString(", ", transform = { it.names.first() }) ) } @@ -456,11 +455,11 @@ class KotlinCompilerClient : KotlinCompilerDaemonClient { reportingTargets: DaemonReportingTargets ): Boolean { val javaExecutable = File(File(System.getProperty("java.home"), "bin"), "java") - val serverHostname = System.getProperty(JAVA_RMI_SERVER_HOSTNAME) ?: error("$JAVA_RMI_SERVER_HOSTNAME is not set!") + val serverHostname = CompilerSystemProperties.JAVA_RMI_SERVER_HOSTNAME.value ?: error("${CompilerSystemProperties.JAVA_RMI_SERVER_HOSTNAME.property} is not set!") val platformSpecificOptions = listOf( // hide daemon window "-Djava.awt.headless=true", - "-D$JAVA_RMI_SERVER_HOSTNAME=$serverHostname" + "-D${CompilerSystemProperties.JAVA_RMI_SERVER_HOSTNAME.property}=$serverHostname" ) val args = listOf( javaExecutable.absolutePath, "-cp", compilerId.compilerClasspath.joinToString(File.pathSeparator) @@ -509,13 +508,13 @@ class KotlinCompilerClient : KotlinCompilerDaemonClient { } try { // trying to wait for process - val daemonStartupTimeout = System.getProperty(COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY)?.let { + val daemonStartupTimeout = CompilerSystemProperties.COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY.value?.let { try { it.toLong() } catch (e: Exception) { reportingTargets.report( DaemonReportCategory.INFO, - "unable to interpret $COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY property ('$it'); using default timeout $DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ms" + "unable to interpret ${CompilerSystemProperties.COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY.property} property ('$it'); using default timeout $DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ms" ) null } diff --git a/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/KotlinCompilerClient.kt b/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/KotlinCompilerClient.kt index 4ba36cd27fd..e2f0dbd4592 100644 --- a/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/KotlinCompilerClient.kt +++ b/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/KotlinCompilerClient.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.daemon.client +import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.daemon.common.* @@ -48,11 +49,11 @@ object KotlinCompilerClient { val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L val DAEMON_CONNECT_CYCLE_ATTEMPTS = 3 - val verboseReporting = System.getProperty(COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY) != null + val verboseReporting = CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.value != null fun getOrCreateClientFlagFile(daemonOptions: DaemonOptions): File = // for jps property is passed from IDEA to JPS in KotlinBuildProcessParametersProvider - System.getProperty(COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY) + CompilerSystemProperties.COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY.value ?.let(String::trimQuotes) ?.takeUnless(String::isBlank) ?.let(::File) @@ -211,7 +212,6 @@ object KotlinCompilerClient { ).get() } - val COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY: String = "kotlin.daemon.client.options" data class ClientOptions( var stop: Boolean = false ) : OptionsGroup { @@ -220,11 +220,11 @@ object KotlinCompilerClient { } private fun configureClientOptions(opts: ClientOptions): ClientOptions { - System.getProperty(COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY)?.let { + CompilerSystemProperties.COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY.value?.let { val unrecognized = it.trimQuotes().split(",").filterExtractProps(opts.mappers, "") if (unrecognized.any()) throw IllegalArgumentException( - "Unrecognized client options passed via property $COMPILE_DAEMON_OPTIONS_PROPERTY: " + unrecognized.joinToString(" ") + + "Unrecognized client options passed via property ${CompilerSystemProperties.COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY.property}: " + unrecognized.joinToString(" ") + "\nSupported options: " + opts.mappers.joinToString(", ", transform = { it.names.first() })) } return opts @@ -369,11 +369,11 @@ object KotlinCompilerClient { private fun startDaemon(compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, daemonOptions: DaemonOptions, reportingTargets: DaemonReportingTargets): Boolean { val javaExecutable = File(File(System.getProperty("java.home"), "bin"), "java") - val serverHostname = System.getProperty(JAVA_RMI_SERVER_HOSTNAME) ?: error("$JAVA_RMI_SERVER_HOSTNAME is not set!") + val serverHostname = CompilerSystemProperties.JAVA_RMI_SERVER_HOSTNAME.value ?: error("${CompilerSystemProperties.JAVA_RMI_SERVER_HOSTNAME.property} is not set!") val platformSpecificOptions = listOf( // hide daemon window "-Djava.awt.headless=true", - "-D$JAVA_RMI_SERVER_HOSTNAME=$serverHostname") + "-D$${CompilerSystemProperties.JAVA_RMI_SERVER_HOSTNAME.property}=$serverHostname") val javaVersion = System.getProperty("java.specification.version")?.toIntOrNull() val javaIllegalAccessWorkaround = if (javaVersion != null && javaVersion >= 16) @@ -424,12 +424,12 @@ object KotlinCompilerClient { } try { // trying to wait for process - val daemonStartupTimeout = System.getProperty(COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY)?.let { + val daemonStartupTimeout = CompilerSystemProperties.COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY.value?.let { try { it.toLong() } catch (e: Exception) { - reportingTargets.report(DaemonReportCategory.INFO, "unable to interpret $COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY property ('$it'); using default timeout $DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ms") + reportingTargets.report(DaemonReportCategory.INFO, "unable to interpret ${CompilerSystemProperties.COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY.property} property ('$it'); using default timeout $DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ms") null } } ?: DAEMON_DEFAULT_STARTUP_TIMEOUT_MS diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/DaemonParams.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/DaemonParams.kt index 8ca966bcb29..0afa4443ca8 100644 --- a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/DaemonParams.kt +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/DaemonParams.kt @@ -16,7 +16,7 @@ package org.jetbrains.kotlin.daemon.common -import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY +import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import java.io.File import java.io.Serializable import java.lang.management.ManagementFactory @@ -24,53 +24,47 @@ import java.security.MessageDigest import java.util.* import kotlin.reflect.KMutableProperty1 +const val COMPILER_JAR_NAME: String = "kotlin-compiler.jar" +const val COMPILER_SERVICE_RMI_NAME: String = "KotlinJvmCompilerService" +const val COMPILER_DAEMON_CLASS_FQN: String = "org.jetbrains.kotlin.daemon.KotlinCompileDaemon" +const val COMPILE_DAEMON_FIND_PORT_ATTEMPTS: Int = 10 +const val COMPILE_DAEMON_PORTS_RANGE_START: Int = 17001 +const val COMPILE_DAEMON_PORTS_RANGE_END: Int = 18000 +const val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String = "--daemon-" +const val COMPILE_DAEMON_DEFAULT_FILES_PREFIX: String = "kotlin-daemon" +const val COMPILE_DAEMON_TIMEOUT_INFINITE_S: Int = 0 +const val COMPILE_DAEMON_DEFAULT_IDLE_TIMEOUT_S: Int = 7200 // 2 hours +const val COMPILE_DAEMON_DEFAULT_UNUSED_TIMEOUT_S: Int = 60 +const val COMPILE_DAEMON_DEFAULT_SHUTDOWN_DELAY_MS: Long = 1000L // 1 sec +const val COMPILE_DAEMON_MEMORY_THRESHOLD_INFINITE: Long = 0L +const val COMPILE_DAEMON_FORCE_SHUTDOWN_DEFAULT_TIMEOUT_MS: Long = 10000L // 10 secs +const val COMPILE_DAEMON_TIMEOUT_INFINITE_MS: Long = 0L +const val COMPILE_DAEMON_IS_READY_MESSAGE = "Kotlin compile daemon is ready" -val COMPILER_JAR_NAME: String = "kotlin-compiler.jar" -val COMPILER_SERVICE_RMI_NAME: String = "KotlinJvmCompilerService" -val COMPILER_DAEMON_CLASS_FQN: String = "org.jetbrains.kotlin.daemon.KotlinCompileDaemon" -val COMPILE_DAEMON_FIND_PORT_ATTEMPTS: Int = 10 -val COMPILE_DAEMON_PORTS_RANGE_START: Int = 17001 -val COMPILE_DAEMON_PORTS_RANGE_END: Int = 18000 -val COMPILE_DAEMON_ENABLED_PROPERTY: String = "kotlin.daemon.enabled" -val COMPILE_DAEMON_JVM_OPTIONS_PROPERTY: String = "kotlin.daemon.jvm.options" -val COMPILE_DAEMON_OPTIONS_PROPERTY: String = "kotlin.daemon.options" -val COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY: String = "kotlin.daemon.client.alive.path" -val COMPILE_DAEMON_LOG_PATH_PROPERTY: String = "kotlin.daemon.log.path" -val COMPILE_DAEMON_REPORT_PERF_PROPERTY: String = "kotlin.daemon.perf" -val COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY: String = "kotlin.daemon.verbose" -val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String = "--daemon-" -val COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY: String = "kotlin.daemon.startup.timeout" -val COMPILE_DAEMON_DEFAULT_FILES_PREFIX: String = "kotlin-daemon" -val COMPILE_DAEMON_TIMEOUT_INFINITE_S: Int = 0 -val COMPILE_DAEMON_DEFAULT_IDLE_TIMEOUT_S: Int = 7200 // 2 hours -val COMPILE_DAEMON_DEFAULT_UNUSED_TIMEOUT_S: Int = 60 -val COMPILE_DAEMON_DEFAULT_SHUTDOWN_DELAY_MS: Long = 1000L // 1 sec -val COMPILE_DAEMON_MEMORY_THRESHOLD_INFINITE: Long = 0L -val COMPILE_DAEMON_FORCE_SHUTDOWN_DEFAULT_TIMEOUT_MS: Long = 10000L // 10 secs -val COMPILE_DAEMON_TIMEOUT_INFINITE_MS: Long = 0L -val COMPILE_DAEMON_IS_READY_MESSAGE = "Kotlin compile daemon is ready" - -val COMPILE_DAEMON_CUSTOM_RUN_FILES_PATH_FOR_TESTS: String = "kotlin.daemon.custom.run.files.path.for.tests" -val COMPILE_DAEMON_DEFAULT_RUN_DIR_PATH: String get() = - System.getProperty(COMPILE_DAEMON_CUSTOM_RUN_FILES_PATH_FOR_TESTS) - ?: FileSystem.getRuntimeStateFilesPath("kotlin", "daemon") +val COMPILE_DAEMON_DEFAULT_RUN_DIR_PATH: String + get() = CompilerSystemProperties.COMPILE_DAEMON_CUSTOM_RUN_FILES_PATH_FOR_TESTS.value ?: FileSystem.getRuntimeStateFilesPath( + "kotlin", + "daemon" + ) val CLASSPATH_ID_DIGEST = "MD5" -open class PropMapper>(val dest: C, - val prop: P, - val names: List = listOf(prop.name), - val fromString: (String) -> V, - val toString: ((V) -> String?) = { it.toString() }, - val skipIf: ((V) -> Boolean) = { false }, - val mergeDelimiter: String? = null) { +open class PropMapper>( + val dest: C, + val prop: P, + val names: List = listOf(prop.name), + val fromString: (String) -> V, + val toString: ((V) -> String?) = { it.toString() }, + val skipIf: ((V) -> Boolean) = { false }, + val mergeDelimiter: String? = null +) { open fun toArgs(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = - when { - skipIf(prop.get(dest)) -> listOf() - mergeDelimiter != null -> listOf(listOfNotNull(prefix + names.first(), toString(prop.get(dest))).joinToString(mergeDelimiter)) - else -> listOfNotNull(prefix + names.first(), toString(prop.get(dest))) - } + when { + skipIf(prop.get(dest)) -> listOf() + mergeDelimiter != null -> listOf(listOfNotNull(prefix + names.first(), toString(prop.get(dest))).joinToString(mergeDelimiter)) + else -> listOfNotNull(prefix + names.first(), toString(prop.get(dest))) + } open fun apply(s: String) = prop.set(dest, fromString(s)) } @@ -255,7 +249,7 @@ data class CompilerId( } -fun isDaemonEnabled(): Boolean = System.getProperty(COMPILE_DAEMON_ENABLED_PROPERTY) != null +fun isDaemonEnabled(): Boolean = CompilerSystemProperties.COMPILE_DAEMON_ENABLED_PROPERTY.value != null fun configureDaemonJVMOptions(opts: DaemonJVMOptions, vararg additionalParams: String, @@ -289,16 +283,16 @@ fun configureDaemonJVMOptions(opts: DaemonJVMOptions, if (inheritOtherJvmOptions) { opts.jvmParams.addAll( - otherArgs.filterNot { - it.startsWith("agentlib") || - it.startsWith("D" + COMPILE_DAEMON_LOG_PATH_PROPERTY) || - it.startsWith("D" + KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY) || - it.startsWith("D" + COMPILE_DAEMON_JVM_OPTIONS_PROPERTY) || - it.startsWith("D" + COMPILE_DAEMON_OPTIONS_PROPERTY) - }) + otherArgs.filterNot { + it.startsWith("agentlib") || + it.startsWith("D" + CompilerSystemProperties.COMPILE_DAEMON_LOG_PATH_PROPERTY.property) || + it.startsWith("D" + CompilerSystemProperties.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY.property) || + it.startsWith("D" + CompilerSystemProperties.COMPILE_DAEMON_JVM_OPTIONS_PROPERTY.property) || + it.startsWith("D" + CompilerSystemProperties.COMPILE_DAEMON_OPTIONS_PROPERTY.property) + }) } } - System.getProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY)?.let { + CompilerSystemProperties.COMPILE_DAEMON_JVM_OPTIONS_PROPERTY.value?.let { opts.jvmParams.addAll( it.trimQuotes() .split("(? progress.compilationStarted() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index 11549412937..b6b57061638 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -24,6 +24,7 @@ import org.gradle.api.internal.FeaturePreviews import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry +import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget @@ -76,9 +77,6 @@ abstract class KotlinBasePluginWrapper : Plugin { it.add(project.dependencies.create("$KOTLIN_MODULE_GROUP:$KOTLIN_KLIB_COMMONIZER_EMBEDDABLE:$kotlinPluginVersion")) } - // TODO: consider only set if if daemon or parallel compilation are enabled, though this way it should be safe too - System.setProperty(org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true") - val kotlinGradleBuildServices = KotlinGradleBuildServices.getInstance(project, listenerRegistryHolder) kotlinGradleBuildServices.detectKotlinPluginLoadedInMultipleProjects(project, kotlinPluginVersion) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 4564dede92e..9e8c07a43e7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporterImpl import org.jetbrains.kotlin.build.report.metrics.BuildTime import org.jetbrains.kotlin.build.report.metrics.measure +import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments @@ -334,6 +335,21 @@ abstract class AbstractKotlinCompile() : AbstractKo @TaskAction fun execute(inputs: IncrementalTaskInputs) { + CompilerSystemProperties.systemPropertyGetter = { + val value = if (it in kotlinDaemonProperties) kotlinDaemonProperties[it] else System.getProperty(it) + logger.warn("System property read $it = $value (declared: ${it in kotlinDaemonProperties})") + value + } + CompilerSystemProperties.systemPropertySetter = setter@{ key, value -> + val oldValue = kotlinDaemonProperties[key] + if (oldValue == value) return@setter oldValue + kotlinDaemonProperties[key] = value + System.setProperty(key, value) + logger.warn("System property set $key = $value (was: $oldValue)") + oldValue + } + CompilerSystemProperties.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY.value = "true" + // If task throws exception, but its outputs are changed during execution, // then Gradle forces next build to be non-incremental (see Gradle's DefaultTaskArtifactStateRepository#persistNewOutputs) // To prevent this, we backup outputs before incremental build and restore when exception is thrown @@ -425,6 +441,15 @@ abstract class AbstractKotlinCompile() : AbstractKo val taskBuildDir = taskBuildDirectory return taskBuildDir.walk().any { it != taskBuildDir && it.isFile } } + + @get:Internal + val kotlinDaemonProperties: MutableMap by lazy { + if (isGradleVersionAtLeast(6, 5)) { + CompilerSystemProperties.values() + .associate { it.property to project.providers.systemProperty(it.property).forUseAtConfigurationTime().orNull } + .toMutableMap() + } else mutableMapOf() + } } open class KotlinCompileArgumentsProvider>(taskProvider: T) { @@ -686,17 +711,6 @@ open class Kotlin2JsCompile : AbstractKotlinCompile(), Ko override fun getSourceRoots() = SourceRoots.KotlinOnly.create(getSource(), sourceFilesExtensions) - @get:InputFiles - @get:Optional - @get:PathSensitive(PathSensitivity.RELATIVE) - internal val friendDependencies: List - get() { - val filter = libraryFilter - return friendPaths.files.filter { - it.exists() && filter(it) - }.map { it.absolutePath } - } - @Suppress("unused") @get:InputFiles @get:Optional @@ -760,6 +774,10 @@ open class Kotlin2JsCompile : AbstractKotlinCompile(), Ko null } + val friendDependencies: List = friendPaths.files.filter { + it.exists() && libraryFilter(it) + }.map { it.absolutePath } + args.friendModules = friendDependencies.joinToString(File.pathSeparator) if (args.sourceMapBaseDirs == null && !args.sourceMapPrefix.isNullOrEmpty()) {