From 28e4e77542cac940d448283cb035adbdaad34f1f Mon Sep 17 00:00:00 2001 From: Andrey Uskov Date: Thu, 6 May 2021 15:59:20 +0300 Subject: [PATCH] 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]' --- .../incremental/storage/externalizers.kt | 8 ++-- .../jetbrains/kotlin/cli/common/Properties.kt | 14 ++++--- .../messages/PlainTextMessageRenderer.java | 2 +- .../cli/jvm/compiler/KotlinCoreEnvironment.kt | 2 +- .../experimental/KotlinCompilerClient.kt | 3 +- .../daemon/client/KotlinCompilerClient.kt | 3 +- .../kotlin/daemon/common/DaemonParams.kt | 11 +++-- .../incremental/IncrementalCompilerRunner.kt | 7 ++-- .../jetbrains/kotlin/gradle/BaseGradleIT.kt | 1 + .../IncrementalCompilationMultiProjectIT.kt | 41 +++++++++++++++++-- .../jetbrains/kotlin/gradle/util/fileUtil.kt | 3 ++ .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 4 +- 12 files changed, 73 insertions(+), 26 deletions(-) diff --git a/build-common/src/org/jetbrains/kotlin/incremental/storage/externalizers.kt b/build-common/src/org/jetbrains/kotlin/incremental/storage/externalizers.kt index 378549fce61..2da4007b163 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/storage/externalizers.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/storage/externalizers.kt @@ -57,12 +57,12 @@ object LookupSymbolKeyDescriptor : KeyDescriptor { override fun save(output: DataOutput, value: LookupSymbolKey) { if (storeFullFqName) { output.writeByte(0) - output.writeUTF(value.name) - output.writeUTF(value.scope) - } else { - output.writeByte(1) output.writeInt(value.nameHash) output.writeInt(value.scopeHash) + } else { + output.writeByte(1) + output.writeUTF(value.name) + output.writeUTF(value.scope) } } 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 50a2532bc24..7779b4feec7 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 @@ -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 */ enum class CompilerSystemProperties(val property: String, val alwaysDirectAccess: Boolean = false) { + // Flags with boolean values 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_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"), - 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_ENDPOINT_PROPERTY("kotlin.plugin.stat.endpoint"), @@ -77,6 +79,8 @@ enum class CompilerSystemProperties(val property: String, val alwaysDirectAccess var systemPropertyCleaner: ((String) -> String?)? = null } + + fun toBooleanLenient(defaultValue: Boolean = false): Boolean = this.value?.toBooleanLenient() ?: defaultValue } val isWindows: Boolean 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 183a1ffc3af..d0c3b31ec0c 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 @@ -36,7 +36,7 @@ public abstract class PlainTextMessageRenderer implements MessageRenderer { static { boolean colorEnabled = false; // 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 { // AnsiConsole doesn't check isatty() for stderr (see https://github.com/fusesource/jansi/pull/35). colorEnabled = CLibrary.isatty(CLibrary.STDERR_FILENO) != 0; 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 3b300f41c49..7cd99f39c41 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 @@ -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 // 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) // All projects share the same ApplicationEnvironment, and when the last project is disposed, the ApplicationEnvironment is disposed as well Disposer.register(parentDisposable, Disposable { 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 1aada5c88db..569ae6a3521 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 @@ -13,6 +13,7 @@ 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.cli.common.toBooleanLenient import org.jetbrains.kotlin.daemon.client.CompileServiceSessionAsync import org.jetbrains.kotlin.daemon.client.DaemonReportMessage import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets @@ -45,7 +46,7 @@ class KotlinCompilerClient : KotlinCompilerDaemonClient { val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L 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") 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 4ec95bfacf3..a3b579cb49e 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 @@ -19,6 +19,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.cli.common.toBooleanLenient import org.jetbrains.kotlin.daemon.common.* import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents @@ -49,7 +50,7 @@ object KotlinCompilerClient { val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L 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 = // for jps property is passed from IDEA to JPS in KotlinBuildProcessParametersProvider 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 b5f1881dee6..6eddc8c55dd 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 @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.daemon.common import org.jetbrains.kotlin.cli.common.CompilerSystemProperties +import org.jetbrains.kotlin.cli.common.toBooleanLenient import java.io.File import java.io.Serializable 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, 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(" ") + "\nSupported options: " + opts.mappers.joinToString(", ", transform = { it.names.first() })) } - CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.value?.let { opts.verbose = true } - CompilerSystemProperties.COMPILE_DAEMON_REPORT_PERF_PROPERTY.value?.let { opts.reportPerf = true } + if (CompilerSystemProperties.COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY.toBooleanLenient()) { + opts.verbose = true + } + if (CompilerSystemProperties.COMPILE_DAEMON_REPORT_PERF_PROPERTY.toBooleanLenient()) { + opts.reportPerf = true + } return opts } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt index 3779a91a5e7..14c0af63668 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments 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.OutputItemsCollectorImpl import org.jetbrains.kotlin.compilerRunner.SimpleOutputItem @@ -63,7 +62,7 @@ abstract class IncrementalCompilerRunner< protected open val kotlinSourceFilesExtensions: List = DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS //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 createCacheManager(args: Args, projectDir: File?): CacheManager @@ -151,8 +150,8 @@ abstract class IncrementalCompilerRunner< messageCollector, withSnapshot, abiSnapshot, - classpathAbiSnapshot - ) + classpathAbiSnapshot) + } else { rebuild(BuildAttribute.NO_ABI_SNAPSHOT) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt index cb41d297efa..9fefc99e746 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt @@ -973,6 +973,7 @@ Finished executing task ':$taskName'| if (supportFailingBuildOnWarning && notUsingAgpWithWarnings && options.warningMode == WarningMode.Fail) { add("--warning-mode=${WarningMode.Fail.name.toLowerCase()}") } + addAll(options.freeCommandLineArgs) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt index 65cf347523c..f5d209e6e9c 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt @@ -176,6 +176,7 @@ abstract class BaseIncrementalCompilationMultiProjectIT : IncrementalCompilation ) } + @Test fun testMoveFunctionFromLibToApp() { 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 fun testAddNewMethodToLib() { doTest( @@ -255,7 +288,7 @@ open class A { } //don't need to recompile app classes because lib's proto stays the same - project.build("build") { + project.build("build", "") { assertSuccessful() val affectedSources = project.projectDir.allKotlinFiles() val relativePaths = project.relativize(affectedSources) @@ -437,12 +470,14 @@ open class A { fun testMoveFunctionFromLibWithRemappedBuildDirs() { val project = defaultProject() project.setupWorkingDir() - project.projectDir.resolve("build.gradle").appendText(""" + project.projectDir.resolve("build.gradle").appendText( + """ allprojects { it.buildDir = new File(rootDir, "../out" + it.path.replace(":", "/") + "/build") } - """.trimIndent()) + """.trimIndent() + ) project.build("build") { assertSuccessful() } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/fileUtil.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/fileUtil.kt index 15889932883..094389f297f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/fileUtil.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/fileUtil.kt @@ -21,6 +21,9 @@ fun File.allJavaFiles(): Iterable = fun File.allFilesWithExtension(ext: String): Iterable = walk().filter { it.isFile && it.extension.equals(ext, ignoreCase = true) }.toList() +fun File.allFilesWithExtensions(vararg exts: String): Iterable = + walk().filter { it.isFile && exts.any { ext -> it.extension.equals(ext, ignoreCase = true) }}.toList() + fun File.modify(transform: (String) -> String) { writeText(transform(readText())) } 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 8d8c503c8cc..3c47d88fd86 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 @@ -320,9 +320,7 @@ abstract class AbstractKotlinCompile : AbstractKotl // To prevent this, we backup outputs before incremental build and restore when exception is thrown val outputsBackup: TaskOutputsBackup? = if (isIncrementalCompilationEnabled() && inputs.isIncremental) - metrics.measure(BuildTime.BACKUP_OUTPUT) { - TaskOutputsBackup(allOutputFiles()) - } + TaskOutputsBackup(allOutputFiles()) else null if (!isIncrementalCompilationEnabled()) {