[Gradle] Introduce 'kotlin.internal.compiler.arguments.log.level' property

This property allows changing log level for message printing the final
set of compiler arguments used to run compilation.

Possible levels are 'error', 'warning', 'info', 'debug'. Default level
is 'debug'.

^KT-60733 Fixed
This commit is contained in:
Yahor Berdnikau
2023-11-17 16:30:26 +01:00
committed by Space Team
parent 03ed1d1d31
commit a20f21f76f
17 changed files with 274 additions and 257 deletions
@@ -100,7 +100,7 @@ internal class CompilerOptionsIT : KGPBaseTest() {
""".trimMargin() """.trimMargin()
) )
build("assemble", buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) { build("assemble") {
assertOutputContainsExactlyTimes("-P plugin:blah-blah:", 3) assertOutputContainsExactlyTimes("-P plugin:blah-blah:", 3)
} }
} }
@@ -138,7 +138,7 @@ internal class CompilerOptionsIT : KGPBaseTest() {
"compileKotlinJs", "compileKotlinJs",
// we do not allow modifying free args for K/N at execution time // we do not allow modifying free args for K/N at execution time
) )
build(*compileTasks.toTypedArray(), buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) { build(*compileTasks.toTypedArray()) {
assertOutputContainsExactlyTimes("-P plugin:blah-blah:", 3 * compileTasks.size) // 3 times per task assertOutputContainsExactlyTimes("-P plugin:blah-blah:", 3 * compileTasks.size) // 3 times per task
} }
} }
@@ -151,7 +151,6 @@ internal class CompilerOptionsIT : KGPBaseTest() {
project( project(
projectName = "simpleProject", projectName = "simpleProject",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.appendText( buildGradle.appendText(
""" """
@@ -163,18 +162,8 @@ internal class CompilerOptionsIT : KGPBaseTest() {
) )
build("compileKotlin") { build("compileKotlin") {
val compilerArgs = output
.lineSequence()
.first {
it.contains("Kotlin compiler args:")
}
.substringAfter("Kotlin compiler args:")
val expectedOptIn = "-opt-in kotlin.RequiresOptIn,my.CustomOptIn" val expectedOptIn = "-opt-in kotlin.RequiresOptIn,my.CustomOptIn"
assert(compilerArgs.contains(expectedOptIn)) { assertCompilerArgument(":compileKotlin", expectedOptIn, logLevel = LogLevel.INFO)
printBuildOutput()
"compiler arguments does not contain '$expectedOptIn' - actual value: $compilerArgs"
}
} }
} }
} }
@@ -186,7 +175,6 @@ internal class CompilerOptionsIT : KGPBaseTest() {
project( project(
projectName = "new-mpp-lib-and-app/sample-lib", projectName = "new-mpp-lib-and-app/sample-lib",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -208,10 +196,11 @@ internal class CompilerOptionsIT : KGPBaseTest() {
build("compileKotlinJvm6") { build("compileKotlinJvm6") {
assertTasksExecuted(":compileKotlinJvm6") assertTasksExecuted(":compileKotlinJvm6")
assert(output.contains("-opt-in my.custom.OptInAnnotation,another.custom.UnderOptIn")) { assertCompilerArgument(
printBuildOutput() ":compileKotlinJvm6",
"Output does not contain '-opt-in my.custom.OptInAnnotation,another.custom.UnderOptIn'!" "-opt-in my.custom.OptInAnnotation,another.custom.UnderOptIn",
} logLevel = LogLevel.INFO
)
} }
} }
} }
@@ -309,7 +298,6 @@ internal class CompilerOptionsIT : KGPBaseTest() {
project( project(
projectName = "simpleProject", projectName = "simpleProject",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -322,18 +310,7 @@ internal class CompilerOptionsIT : KGPBaseTest() {
) )
build("compileKotlin") { build("compileKotlin") {
val compilerArgs = output assertCompilerArgument(":compileKotlin", "-progressive", logLevel = LogLevel.INFO)
.lineSequence()
.first {
it.contains("Kotlin compiler args:")
}
.substringAfter("Kotlin compiler args:")
val expectedArg = "-progressive"
assert(compilerArgs.contains(expectedArg)) {
printBuildOutput()
"compiler arguments does not contain '$expectedArg' - actual value: $compilerArgs"
}
} }
} }
} }
@@ -345,21 +322,9 @@ internal class CompilerOptionsIT : KGPBaseTest() {
project( project(
projectName = "simpleProject", projectName = "simpleProject",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
build("compileKotlin") { build("compileKotlin") {
val compilerArgs = output assertNoCompilerArgument(":compileKotlin", "-progressive", logLevel = LogLevel.INFO)
.lineSequence()
.first {
it.contains("Kotlin compiler args:")
}
.substringAfter("Kotlin compiler args:")
val expectedArg = "-progressive"
assert(!compilerArgs.contains(expectedArg)) {
printBuildOutput()
"compiler arguments contains '$expectedArg' - actual value: $compilerArgs"
}
} }
} }
} }
@@ -371,7 +336,6 @@ internal class CompilerOptionsIT : KGPBaseTest() {
project( project(
projectName = "simpleProject", projectName = "simpleProject",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -386,18 +350,7 @@ internal class CompilerOptionsIT : KGPBaseTest() {
) )
build("compileKotlin") { build("compileKotlin") {
val compilerArgs = output assertCompilerArgument(":compileKotlin", "-progressive", logLevel = LogLevel.INFO)
.lineSequence()
.first {
it.contains("Kotlin compiler args:")
}
.substringAfter("Kotlin compiler args:")
val expectedArg = "-progressive"
assert(compilerArgs.contains(expectedArg)) {
printBuildOutput()
"compiler arguments does not contain '$expectedArg' - actual value: $compilerArgs"
}
} }
} }
} }
@@ -22,7 +22,6 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
project( project(
projectName = "simpleProject", projectName = "simpleProject",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -40,18 +39,8 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
build("compileKotlin") { build("compileKotlin") {
assertTasksExecuted(":compileKotlin") assertTasksExecuted(":compileKotlin")
val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") } assertCompilerArguments(":compileKotlin", "-java-parameters", logLevel = LogLevel.INFO)
assertNoCompilerArgument(":compileKotlin", "-verbose", logLevel = LogLevel.INFO)
assert(compilationArgs.contains("-java-parameters")) {
printBuildOutput()
"Compiler arguments does not contain '-progressive': $compilationArgs"
}
// '-verbose' by default will be set to 'true' by debug log level
assert(!compilationArgs.contains("-verbose")) {
printBuildOutput()
"Compiler arguments contains '-verbose': $compilationArgs"
}
} }
} }
} }
@@ -63,7 +52,6 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
project( project(
"simpleProject", "simpleProject",
gradleVersion, gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -85,19 +73,8 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
build("compileKotlin") { build("compileKotlin") {
assertTasksExecuted(":compileKotlin") assertTasksExecuted(":compileKotlin")
assertCompilerArgument(":compileKotlin", "-java-parameters", logLevel = LogLevel.INFO)
val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") } assertNoCompilerArgument(":compileKotlin", "-verbose", logLevel = LogLevel.INFO)
assert(compilationArgs.contains("-java-parameters")) {
printBuildOutput()
"Compiler arguments does not contain '-progressive': $compilationArgs"
}
// '-verbose' by default will be set to 'true' by debug log level
assert(!compilationArgs.contains("-verbose")) {
printBuildOutput()
"Compiler arguments contains '-verbose': $compilationArgs"
}
} }
} }
} }
@@ -109,7 +86,6 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
project( project(
projectName = "simpleProject", projectName = "simpleProject",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -130,32 +106,11 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
build("compileKotlin") { build("compileKotlin") {
assertTasksExecuted(":compileKotlin") assertTasksExecuted(":compileKotlin")
val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") } assertCompilerArguments(
":compileKotlin",
assert(compilationArgs.contains("-language-version 2.0")) { "-language-version 2.0", "-api-version 2.0", "-progressive", "-opt-in my.custom.OptInAnnotation", "-Xdebug",
printBuildOutput() logLevel = LogLevel.INFO
"Compiler arguments does not contain '-language-version 2.0': $compilationArgs" )
}
assert(compilationArgs.contains("-api-version 2.0")) {
printBuildOutput()
"Compiler arguments does not contain '-api-version 2.0': $compilationArgs"
}
assert(compilationArgs.contains("-progressive")) {
printBuildOutput()
"Compiler arguments does not contain '-progressive': $compilationArgs"
}
assert(compilationArgs.contains("-opt-in my.custom.OptInAnnotation")) {
printBuildOutput()
"Compiler arguments does not contain '-opt-in my.custom.OptInAnnotation': $compilationArgs"
}
assert(compilationArgs.contains("-Xdebug")) {
printBuildOutput()
"Compiler arguments does not contain '-Xdebug': $compilationArgs"
}
} }
} }
} }
@@ -167,7 +122,6 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
project( project(
projectName = "simpleProject", projectName = "simpleProject",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -204,10 +158,11 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
"-api-version 1.9", "-api-version 1.9",
"-Xdebug", "-Xdebug",
"-opt-in my.custom.OptInAnnotation,another.CustomOptInAnnotation", "-opt-in my.custom.OptInAnnotation,another.CustomOptInAnnotation",
"-XXLanguage:+UnitConversionsOnArbitraryExpressions" "-XXLanguage:+UnitConversionsOnArbitraryExpressions",
logLevel = LogLevel.INFO
) )
assertNoCompilerArgument(":compileKotlin", "-progressive") assertNoCompilerArgument(":compileKotlin", "-progressive", logLevel = LogLevel.INFO)
} }
} }
} }
@@ -219,7 +174,6 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
project( project(
projectName = "simpleProject", projectName = "simpleProject",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -239,13 +193,7 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
assertOutputDoesNotContain( assertOutputDoesNotContain(
"w: :compileKotlin 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!" "w: :compileKotlin 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!"
) )
assertCompilerArgument(":compileKotlin", "-module-name customModule", logLevel = LogLevel.INFO)
val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") }
assert(compilationArgs.contains("-module-name customModule")) {
printBuildOutput()
"Compiler arguments does not contain '-module-name customModule': $compilationArgs"
}
} }
} }
} }
@@ -262,7 +210,7 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
"AndroidSimpleApp", "AndroidSimpleApp",
gradleVersion, gradleVersion,
buildJdk = jdk.location, buildJdk = jdk.location,
buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion, logLevel = LogLevel.DEBUG) buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -283,18 +231,11 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
assertOutputDoesNotContain( assertOutputDoesNotContain(
"w: :compileKotlin 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!" "w: :compileKotlin 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!"
) )
assertCompilerArguments(
val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") } ":compileDebugKotlin",
"-java-parameters", "-module-name my_app_debug",
assert(compilationArgs.contains("-java-parameters")) { logLevel = LogLevel.INFO
printBuildOutput() )
"Compiler arguments does not contain '-java-parameters': $compilationArgs"
}
assert(compilationArgs.contains("-module-name my_app_debug")) {
printBuildOutput()
"Compiler arguments does not contain '-module-name my_app_debug': $compilationArgs"
}
} }
} }
} }
@@ -312,7 +253,7 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
"AndroidSimpleApp", "AndroidSimpleApp",
gradleVersion, gradleVersion,
buildJdk = jdk.location, buildJdk = jdk.location,
buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion, logLevel = LogLevel.DEBUG) buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -342,7 +283,8 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
assertCompilerArguments( assertCompilerArguments(
":compileDebugKotlin", ":compileDebugKotlin",
"-java-parameters", "-java-parameters",
"-module-name my_app_debug" "-module-name my_app_debug",
logLevel = LogLevel.INFO
) )
} }
} }
@@ -361,7 +303,6 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
gradleVersion, gradleVersion,
buildOptions = defaultBuildOptions.copy( buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion, androidVersion = agpVersion,
logLevel = LogLevel.DEBUG
), ),
buildJdk = jdk.location buildJdk = jdk.location
) { ) {
@@ -394,8 +335,16 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
build(":libAndroid:compileDebugKotlin") { build(":libAndroid:compileDebugKotlin") {
assertTasksExecuted(":libAndroid:compileDebugKotlin") assertTasksExecuted(":libAndroid:compileDebugKotlin")
assertCompilerArgument(":libAndroid:compileDebugKotlin", "-progressive") assertCompilerArgument(
assertCompilerArgument(":libAndroid:compileDebugKotlin", "-opt-in=com.example.roo.requiresOpt.FunTests") ":libAndroid:compileDebugKotlin",
"-progressive",
logLevel = LogLevel.INFO
)
assertCompilerArgument(
":libAndroid:compileDebugKotlin",
"-opt-in=com.example.roo.requiresOpt.FunTests",
logLevel = LogLevel.INFO
)
} }
} }
} }
@@ -407,7 +356,6 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
project( project(
projectName = "simpleProject", projectName = "simpleProject",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.appendText( buildGradle.appendText(
//language=Groovy //language=Groovy
@@ -431,13 +379,7 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
assertOutputContains( assertOutputContains(
"w: :compileKotlin 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!" "w: :compileKotlin 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!"
) )
assertCompilerArgument(":compileKotlin", "-module-name otherCustomModuleName", logLevel = LogLevel.INFO)
val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") }
assert(compilationArgs.contains("-module-name otherCustomModuleName")) {
printBuildOutput()
"Compiler arguments does not contain '-module-name otherCustomModuleName': $compilationArgs"
}
} }
} }
} }
@@ -454,7 +396,7 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
project( project(
"multiplatformAndroidSourceSetLayout2", "multiplatformAndroidSourceSetLayout2",
gradleVersion, gradleVersion,
buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion, logLevel = LogLevel.DEBUG), buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion),
buildJdk = jdk.location buildJdk = jdk.location
) { ) {
buildGradleKts.appendText( buildGradleKts.appendText(
@@ -474,7 +416,11 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
build(":compileGermanFreeDebugKotlinAndroid") { build(":compileGermanFreeDebugKotlinAndroid") {
assertTasksExecuted(":compileGermanFreeDebugKotlinAndroid") assertTasksExecuted(":compileGermanFreeDebugKotlinAndroid")
assertCompilerArgument(":compileGermanFreeDebugKotlinAndroid", "-module-name last-chance") assertCompilerArgument(
":compileGermanFreeDebugKotlinAndroid",
"-module-name last-chance",
logLevel = LogLevel.INFO
)
} }
} }
} }
@@ -487,7 +433,6 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
project( project(
projectName = "mpp-default-hierarchy", projectName = "mpp-default-hierarchy",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) { ) {
buildGradle.modify { buildGradle.modify {
it.substringBefore("kotlin {") + it.substringBefore("kotlin {") +
@@ -530,7 +475,11 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
} }
build(":compileCommonMainKotlinMetadata") { build(":compileCommonMainKotlinMetadata") {
assertCompilerArguments(":compileCommonMainKotlinMetadata", "-language-version 1.7", "-api-version 1.7") assertCompilerArguments(
":compileCommonMainKotlinMetadata",
"-language-version 1.7", "-api-version 1.7",
logLevel = LogLevel.INFO
)
} }
build(":compileKotlinJvm") { build(":compileKotlinJvm") {
@@ -539,12 +488,17 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
"-language-version 1.8", "-language-version 1.8",
"-api-version 1.8", "-api-version 1.8",
"-java-parameters", "-java-parameters",
"-jvm-target 11" "-jvm-target 11",
logLevel = LogLevel.INFO
) )
} }
build(":compileKotlinJs") { build(":compileKotlinJs") {
assertCompilerArguments(":compileKotlinJs", "-language-version 2.0", "-api-version 2.0", "-Xfriend-modules-disabled") assertCompilerArguments(
":compileKotlinJs",
"-language-version 2.0", "-api-version 2.0", "-Xfriend-modules-disabled",
logLevel = LogLevel.INFO
)
} }
build(":compileKotlinLinuxX64") { build(":compileKotlinLinuxX64") {
@@ -570,7 +524,7 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
project( project(
projectName = "multiplatformAndroidSourceSetLayout2", projectName = "multiplatformAndroidSourceSetLayout2",
gradleVersion = gradleVersion, gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG , androidVersion = agpVersion), buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion),
buildJdk = jdk.location buildJdk = jdk.location
) { ) {
buildGradleKts.appendText( buildGradleKts.appendText(
@@ -591,7 +545,8 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
build(":compileGermanFreeDebugKotlinAndroid") { build(":compileGermanFreeDebugKotlinAndroid") {
assertCompilerArguments( assertCompilerArguments(
":compileGermanFreeDebugKotlinAndroid", ":compileGermanFreeDebugKotlinAndroid",
"-module-name my-custom-module_germanFreeDebug" "-module-name my-custom-module_germanFreeDebug",
logLevel = LogLevel.INFO
) )
} }
} }
@@ -15,6 +15,9 @@ import kotlin.io.path.writeText
@MppGradlePluginTests @MppGradlePluginTests
class MppDiagnosticsIt : KGPBaseTest() { class MppDiagnosticsIt : KGPBaseTest() {
override val defaultBuildOptions: BuildOptions
get() = super.defaultBuildOptions.copy(compilerArgumentsLogLevel = null)
@GradleTest @GradleTest
fun testDiagnosticsRenderingSmoke(gradleVersion: GradleVersion) { fun testDiagnosticsRenderingSmoke(gradleVersion: GradleVersion) {
project("diagnosticsRenderingSmoke", gradleVersion) { project("diagnosticsRenderingSmoke", gradleVersion) {
@@ -54,6 +54,7 @@ data class BuildOptions(
val runViaBuildToolsApi: Boolean? = null, val runViaBuildToolsApi: Boolean? = null,
val konanDataDir: Path? = konanDir, // null can be used only if you are using custom 'kotlin.native.home' or 'org.jetbrains.kotlin.native.home' property instead of konanDir val konanDataDir: Path? = konanDir, // null can be used only if you are using custom 'kotlin.native.home' or 'org.jetbrains.kotlin.native.home' property instead of konanDir
val kotlinUserHome: Path? = testKitDir.resolve(".kotlin"), val kotlinUserHome: Path? = testKitDir.resolve(".kotlin"),
val compilerArgumentsLogLevel: String? = "info"
) { ) {
val isK2ByDefault val isK2ByDefault
get() = KotlinVersion.DEFAULT >= KotlinVersion.KOTLIN_2_0 get() = KotlinVersion.DEFAULT >= KotlinVersion.KOTLIN_2_0
@@ -222,6 +223,10 @@ data class BuildOptions(
arguments.add("-Pkotlin.user.home=${kotlinUserHome.absolutePathString()}") arguments.add("-Pkotlin.user.home=${kotlinUserHome.absolutePathString()}")
} }
if (compilerArgumentsLogLevel != null) {
arguments.add("-Pkotlin.internal.compiler.arguments.log.level=$compilerArgumentsLogLevel")
}
arguments.addAll(freeArgs) arguments.addAll(freeArgs)
return arguments.toList() return arguments.toList()
@@ -249,8 +249,9 @@ fun findParameterInOutput(name: String, output: String): String? =
fun BuildResult.assertCompilerArgument( fun BuildResult.assertCompilerArgument(
taskPath: String, taskPath: String,
expectedArgument: String, expectedArgument: String,
logLevel: LogLevel = LogLevel.DEBUG
) { ) {
val taskOutput = getOutputForTask(taskPath) val taskOutput = getOutputForTask(taskPath, logLevel)
val compilerArguments = taskOutput.lines().first { val compilerArguments = taskOutput.lines().first {
it.contains("Kotlin compiler args:") it.contains("Kotlin compiler args:")
}.substringAfter("Kotlin compiler args:") }.substringAfter("Kotlin compiler args:")
@@ -280,8 +281,9 @@ fun BuildResult.assertNativeTasksClasspath(
fun BuildResult.assertCompilerArguments( fun BuildResult.assertCompilerArguments(
taskPath: String, taskPath: String,
vararg expectedArguments: String, vararg expectedArguments: String,
logLevel: LogLevel = LogLevel.DEBUG,
) { ) {
val taskOutput = getOutputForTask(taskPath) val taskOutput = getOutputForTask(taskPath, logLevel)
val compilerArguments = taskOutput.lines().first { val compilerArguments = taskOutput.lines().first {
it.contains("Kotlin compiler args:") it.contains("Kotlin compiler args:")
}.substringAfter("Kotlin compiler args:") }.substringAfter("Kotlin compiler args:")
@@ -301,8 +303,9 @@ fun BuildResult.assertCompilerArguments(
fun BuildResult.assertNoCompilerArgument( fun BuildResult.assertNoCompilerArgument(
taskPath: String, taskPath: String,
notExpectedArgument: String, notExpectedArgument: String,
logLevel: LogLevel = LogLevel.DEBUG,
) { ) {
val taskOutput = getOutputForTask(taskPath) val taskOutput = getOutputForTask(taskPath, logLevel)
val compilerArguments = taskOutput.lines().first { val compilerArguments = taskOutput.lines().first {
it.contains("Kotlin compiler args:") it.contains("Kotlin compiler args:")
}.substringAfter("Kotlin compiler args:") }.substringAfter("Kotlin compiler args:")
@@ -16,12 +16,13 @@ internal class GradleCompilerEnvironment(
outputItemsCollector: OutputItemsCollector, outputItemsCollector: OutputItemsCollector,
val outputFiles: List<File>, val outputFiles: List<File>,
val reportingSettings: ReportingSettings, val reportingSettings: ReportingSettings,
val compilerArgumentsLogLevel: KotlinCompilerArgumentsLogLevel,
val incrementalCompilationEnvironment: IncrementalCompilationEnvironment? = null, val incrementalCompilationEnvironment: IncrementalCompilationEnvironment? = null,
val kotlinScriptExtensions: Array<String> = emptyArray() val kotlinScriptExtensions: Array<String> = emptyArray(),
) : CompilerEnvironment(Services.EMPTY, messageCollector, outputItemsCollector) { ) : CompilerEnvironment(Services.EMPTY, messageCollector, outputItemsCollector) {
fun compilerFullClasspath( fun compilerFullClasspath(
toolsJar: File? toolsJar: File?
): List<File> = if (toolsJar != null ) compilerClasspath + toolsJar else compilerClasspath.toList() ): List<File> = if (toolsJar != null) compilerClasspath + toolsJar else compilerClasspath.toList()
} }
@@ -235,7 +235,8 @@ internal open class GradleCompilerRunner(
errorsFiles = errorsFiles, errorsFiles = errorsFiles,
kotlinPluginVersion = getKotlinPluginVersion(loggerProvider), kotlinPluginVersion = getKotlinPluginVersion(loggerProvider),
//no need to log warnings in MessageCollector hear it will be logged by compiler //no need to log warnings in MessageCollector hear it will be logged by compiler
kotlinLanguageVersion = parseLanguageVersion(compilerArgs.languageVersion, compilerArgs.useK2) kotlinLanguageVersion = parseLanguageVersion(compilerArgs.languageVersion, compilerArgs.useK2),
compilerArgumentsLogLevel = environment.compilerArgumentsLogLevel,
) )
TaskLoggers.put(pathProvider, loggerProvider) TaskLoggers.put(pathProvider, loggerProvider)
return runCompilerAsync( return runCompilerAsync(
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import org.jetbrains.kotlin.gradle.logging.* import org.jetbrains.kotlin.gradle.logging.*
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
import org.jetbrains.kotlin.gradle.plugin.internal.state.getTaskLogger import org.jetbrains.kotlin.gradle.plugin.internal.state.getTaskLogger
import org.jetbrains.kotlin.gradle.report.* import org.jetbrains.kotlin.gradle.report.*
import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.tasks.*
@@ -27,7 +26,6 @@ import org.jetbrains.kotlin.incremental.ClasspathChanges
import org.jetbrains.kotlin.incremental.IncrementalModuleInfo import org.jetbrains.kotlin.incremental.IncrementalModuleInfo
import org.jetbrains.kotlin.util.removeSuffixIfPresent import org.jetbrains.kotlin.util.removeSuffixIfPresent
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
import org.slf4j.LoggerFactory
import java.io.* import java.io.*
import java.net.URLClassLoader import java.net.URLClassLoader
import java.rmi.RemoteException import java.rmi.RemoteException
@@ -77,97 +75,86 @@ internal class GradleKotlinCompilerWorkArguments(
val errorsFiles: Set<File>?, val errorsFiles: Set<File>?,
val kotlinPluginVersion: String, val kotlinPluginVersion: String,
val kotlinLanguageVersion: KotlinVersion, val kotlinLanguageVersion: KotlinVersion,
val compilerArgumentsLogLevel: KotlinCompilerArgumentsLogLevel,
) : Serializable { ) : Serializable {
companion object { companion object {
const val serialVersionUID: Long = 1 const val serialVersionUID: Long = 2L
} }
} }
internal class GradleKotlinCompilerWork @Inject constructor( internal class GradleKotlinCompilerWork @Inject constructor(
/** private val config: GradleKotlinCompilerWorkArguments
* Arguments are passed through [GradleKotlinCompilerWorkArguments],
* because Gradle Workers API does not support nullable arguments (https://github.com/gradle/gradle/issues/2405),
* and because Workers API does not support named arguments,
* which are useful when there are many arguments with the same type
* (to protect against parameters reordering bugs)
*/
config: GradleKotlinCompilerWorkArguments
) : Runnable { ) : Runnable {
private val projectRootFile = config.projectFiles.projectRootFile private val metrics = if (config.reportingSettings.buildReportOutputs.isNotEmpty()) {
private val clientIsAliveFlagFile = config.projectFiles.clientIsAliveFlagFile BuildMetricsReporterImpl()
private val sessionFlagFile = config.projectFiles.sessionFlagFile } else {
private val compilerFullClasspath = config.compilerFullClasspath DoNothingBuildMetricsReporter
private val compilerClassName = config.compilerClassName }
private val compilerArgs = config.compilerArgs
private val isVerbose = config.isVerbose
private val incrementalCompilationEnvironment = config.incrementalCompilationEnvironment
private val incrementalModuleInfo = config.incrementalModuleInfo
private val outputFiles = config.outputFiles
private val taskPath = config.taskPath
private val reportingSettings = config.reportingSettings
private val kotlinScriptExtensions = config.kotlinScriptExtensions
private val allWarningsAsErrors = config.allWarningsAsErrors
private val buildDir = config.projectFiles.buildDir
private val metrics = if (reportingSettings.buildReportOutputs.isNotEmpty()) BuildMetricsReporterImpl() else DoNothingBuildMetricsReporter
private var icLogLines: List<String> = emptyList() private var icLogLines: List<String> = emptyList()
private val compilerExecutionSettings = config.compilerExecutionSettings
private val errorsFiles = config.errorsFiles
private val kotlinPluginVersion = config.kotlinPluginVersion
private val kotlinLanguageVersion = config.kotlinLanguageVersion
private val log: KotlinLogger = getTaskLogger(taskPath, null, "GradleKotlinCompilerWork") private val log: KotlinLogger = getTaskLogger(config.taskPath, null, "GradleKotlinCompilerWork")
private val isIncremental: Boolean private val isIncremental: Boolean
get() = incrementalCompilationEnvironment != null get() = config.incrementalCompilationEnvironment != null
override fun run() { override fun run() {
metrics.addTimeMetric(GradleBuildPerformanceMetric.START_WORKER_EXECUTION) metrics.addTimeMetric(GradleBuildPerformanceMetric.START_WORKER_EXECUTION)
metrics.startMeasure(GradleBuildTime.RUN_COMPILATION_IN_WORKER) metrics.startMeasure(GradleBuildTime.RUN_COMPILATION_IN_WORKER)
try { try {
val gradlePrintingMessageCollector = GradlePrintingMessageCollector(log, allWarningsAsErrors) val gradlePrintingMessageCollector = GradlePrintingMessageCollector(log, config.allWarningsAsErrors)
val gradleMessageCollector = GradleErrorMessageCollector(log, gradlePrintingMessageCollector, kotlinPluginVersion = kotlinPluginVersion) val gradleMessageCollector = GradleErrorMessageCollector(
val (exitCode, executionStrategy) = compileWithDaemonOrFallbackImpl(gradleMessageCollector) log,
if (incrementalCompilationEnvironment?.disableMultiModuleIC == true) { gradlePrintingMessageCollector,
incrementalCompilationEnvironment.multiModuleICSettings.buildHistoryFile.delete() kotlinPluginVersion = config.kotlinPluginVersion
)
val (exitCode, executionStrategy) = compileWithDaemonOrFallbackImpl(gradleMessageCollector, config.compilerArgumentsLogLevel)
if (config.incrementalCompilationEnvironment?.disableMultiModuleIC == true) {
config.incrementalCompilationEnvironment.multiModuleICSettings.buildHistoryFile.delete()
} }
errorsFiles?.let { config.errorsFiles?.let {
gradleMessageCollector.flush(it) gradleMessageCollector.flush(it)
} }
throwExceptionIfCompilationFailed(exitCode, executionStrategy) throwExceptionIfCompilationFailed(exitCode, executionStrategy)
} finally { } finally {
val taskInfo = TaskExecutionInfo( val taskInfo = TaskExecutionInfo(
kotlinLanguageVersion = kotlinLanguageVersion, kotlinLanguageVersion = config.kotlinLanguageVersion,
changedFiles = incrementalCompilationEnvironment?.changedFiles, changedFiles = config.incrementalCompilationEnvironment?.changedFiles,
compilerArguments = if (reportingSettings.includeCompilerArguments) compilerArgs else emptyArray(), compilerArguments = if (config.reportingSettings.includeCompilerArguments) config.compilerArgs else emptyArray(),
tags = collectStatTags(), tags = collectStatTags(),
) )
metrics.endMeasure(GradleBuildTime.RUN_COMPILATION_IN_WORKER) metrics.endMeasure(GradleBuildTime.RUN_COMPILATION_IN_WORKER)
val result = TaskExecutionResult(buildMetrics = metrics.getMetrics(), icLogLines = icLogLines, taskInfo = taskInfo) val result = TaskExecutionResult(buildMetrics = metrics.getMetrics(), icLogLines = icLogLines, taskInfo = taskInfo)
TaskExecutionResults[taskPath] = result TaskExecutionResults[config.taskPath] = result
} }
} }
private fun collectStatTags(): Set<StatTag> { private fun collectStatTags(): Set<StatTag> {
val statTags = HashSet<StatTag>() val statTags = HashSet<StatTag>()
incrementalCompilationEnvironment?.withAbiSnapshot?.ifTrue { statTags.add(StatTag.ABI_SNAPSHOT) } config.incrementalCompilationEnvironment?.withAbiSnapshot?.ifTrue { statTags.add(StatTag.ABI_SNAPSHOT) }
if (incrementalCompilationEnvironment?.classpathChanges is ClasspathChanges.ClasspathSnapshotEnabled) { if (config.incrementalCompilationEnvironment?.classpathChanges is ClasspathChanges.ClasspathSnapshotEnabled) {
statTags.add(StatTag.ARTIFACT_TRANSFORM) statTags.add(StatTag.ARTIFACT_TRANSFORM)
} }
return statTags return statTags
} }
private fun compileWithDaemonOrFallbackImpl(messageCollector: MessageCollector): Pair<ExitCode, KotlinCompilerExecutionStrategy> { private fun compileWithDaemonOrFallbackImpl(
messageCollector: MessageCollector,
compilerArgsLogLevel: KotlinCompilerArgumentsLogLevel,
): Pair<ExitCode, KotlinCompilerExecutionStrategy> {
with(log) { with(log) {
kotlinDebug { "Kotlin compiler class: $compilerClassName" } kotlinDebug { "Kotlin compiler class: ${config.compilerClassName}" }
kotlinDebug { kotlinDebug {
"Kotlin compiler classpath: ${compilerFullClasspath.joinToString(File.pathSeparator) { it.normalize().absolutePath }}" val compilerClasspath = config.compilerFullClasspath.joinToString(File.pathSeparator) { it.normalize().absolutePath }
"Kotlin compiler classpath: $compilerClasspath"
}
logCompilerArgumentsMessage(compilerArgsLogLevel) {
"${config.taskPath} Kotlin compiler args: ${config.compilerArgs.joinToString(" ")}"
} }
kotlinDebug { "$taskPath Kotlin compiler args: ${compilerArgs.joinToString(" ")}" }
} }
if (compilerExecutionSettings.strategy == KotlinCompilerExecutionStrategy.DAEMON) { if (config.compilerExecutionSettings.strategy == KotlinCompilerExecutionStrategy.DAEMON) {
try { try {
return compileWithDaemon(messageCollector) to KotlinCompilerExecutionStrategy.DAEMON return compileWithDaemon(messageCollector) to KotlinCompilerExecutionStrategy.DAEMON
} catch (e: Throwable) { } catch (e: Throwable) {
@@ -175,7 +162,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
severity = CompilerMessageSeverity.EXCEPTION, severity = CompilerMessageSeverity.EXCEPTION,
message = "Daemon compilation failed: ${e.message}\n${e.stackTraceToString()}" message = "Daemon compilation failed: ${e.message}\n${e.stackTraceToString()}"
) )
if (!compilerExecutionSettings.useDaemonFallbackStrategy) { if (!config.compilerExecutionSettings.useDaemonFallbackStrategy) {
throw RuntimeException( throw RuntimeException(
"Failed to compile with Kotlin daemon. Fallback strategy (compiling without Kotlin daemon) is turned off. " + "Failed to compile with Kotlin daemon. Fallback strategy (compiling without Kotlin daemon) is turned off. " +
"Try ./gradlew --stop if this issue persists.", "Try ./gradlew --stop if this issue persists.",
@@ -194,7 +181,9 @@ internal class GradleKotlinCompilerWork @Inject constructor(
} }
val isGradleDaemonUsed = System.getProperty("org.gradle.daemon")?.let(String::toBoolean) val isGradleDaemonUsed = System.getProperty("org.gradle.daemon")?.let(String::toBoolean)
return if (compilerExecutionSettings.strategy == KotlinCompilerExecutionStrategy.IN_PROCESS || isGradleDaemonUsed == false) { return if (config.compilerExecutionSettings.strategy == KotlinCompilerExecutionStrategy.IN_PROCESS ||
isGradleDaemonUsed == false
) {
compileInProcess(messageCollector) to KotlinCompilerExecutionStrategy.IN_PROCESS compileInProcess(messageCollector) to KotlinCompilerExecutionStrategy.IN_PROCESS
} else { } else {
compileOutOfProcess() to KotlinCompilerExecutionStrategy.OUT_OF_PROCESS compileOutOfProcess() to KotlinCompilerExecutionStrategy.OUT_OF_PROCESS
@@ -208,12 +197,12 @@ internal class GradleKotlinCompilerWork @Inject constructor(
val connection = val connection =
metrics.measure(GradleBuildTime.CONNECT_TO_DAEMON) { metrics.measure(GradleBuildTime.CONNECT_TO_DAEMON) {
GradleCompilerRunner.getDaemonConnectionImpl( GradleCompilerRunner.getDaemonConnectionImpl(
clientIsAliveFlagFile, config.projectFiles.clientIsAliveFlagFile,
sessionFlagFile, config.projectFiles.sessionFlagFile,
compilerFullClasspath, config.compilerFullClasspath,
daemonMessageCollector, daemonMessageCollector,
isDebugEnabled = isDebugEnabled, isDebugEnabled = isDebugEnabled,
daemonJvmArgs = compilerExecutionSettings.daemonJvmArgs daemonJvmArgs = config.compilerExecutionSettings.daemonJvmArgs
) )
} ?: throw RuntimeException(COULD_NOT_CONNECT_TO_DAEMON_MESSAGE) // TODO: Add root cause } ?: throw RuntimeException(COULD_NOT_CONNECT_TO_DAEMON_MESSAGE) // TODO: Add root cause
@@ -227,11 +216,11 @@ internal class GradleKotlinCompilerWork @Inject constructor(
val memoryUsageBeforeBuild = daemon.getUsedMemory(withGC = false).takeIf { it.isGood }?.get() val memoryUsageBeforeBuild = daemon.getUsedMemory(withGC = false).takeIf { it.isGood }?.get()
val targetPlatform = when (compilerClassName) { val targetPlatform = when (config.compilerClassName) {
KotlinCompilerClass.JVM -> CompileService.TargetPlatform.JVM KotlinCompilerClass.JVM -> CompileService.TargetPlatform.JVM
KotlinCompilerClass.JS -> CompileService.TargetPlatform.JS KotlinCompilerClass.JS -> CompileService.TargetPlatform.JS
KotlinCompilerClass.METADATA -> CompileService.TargetPlatform.METADATA KotlinCompilerClass.METADATA -> CompileService.TargetPlatform.METADATA
else -> throw IllegalArgumentException("Unknown compiler type $compilerClassName") else -> throw IllegalArgumentException("Unknown compiler type ${config.compilerClassName}")
} }
val bufferingMessageCollector = GradleBufferingMessageCollector() val bufferingMessageCollector = GradleBufferingMessageCollector()
val exitCode = try { val exitCode = try {
@@ -281,15 +270,15 @@ internal class GradleKotlinCompilerWork @Inject constructor(
val compilationOptions = CompilationOptions( val compilationOptions = CompilationOptions(
compilerMode = CompilerMode.NON_INCREMENTAL_COMPILER, compilerMode = CompilerMode.NON_INCREMENTAL_COMPILER,
targetPlatform = targetPlatform, targetPlatform = targetPlatform,
reportCategories = reportCategories(isVerbose), reportCategories = reportCategories(config.isVerbose),
reportSeverity = reportSeverity(isVerbose), reportSeverity = reportSeverity(config.isVerbose),
requestedCompilationResults = emptyArray(), requestedCompilationResults = emptyArray(),
kotlinScriptExtensions = kotlinScriptExtensions kotlinScriptExtensions = config.kotlinScriptExtensions
) )
val servicesFacade = GradleCompilerServicesFacadeImpl(log, bufferingMessageCollector) val servicesFacade = GradleCompilerServicesFacadeImpl(log, bufferingMessageCollector)
val compilationResults = GradleCompilationResults(log, projectRootFile) val compilationResults = GradleCompilationResults(log, config.projectFiles.projectRootFile)
return metrics.measure(GradleBuildTime.NON_INCREMENTAL_COMPILATION_DAEMON) { return metrics.measure(GradleBuildTime.NON_INCREMENTAL_COMPILATION_DAEMON) {
daemon.compile(sessionId, compilerArgs, compilationOptions, servicesFacade, compilationResults) daemon.compile(sessionId, config.compilerArgs, compilationOptions, servicesFacade, compilationResults)
}.also { }.also {
metrics.addMetrics(compilationResults.buildMetrics) metrics.addMetrics(compilationResults.buildMetrics)
icLogLines = compilationResults.icLogLines icLogLines = compilationResults.icLogLines
@@ -302,7 +291,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
targetPlatform: CompileService.TargetPlatform, targetPlatform: CompileService.TargetPlatform,
bufferingMessageCollector: GradleBufferingMessageCollector bufferingMessageCollector: GradleBufferingMessageCollector
): CompileService.CallResult<Int> { ): CompileService.CallResult<Int> {
val icEnv = incrementalCompilationEnvironment ?: error("incrementalCompilationEnvironment is null!") val icEnv = config.incrementalCompilationEnvironment ?: error("incrementalCompilationEnvironment is null!")
val knownChangedFiles = icEnv.changedFiles as? SourcesChanges.Known val knownChangedFiles = icEnv.changedFiles as? SourcesChanges.Known
val requestedCompilationResults = requestedCompilationResults() val requestedCompilationResults = requestedCompilationResults()
val compilationOptions = IncrementalCompilationOptions( val compilationOptions = IncrementalCompilationOptions(
@@ -311,18 +300,18 @@ internal class GradleKotlinCompilerWork @Inject constructor(
deletedFiles = knownChangedFiles?.removedFiles, deletedFiles = knownChangedFiles?.removedFiles,
classpathChanges = icEnv.classpathChanges, classpathChanges = icEnv.classpathChanges,
workingDir = icEnv.workingDir, workingDir = icEnv.workingDir,
reportCategories = reportCategories(isVerbose), reportCategories = reportCategories(config.isVerbose),
reportSeverity = reportSeverity(isVerbose), reportSeverity = reportSeverity(config.isVerbose),
requestedCompilationResults = requestedCompilationResults.map { it.code }.toTypedArray(), requestedCompilationResults = requestedCompilationResults.map { it.code }.toTypedArray(),
compilerMode = CompilerMode.INCREMENTAL_COMPILER, compilerMode = CompilerMode.INCREMENTAL_COMPILER,
targetPlatform = targetPlatform, targetPlatform = targetPlatform,
usePreciseJavaTracking = icEnv.usePreciseJavaTracking, usePreciseJavaTracking = icEnv.usePreciseJavaTracking,
outputFiles = outputFiles, outputFiles = config.outputFiles,
multiModuleICSettings = icEnv.multiModuleICSettings, multiModuleICSettings = icEnv.multiModuleICSettings,
modulesInfo = incrementalModuleInfo, modulesInfo = config.incrementalModuleInfo,
rootProjectDir = icEnv.rootProjectDir, rootProjectDir = icEnv.rootProjectDir,
buildDir = icEnv.buildDir, buildDir = icEnv.buildDir,
kotlinScriptExtensions = kotlinScriptExtensions, kotlinScriptExtensions = config.kotlinScriptExtensions,
withAbiSnapshot = icEnv.withAbiSnapshot, withAbiSnapshot = icEnv.withAbiSnapshot,
preciseCompilationResultsBackup = icEnv.preciseCompilationResultsBackup, preciseCompilationResultsBackup = icEnv.preciseCompilationResultsBackup,
keepIncrementalCompilationCachesInMemory = icEnv.keepIncrementalCompilationCachesInMemory keepIncrementalCompilationCachesInMemory = icEnv.keepIncrementalCompilationCachesInMemory
@@ -330,10 +319,10 @@ internal class GradleKotlinCompilerWork @Inject constructor(
log.info("Options for KOTLIN DAEMON: $compilationOptions") log.info("Options for KOTLIN DAEMON: $compilationOptions")
val servicesFacade = GradleIncrementalCompilerServicesFacadeImpl(log, bufferingMessageCollector) val servicesFacade = GradleIncrementalCompilerServicesFacadeImpl(log, bufferingMessageCollector)
val compilationResults = GradleCompilationResults(log, projectRootFile) val compilationResults = GradleCompilationResults(log, config.projectFiles.projectRootFile)
metrics.addTimeMetric(GradleBuildPerformanceMetric.CALL_KOTLIN_DAEMON) metrics.addTimeMetric(GradleBuildPerformanceMetric.CALL_KOTLIN_DAEMON)
return metrics.measure(GradleBuildTime.RUN_COMPILATION) { return metrics.measure(GradleBuildTime.RUN_COMPILATION) {
daemon.compile(sessionId, compilerArgs, compilationOptions, servicesFacade, compilationResults) daemon.compile(sessionId, config.compilerArgs, compilationOptions, servicesFacade, compilationResults)
}.also { }.also {
metrics.addMetrics(compilationResults.buildMetrics) metrics.addMetrics(compilationResults.buildMetrics)
icLogLines = compilationResults.icLogLines icLogLines = compilationResults.icLogLines
@@ -342,16 +331,22 @@ internal class GradleKotlinCompilerWork @Inject constructor(
private fun compileOutOfProcess(): ExitCode { private fun compileOutOfProcess(): ExitCode {
metrics.addAttribute(BuildAttribute.OUT_OF_PROCESS_EXECUTION) metrics.addAttribute(BuildAttribute.OUT_OF_PROCESS_EXECUTION)
cleanOutputsAndLocalState(outputFiles, log, metrics, reason = "out-of-process execution strategy is non-incremental") cleanOutputsAndLocalState(config.outputFiles, log, metrics, reason = "out-of-process execution strategy is non-incremental")
return metrics.measure(GradleBuildTime.NON_INCREMENTAL_COMPILATION_OUT_OF_PROCESS) { return metrics.measure(GradleBuildTime.NON_INCREMENTAL_COMPILATION_OUT_OF_PROCESS) {
runToolInSeparateProcess(compilerArgs, compilerClassName, compilerFullClasspath, log, buildDir) runToolInSeparateProcess(
config.compilerArgs,
config.compilerClassName,
config.compilerFullClasspath,
log,
config.projectFiles.buildDir,
)
} }
} }
private fun compileInProcess(messageCollector: MessageCollector): ExitCode { private fun compileInProcess(messageCollector: MessageCollector): ExitCode {
metrics.addAttribute(BuildAttribute.IN_PROCESS_EXECUTION) metrics.addAttribute(BuildAttribute.IN_PROCESS_EXECUTION)
cleanOutputsAndLocalState(outputFiles, log, metrics, reason = "in-process execution strategy is non-incremental") cleanOutputsAndLocalState(config.outputFiles, log, metrics, reason = "in-process execution strategy is non-incremental")
metrics.startMeasure(GradleBuildTime.NON_INCREMENTAL_COMPILATION_IN_PROCESS) metrics.startMeasure(GradleBuildTime.NON_INCREMENTAL_COMPILATION_IN_PROCESS)
// in-process compiler should always be run in a different thread // in-process compiler should always be run in a different thread
@@ -375,10 +370,10 @@ internal class GradleKotlinCompilerWork @Inject constructor(
val stream = ByteArrayOutputStream() val stream = ByteArrayOutputStream()
val out = PrintStream(stream) val out = PrintStream(stream)
// todo: cache classloader? // todo: cache classloader?
val classLoader = URLClassLoader(compilerFullClasspath.map { it.toURI().toURL() }.toTypedArray()) val classLoader = URLClassLoader(config.compilerFullClasspath.map { it.toURI().toURL() }.toTypedArray())
val servicesClass = Class.forName(Services::class.java.canonicalName, true, classLoader) val servicesClass = Class.forName(Services::class.java.canonicalName, true, classLoader)
val emptyServices = servicesClass.getField("EMPTY").get(servicesClass) val emptyServices = servicesClass.getField("EMPTY").get(servicesClass)
val compiler = Class.forName(compilerClassName, true, classLoader) val compiler = Class.forName(config.compilerClassName, true, classLoader)
val exec = compiler.getMethod( val exec = compiler.getMethod(
"execAndOutputXml", "execAndOutputXml",
@@ -387,7 +382,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
Array<String>::class.java Array<String>::class.java
) )
val res = exec.invoke(compiler.newInstance(), out, emptyServices, compilerArgs) val res = exec.invoke(compiler.declaredConstructors.single().newInstance(), out, emptyServices, config.compilerArgs)
val exitCode = ExitCode.valueOf(res.toString()) val exitCode = ExitCode.valueOf(res.toString())
processCompilerOutput( processCompilerOutput(
messageCollector, messageCollector,
@@ -410,12 +405,12 @@ internal class GradleKotlinCompilerWork @Inject constructor(
private fun requestedCompilationResults(): EnumSet<CompilationResultCategory> { private fun requestedCompilationResults(): EnumSet<CompilationResultCategory> {
val requestedCompilationResults = EnumSet.of(CompilationResultCategory.IC_COMPILE_ITERATION) val requestedCompilationResults = EnumSet.of(CompilationResultCategory.IC_COMPILE_ITERATION)
when (reportingSettings.buildReportMode) { when (config.reportingSettings.buildReportMode) {
BuildReportMode.NONE -> null BuildReportMode.NONE -> null
BuildReportMode.SIMPLE -> CompilationResultCategory.BUILD_REPORT_LINES BuildReportMode.SIMPLE -> CompilationResultCategory.BUILD_REPORT_LINES
BuildReportMode.VERBOSE -> CompilationResultCategory.VERBOSE_BUILD_REPORT_LINES BuildReportMode.VERBOSE -> CompilationResultCategory.VERBOSE_BUILD_REPORT_LINES
}?.let { requestedCompilationResults.add(it) } }?.let { requestedCompilationResults.add(it) }
if (reportingSettings.buildReportOutputs.isNotEmpty()) { if (config.reportingSettings.buildReportOutputs.isNotEmpty()) {
requestedCompilationResults.add(CompilationResultCategory.BUILD_METRICS) requestedCompilationResults.add(CompilationResultCategory.BUILD_METRICS)
} }
return requestedCompilationResults return requestedCompilationResults
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2023 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.compilerRunner
/**
* Controls the log level to print used Kotlin compilation compiler arguments to output.
*/
internal enum class KotlinCompilerArgumentsLogLevel(val value: String) {
ERROR("error"),
WARNING("warning"),
INFO("info"),
DEBUG("debug");
companion object {
fun fromPropertyValue(value: String): KotlinCompilerArgumentsLogLevel =
values().single { it.value == value }
val DEFAULT = DEBUG
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.logging
import org.gradle.api.logging.Logger import org.gradle.api.logging.Logger
import org.jetbrains.kotlin.buildtools.api.KotlinLogger import org.jetbrains.kotlin.buildtools.api.KotlinLogger
import org.jetbrains.kotlin.compilerRunner.KotlinCompilerArgumentsLogLevel
internal fun Logger.kotlinInfo(message: String) { internal fun Logger.kotlinInfo(message: String) {
this.info("[KOTLIN] $message") this.info("[KOTLIN] $message")
@@ -44,15 +45,14 @@ internal inline fun KotlinLogger.kotlinDebug(message: () -> String) {
} }
} }
internal inline fun <T> KotlinLogger.logTime(action: String, fn: () -> T): T { internal fun KotlinLogger.logCompilerArgumentsMessage(
val startNs = System.nanoTime() logLevel: KotlinCompilerArgumentsLogLevel,
val result = fn() message: () -> String
val endNs = System.nanoTime() ) {
when (logLevel) {
val timeNs = endNs - startNs KotlinCompilerArgumentsLogLevel.ERROR -> kotlinError(message)
val timeMs = timeNs.toDouble() / 1_000_000 KotlinCompilerArgumentsLogLevel.WARNING -> kotlinWarn(message)
KotlinCompilerArgumentsLogLevel.INFO -> kotlinInfo(message)
debug(String.format("%s took %.2f ms", action, timeMs)) KotlinCompilerArgumentsLogLevel.DEBUG -> kotlinDebug(message)
}
return result
} }
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.provider.Provider import org.gradle.api.provider.Provider
import org.gradle.util.GradleVersion import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.compilerRunner.KotlinCompilerArgumentsLogLevel
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
import org.jetbrains.kotlin.gradle.dsl.NativeCacheOrchestration import org.jetbrains.kotlin.gradle.dsl.NativeCacheOrchestration
import org.jetbrains.kotlin.gradle.dsl.jvm.JvmTargetValidationMode import org.jetbrains.kotlin.gradle.dsl.jvm.JvmTargetValidationMode
@@ -530,6 +531,8 @@ internal class PropertiesProvider private constructor(private val project: Proje
internal fun get(propertyName: String): String? = propertiesBuildService.get(propertyName, project) internal fun get(propertyName: String): String? = propertiesBuildService.get(propertyName, project)
internal fun getProvider(propertyName: String): Provider<String> = propertiesBuildService.property(propertyName, project)
/** /**
* The directory where Kotlin global caches, logs, or project persistent data are stored. * The directory where Kotlin global caches, logs, or project persistent data are stored.
* *
@@ -552,6 +555,11 @@ internal class PropertiesProvider private constructor(private val project: Proje
val kotlinProjectPersistentDirGradleDisableWrite: Boolean val kotlinProjectPersistentDirGradleDisableWrite: Boolean
get() = booleanProperty(PropertyNames.KOTLIN_PROJECT_PERSISTENT_DIR_GRADLE_DISABLE_WRITE) ?: false get() = booleanProperty(PropertyNames.KOTLIN_PROJECT_PERSISTENT_DIR_GRADLE_DISABLE_WRITE) ?: false
val kotlinCompilerArgumentsLogLevel: Provider<KotlinCompilerArgumentsLogLevel>
get() = getProvider(PropertyNames.KOTLIN_COMPILER_ARGUMENTS_LOG_LEVEL)
.map { KotlinCompilerArgumentsLogLevel.fromPropertyValue(it) }
.orElse(KotlinCompilerArgumentsLogLevel.DEFAULT)
/** /**
* Retrieves a comma-separated list of browsers to use when running karma tests for [target] * Retrieves a comma-separated list of browsers to use when running karma tests for [target]
* @see KOTLIN_JS_KARMA_BROWSERS * @see KOTLIN_JS_KARMA_BROWSERS
@@ -660,6 +668,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
val MPP_13X_FLAGS_SET_BY_PLUGIN = property("$KOTLIN_INTERNAL_NAMESPACE.mpp.13X.flags.setByPlugin") val MPP_13X_FLAGS_SET_BY_PLUGIN = property("$KOTLIN_INTERNAL_NAMESPACE.mpp.13X.flags.setByPlugin")
val KOTLIN_CREATE_ARCHIVE_TASKS_FOR_CUSTOM_COMPILATIONS = val KOTLIN_CREATE_ARCHIVE_TASKS_FOR_CUSTOM_COMPILATIONS =
property("$KOTLIN_INTERNAL_NAMESPACE.mpp.createArchiveTasksForCustomCompilations") property("$KOTLIN_INTERNAL_NAMESPACE.mpp.createArchiveTasksForCustomCompilations")
val KOTLIN_COMPILER_ARGUMENTS_LOG_LEVEL = property("$KOTLIN_INTERNAL_NAMESPACE.compiler.arguments.log.level")
} }
companion object { companion object {
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.build.report.metrics.*
import org.jetbrains.kotlin.buildtools.api.SourcesChanges import org.jetbrains.kotlin.buildtools.api.SourcesChanges
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.compilerRunner.CompilerExecutionSettings import org.jetbrains.kotlin.compilerRunner.CompilerExecutionSettings
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
import org.jetbrains.kotlin.compilerRunner.UsesCompilerSystemPropertiesService import org.jetbrains.kotlin.compilerRunner.UsesCompilerSystemPropertiesService
@@ -164,6 +165,9 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constr
@get:Internal @get:Internal
internal val friendSourceSets = objectFactory.listProperty(String::class.java) internal val friendSourceSets = objectFactory.listProperty(String::class.java)
@get:Internal
internal abstract val kotlinCompilerArgumentsLogLevel: Property<KotlinCompilerArgumentsLogLevel>
private val kotlinLogger by lazy { GradleKotlinLogger(logger) } private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
@get:Internal @get:Internal
@@ -274,7 +274,8 @@ abstract class Kotlin2JsCompile @Inject constructor(
defaultCompilerClasspath, gradleMessageCollector, outputItemCollector, defaultCompilerClasspath, gradleMessageCollector, outputItemCollector,
outputFiles = allOutputFiles(), outputFiles = allOutputFiles(),
reportingSettings = reportingSettings(), reportingSettings = reportingSettings(),
incrementalCompilationEnvironment = icEnv incrementalCompilationEnvironment = icEnv,
compilerArgumentsLogLevel = kotlinCompilerArgumentsLogLevel.get()
) )
processArgsBeforeCompile(args) processArgsBeforeCompile(args)
compilerRunner.runJsCompilerAsync( compilerRunner.runJsCompilerAsync(
@@ -342,7 +342,8 @@ abstract class KotlinCompile @Inject constructor(
- (classpathSnapshotProperties.classpathSnapshotDir.orNull?.asFile?.let { setOf(it) } ?: emptySet()), - (classpathSnapshotProperties.classpathSnapshotDir.orNull?.asFile?.let { setOf(it) } ?: emptySet()),
reportingSettings = reportingSettings(), reportingSettings = reportingSettings(),
incrementalCompilationEnvironment = icEnv, incrementalCompilationEnvironment = icEnv,
kotlinScriptExtensions = scriptExtensions.get().toTypedArray() kotlinScriptExtensions = scriptExtensions.get().toTypedArray(),
compilerArgumentsLogLevel = kotlinCompilerArgumentsLogLevel.get()
) )
compilerRunner.runJvmCompilerAsync( compilerRunner.runJvmCompilerAsync(
args, args,
@@ -141,7 +141,8 @@ abstract class KotlinCompileCommon @Inject constructor(
val environment = GradleCompilerEnvironment( val environment = GradleCompilerEnvironment(
defaultCompilerClasspath, gradleMessageCollector, outputItemCollector, defaultCompilerClasspath, gradleMessageCollector, outputItemCollector,
reportingSettings = reportingSettings(), reportingSettings = reportingSettings(),
outputFiles = allOutputFiles() outputFiles = allOutputFiles(),
compilerArgumentsLogLevel = kotlinCompilerArgumentsLogLevel.get()
) )
compilerRunner.runMetadataCompilerAsync(args, environment) compilerRunner.runMetadataCompilerAsync(args, environment)
compilerRunner.errorsFiles?.let { gradleMessageCollector.flush(it) } compilerRunner.errorsFiles?.let { gradleMessageCollector.flush(it) }
@@ -55,6 +55,8 @@ internal abstract class AbstractKotlinCompileConfig<TASK : AbstractKotlinCompile
task.localStateDirectories.from(task.taskBuildLocalStateDirectory).disallowChanges() task.localStateDirectories.from(task.taskBuildLocalStateDirectory).disallowChanges()
task.systemPropertiesService.value(compilerSystemPropertiesService).disallowChanges() task.systemPropertiesService.value(compilerSystemPropertiesService).disallowChanges()
task.kotlinCompilerArgumentsLogLevel.value(propertiesProvider.kotlinCompilerArgumentsLogLevel).disallowChanges()
propertiesProvider.kotlinDaemonJvmArgs?.let { kotlinDaemonJvmArgs -> propertiesProvider.kotlinDaemonJvmArgs?.let { kotlinDaemonJvmArgs ->
task.kotlinDaemonJvmArguments.set(providers.provider { task.kotlinDaemonJvmArguments.set(providers.provider {
kotlinDaemonJvmArgs.split("\\s+".toRegex()) kotlinDaemonJvmArgs.split("\\s+".toRegex())
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2023 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.unitTests
import org.jetbrains.kotlin.compilerRunner.KotlinCompilerArgumentsLogLevel
import org.jetbrains.kotlin.gradle.plugin.extraProperties
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.util.buildProjectWithJvm
import org.jetbrains.kotlin.gradle.utils.named
import kotlin.test.Test
import kotlin.test.assertEquals
class CompilerArgumentsLogLevelTest {
@Test
fun checkTheDefaultLevel() {
checkLogLevel(KotlinCompilerArgumentsLogLevel.DEFAULT)
}
@Test
fun checkErrorLevel() {
checkLogLevel(KotlinCompilerArgumentsLogLevel.ERROR, "error")
}
@Test
fun checkWarnLevel() {
checkLogLevel(KotlinCompilerArgumentsLogLevel.WARNING, "warning")
}
@Test
fun checkInfoLevel() {
checkLogLevel(KotlinCompilerArgumentsLogLevel.INFO, "info")
}
private fun checkLogLevel(
expectedLogLevel: KotlinCompilerArgumentsLogLevel,
levelToConfigure: String? = null
) {
val project = buildProjectWithJvm(
preApplyCode = {
if (levelToConfigure != null) {
project.extraProperties.set(
"kotlin.internal.compiler.arguments.log.level",
levelToConfigure
)
}
}
)
project.evaluate()
assertEquals(
expectedLogLevel,
project.tasks.named<KotlinCompile>("compileKotlin").get().kotlinCompilerArgumentsLogLevel.get()
)
}
}