Unify the way to set compiler options using System.properties

Now compiler flags with boolean values which are controlled by system
properties could be set in similar way. The following syntax is
appropriate. For setting flag:
'-DflagName,'-DflagName=[y|Y|true|TRUE|yes|YES|on|ON]'
for unsetting flag:
'-DflagName=[n|N|false|FALSE|no|NO|off|OFF]'
This commit is contained in:
Andrey Uskov
2021-05-06 15:59:20 +03:00
committed by nataliya.valtman
parent 04e8140162
commit 28e4e77542
12 changed files with 73 additions and 26 deletions
@@ -57,12 +57,12 @@ object LookupSymbolKeyDescriptor : KeyDescriptor<LookupSymbolKey> {
override fun save(output: DataOutput, value: LookupSymbolKey) { override fun save(output: DataOutput, value: LookupSymbolKey) {
if (storeFullFqName) { if (storeFullFqName) {
output.writeByte(0) output.writeByte(0)
output.writeUTF(value.name)
output.writeUTF(value.scope)
} else {
output.writeByte(1)
output.writeInt(value.nameHash) output.writeInt(value.nameHash)
output.writeInt(value.scopeHash) output.writeInt(value.scopeHash)
} else {
output.writeByte(1)
output.writeUTF(value.name)
output.writeUTF(value.scope)
} }
} }
@@ -20,23 +20,25 @@ package org.jetbrains.kotlin.cli.common
* @param alwaysDirectAccess Gradle has a list of properties that can be read without declaring, see https://github.com/gradle/gradle/blob/f191a61cec61afe308f2b45184cb303d32706a6f/subprojects/configuration-cache/src/main/kotlin/org/gradle/configurationcache/SystemPropertyAccessListener.kt#L32 * @param alwaysDirectAccess Gradle has a list of properties that can be read without declaring, see https://github.com/gradle/gradle/blob/f191a61cec61afe308f2b45184cb303d32706a6f/subprojects/configuration-cache/src/main/kotlin/org/gradle/configurationcache/SystemPropertyAccessListener.kt#L32
*/ */
enum class CompilerSystemProperties(val property: String, val alwaysDirectAccess: Boolean = false) { enum class CompilerSystemProperties(val property: String, val alwaysDirectAccess: Boolean = false) {
// Flags with boolean values
COMPILE_DAEMON_ENABLED_PROPERTY("kotlin.daemon.enabled"), COMPILE_DAEMON_ENABLED_PROPERTY("kotlin.daemon.enabled"),
COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY("kotlin.daemon.verbose"),
COMPILE_DAEMON_REPORT_PERF_PROPERTY("kotlin.daemon.perf"),
KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY("kotlin.environment.keepalive"),
COMPILE_INCREMENTAL_WITH_CLASSPATH_SHAPSHOTS("kotlin.incremental.classpath.snapshot.enabled"),
KOTLIN_COLORS_ENABLED_PROPERTY("kotlin.colors.enabled"),
COMPILE_DAEMON_JVM_OPTIONS_PROPERTY("kotlin.daemon.jvm.options"), COMPILE_DAEMON_JVM_OPTIONS_PROPERTY("kotlin.daemon.jvm.options"),
COMPILE_DAEMON_OPTIONS_PROPERTY("kotlin.daemon.options"), COMPILE_DAEMON_OPTIONS_PROPERTY("kotlin.daemon.options"),
COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY("kotlin.daemon.client.options"), COMPILE_DAEMON_CLIENT_OPTIONS_PROPERTY("kotlin.daemon.client.options"),
COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY("kotlin.daemon.client.alive.path"), COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY("kotlin.daemon.client.alive.path"),
COMPILE_DAEMON_LOG_PATH_PROPERTY("kotlin.daemon.log.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"), COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY("kotlin.daemon.startup.timeout"),
JAVA_RMI_SERVER_HOSTNAME("java.rmi.server.hostname"), JAVA_RMI_SERVER_HOSTNAME("java.rmi.server.hostname"),
DAEMON_RMI_SOCKET_BACKLOG_SIZE_PROPERTY("kotlin.daemon.socket.backlog.size"), 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_ATTEMPTS_PROPERTY("kotlin.daemon.socket.connect.attempts"),
DAEMON_RMI_SOCKET_CONNECT_INTERVAL_PROPERTY("kotlin.daemon.socket.connect.interval"), 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"), COMPILE_DAEMON_CUSTOM_RUN_FILES_PATH_FOR_TESTS("kotlin.daemon.custom.run.files.path.for.tests"),
COMPILE_INCREMENTAL_WITH_CLASSPATH_SHAPSHOTS("kotlin.incremental.classpath.snapshot.enabled"),
KOTLIN_COLORS_ENABLED_PROPERTY("kotlin.colors.enabled"),
KOTLIN_STAT_ENABLED_PROPERTY("kotlin.plugin.stat.enabled"), KOTLIN_STAT_ENABLED_PROPERTY("kotlin.plugin.stat.enabled"),
KOTLIN_STAT_ENDPOINT_PROPERTY("kotlin.plugin.stat.endpoint"), KOTLIN_STAT_ENDPOINT_PROPERTY("kotlin.plugin.stat.endpoint"),
@@ -77,6 +79,8 @@ enum class CompilerSystemProperties(val property: String, val alwaysDirectAccess
var systemPropertyCleaner: ((String) -> String?)? = null var systemPropertyCleaner: ((String) -> String?)? = null
} }
fun toBooleanLenient(defaultValue: Boolean = false): Boolean = this.value?.toBooleanLenient() ?: defaultValue
} }
val isWindows: Boolean val isWindows: Boolean
@@ -36,7 +36,7 @@ public abstract class PlainTextMessageRenderer implements MessageRenderer {
static { static {
boolean colorEnabled = false; boolean colorEnabled = false;
// TODO: investigate why ANSI escape codes on Windows only work in REPL for some reason // TODO: investigate why ANSI escape codes on Windows only work in REPL for some reason
if (!PropertiesKt.isWindows() && "true".equals(CompilerSystemProperties.KOTLIN_COLORS_ENABLED_PROPERTY.getValue())) { if (!PropertiesKt.isWindows() && CompilerSystemProperties.KOTLIN_COLORS_ENABLED_PROPERTY.toBooleanLenient(false)) {
try { try {
// AnsiConsole doesn't check isatty() for stderr (see https://github.com/fusesource/jansi/pull/35). // AnsiConsole doesn't check isatty() for stderr (see https://github.com/fusesource/jansi/pull/35).
colorEnabled = CLibrary.isatty(CLibrary.STDERR_FILENO) != 0; colorEnabled = CLibrary.isatty(CLibrary.STDERR_FILENO) != 0;
@@ -504,7 +504,7 @@ class KotlinCoreEnvironment private constructor(
} }
// Disposing of the environment is unsafe in production then parallel builds are enabled, but turning it off universally // 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 // breaks a lot of tests, therefore it is disabled for production and enabled for tests
if (CompilerSystemProperties.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY.value.toBooleanLenient() != true) { if (!CompilerSystemProperties.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY.toBooleanLenient()) {
// JPS may run many instances of the compiler in parallel (there's an option for compiling independent modules in parallel in IntelliJ) // 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 // All projects share the same ApplicationEnvironment, and when the last project is disposed, the ApplicationEnvironment is disposed as well
Disposer.register(parentDisposable, Disposable { Disposer.register(parentDisposable, Disposable {
@@ -13,6 +13,7 @@ import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.toBooleanLenient
import org.jetbrains.kotlin.daemon.client.CompileServiceSessionAsync import org.jetbrains.kotlin.daemon.client.CompileServiceSessionAsync
import org.jetbrains.kotlin.daemon.client.DaemonReportMessage import org.jetbrains.kotlin.daemon.client.DaemonReportMessage
import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets
@@ -45,7 +46,7 @@ class KotlinCompilerClient : KotlinCompilerDaemonClient {
val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L
val DAEMON_CONNECT_CYCLE_ATTEMPTS = 3 val DAEMON_CONNECT_CYCLE_ATTEMPTS = 3
val verboseReporting = CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.value != null val verboseReporting = CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.toBooleanLenient()
private val log = Logger.getLogger("KotlinCompilerClient") private val log = Logger.getLogger("KotlinCompilerClient")
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.daemon.client
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.toBooleanLenient
import org.jetbrains.kotlin.daemon.common.* import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
@@ -49,7 +50,7 @@ object KotlinCompilerClient {
val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L
val DAEMON_CONNECT_CYCLE_ATTEMPTS = 3 val DAEMON_CONNECT_CYCLE_ATTEMPTS = 3
val verboseReporting = CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.value != null val verboseReporting = CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.toBooleanLenient()
fun getOrCreateClientFlagFile(daemonOptions: DaemonOptions): File = fun getOrCreateClientFlagFile(daemonOptions: DaemonOptions): File =
// for jps property is passed from IDEA to JPS in KotlinBuildProcessParametersProvider // for jps property is passed from IDEA to JPS in KotlinBuildProcessParametersProvider
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.daemon.common package org.jetbrains.kotlin.daemon.common
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.cli.common.toBooleanLenient
import java.io.File import java.io.File
import java.io.Serializable import java.io.Serializable
import java.lang.management.ManagementFactory import java.lang.management.ManagementFactory
@@ -254,7 +255,7 @@ data class CompilerId(
} }
fun isDaemonEnabled(): Boolean = CompilerSystemProperties.COMPILE_DAEMON_ENABLED_PROPERTY.value != null fun isDaemonEnabled(): Boolean = CompilerSystemProperties.COMPILE_DAEMON_ENABLED_PROPERTY.toBooleanLenient()
fun configureDaemonJVMOptions(opts: DaemonJVMOptions, fun configureDaemonJVMOptions(opts: DaemonJVMOptions,
vararg additionalParams: String, vararg additionalParams: String,
@@ -346,8 +347,12 @@ fun configureDaemonOptions(opts: DaemonOptions): DaemonOptions {
"Unrecognized daemon options passed via property ${CompilerSystemProperties.COMPILE_DAEMON_OPTIONS_PROPERTY.property}: " + unrecognized.joinToString(" ") + "Unrecognized daemon options passed via property ${CompilerSystemProperties.COMPILE_DAEMON_OPTIONS_PROPERTY.property}: " + unrecognized.joinToString(" ") +
"\nSupported options: " + opts.mappers.joinToString(", ", transform = { it.names.first() })) "\nSupported options: " + opts.mappers.joinToString(", ", transform = { it.names.first() }))
} }
CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.value?.let { opts.verbose = true } if (CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.toBooleanLenient()) {
CompilerSystemProperties.COMPILE_DAEMON_REPORT_PERF_PROPERTY.value?.let { opts.reportPerf = true } opts.verbose = true
}
if (CompilerSystemProperties.COMPILE_DAEMON_REPORT_PERF_PROPERTY.toBooleanLenient()) {
opts.reportPerf = true
}
return opts return opts
} }
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.toBooleanLenient
import org.jetbrains.kotlin.compilerRunner.MessageCollectorToOutputItemsCollectorAdapter import org.jetbrains.kotlin.compilerRunner.MessageCollectorToOutputItemsCollectorAdapter
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.compilerRunner.SimpleOutputItem import org.jetbrains.kotlin.compilerRunner.SimpleOutputItem
@@ -63,7 +62,7 @@ abstract class IncrementalCompilerRunner<
protected open val kotlinSourceFilesExtensions: List<String> = DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS protected open val kotlinSourceFilesExtensions: List<String> = DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
//TODO(valtman) temporal measure to ensure quick disable, should be deleted after successful release //TODO(valtman) temporal measure to ensure quick disable, should be deleted after successful release
protected val withSnapshot: Boolean = CompilerSystemProperties.COMPILE_INCREMENTAL_WITH_CLASSPATH_SHAPSHOTS.value.toBooleanLenient() ?: false protected val withSnapshot: Boolean = CompilerSystemProperties.COMPILE_INCREMENTAL_WITH_CLASSPATH_SHAPSHOTS.toBooleanLenient()
protected abstract fun isICEnabled(): Boolean protected abstract fun isICEnabled(): Boolean
protected abstract fun createCacheManager(args: Args, projectDir: File?): CacheManager protected abstract fun createCacheManager(args: Args, projectDir: File?): CacheManager
@@ -151,8 +150,8 @@ abstract class IncrementalCompilerRunner<
messageCollector, messageCollector,
withSnapshot, withSnapshot,
abiSnapshot, abiSnapshot,
classpathAbiSnapshot classpathAbiSnapshot)
)
} else { } else {
rebuild(BuildAttribute.NO_ABI_SNAPSHOT) rebuild(BuildAttribute.NO_ABI_SNAPSHOT)
} }
@@ -973,6 +973,7 @@ Finished executing task ':$taskName'|
if (supportFailingBuildOnWarning && notUsingAgpWithWarnings && options.warningMode == WarningMode.Fail) { if (supportFailingBuildOnWarning && notUsingAgpWithWarnings && options.warningMode == WarningMode.Fail) {
add("--warning-mode=${WarningMode.Fail.name.toLowerCase()}") add("--warning-mode=${WarningMode.Fail.name.toLowerCase()}")
} }
addAll(options.freeCommandLineArgs) addAll(options.freeCommandLineArgs)
} }
@@ -176,6 +176,7 @@ abstract class BaseIncrementalCompilationMultiProjectIT : IncrementalCompilation
) )
} }
@Test @Test
fun testMoveFunctionFromLibToApp() { fun testMoveFunctionFromLibToApp() {
doTest( doTest(
@@ -189,6 +190,38 @@ abstract class BaseIncrementalCompilationMultiProjectIT : IncrementalCompilation
) )
} }
//val abiSnapshotFile: File by project.provider {
// File(taskBuildDirectory, IncrementalCompilerRunner.ABI_SNAPSHOT_FILE_NAME)
//}
//
//val abiSnapshotRelativePath: String by project.provider {
// //TODO update to support any jar changes
// "$taskName/${IncrementalCompilerRunner.ABI_SNAPSHOT_FILE_NAME}"
//}
@Test
fun testAddNewMethodToLib() {
doTest(
options = defaultBuildOptions().copy(abiSnapshot = true),
{ project ->
val aKt = project.projectDir.getFileByName("A.kt")
aKt.writeText(
"""
package bar
open class A {
fun a() {}
fun newA() {}
}
"""
)
},
//TODO for abi-snapshot "BB.kt" should not be recompiled
expectedAffectedFileNames = listOf("A.kt", "B.kt", "AA.kt", "BB.kt", "AAA.kt)
)
)
}
@Test @Test
fun testAddNewMethodToLib() { fun testAddNewMethodToLib() {
doTest( doTest(
@@ -255,7 +288,7 @@ open class A {
} }
//don't need to recompile app classes because lib's proto stays the same //don't need to recompile app classes because lib's proto stays the same
project.build("build") { project.build("build", "") {
assertSuccessful() assertSuccessful()
val affectedSources = project.projectDir.allKotlinFiles() val affectedSources = project.projectDir.allKotlinFiles()
val relativePaths = project.relativize(affectedSources) val relativePaths = project.relativize(affectedSources)
@@ -437,12 +470,14 @@ open class A {
fun testMoveFunctionFromLibWithRemappedBuildDirs() { fun testMoveFunctionFromLibWithRemappedBuildDirs() {
val project = defaultProject() val project = defaultProject()
project.setupWorkingDir() project.setupWorkingDir()
project.projectDir.resolve("build.gradle").appendText(""" project.projectDir.resolve("build.gradle").appendText(
"""
allprojects { allprojects {
it.buildDir = new File(rootDir, "../out" + it.path.replace(":", "/") + "/build") it.buildDir = new File(rootDir, "../out" + it.path.replace(":", "/") + "/build")
} }
""".trimIndent()) """.trimIndent()
)
project.build("build") { project.build("build") {
assertSuccessful() assertSuccessful()
} }
@@ -21,6 +21,9 @@ fun File.allJavaFiles(): Iterable<File> =
fun File.allFilesWithExtension(ext: String): Iterable<File> = fun File.allFilesWithExtension(ext: String): Iterable<File> =
walk().filter { it.isFile && it.extension.equals(ext, ignoreCase = true) }.toList() walk().filter { it.isFile && it.extension.equals(ext, ignoreCase = true) }.toList()
fun File.allFilesWithExtensions(vararg exts: String): Iterable<File> =
walk().filter { it.isFile && exts.any { ext -> it.extension.equals(ext, ignoreCase = true) }}.toList()
fun File.modify(transform: (String) -> String) { fun File.modify(transform: (String) -> String) {
writeText(transform(readText())) writeText(transform(readText()))
} }
@@ -320,9 +320,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
// To prevent this, we backup outputs before incremental build and restore when exception is thrown // To prevent this, we backup outputs before incremental build and restore when exception is thrown
val outputsBackup: TaskOutputsBackup? = val outputsBackup: TaskOutputsBackup? =
if (isIncrementalCompilationEnabled() && inputs.isIncremental) if (isIncrementalCompilationEnabled() && inputs.isIncremental)
metrics.measure(BuildTime.BACKUP_OUTPUT) { TaskOutputsBackup(allOutputFiles())
TaskOutputsBackup(allOutputFiles())
}
else null else null
if (!isIncrementalCompilationEnabled()) { if (!isIncrementalCompilationEnabled()) {