From 2719dd188f00fab15988a7be99c5424eae5cb4db Mon Sep 17 00:00:00 2001 From: "Nataliya.Valtman" Date: Tue, 8 Aug 2023 07:43:18 +0000 Subject: [PATCH] Added build metrics for Kotlin/Native tasks #KT-58315 Fixed Co-authored-by: Nataliya Valtman Merge-request: KT-MR-11343 Merged-by: Dmitrii Krasnov --- .../kotlin/build/report/metrics/BuildTime.kt | 10 +- .../gradle/BuildStatisticsWithKtorIT.kt | 99 +++++++++++-- .../kotlin/gradle/experimental/TryK2IT.kt | 37 ++++- .../GradleKotlinCompilerRunner.kt | 6 - .../KotlinNativeCommonizerToolRunner.kt | 6 +- .../kotlin/compilerRunner/KotlinToolRunner.kt | 127 ++++++++-------- .../compilerRunner/nativeToolRunners.kt | 25 +++- .../kotlin/compilerRunner/reportUtils.kt | 43 +++++- .../gradle/report/BuildMetricsService.kt | 1 + .../gradle/report/BuildReportsService.kt | 2 +- .../gradle/targets/js/ir/KotlinBrowserJsIr.kt | 6 - .../targets/js/npm/GradleNodeModulesCache.kt | 4 - .../targets/js/subtargets/KotlinBrowserJs.kt | 5 - .../native/KotlinNativeTargetConfigurator.kt | 6 +- .../AbstractCInteropCommonizerTask.kt | 3 +- .../native/internal/CInteropCommonizerTask.kt | 20 ++- ...yCInteropCommonizerTaskOutputForIdeTask.kt | 30 ++-- .../NativeDistributionCommonizerTask.kt | 38 +++-- .../CInteropRunnerExecutionContextFactory.kt | 18 ++- .../targets/native/tasks/KotlinNativeLink.kt | 91 +++++++----- .../targets/native/tasks/KotlinNativeTasks.kt | 136 +++++++++++------- .../tasks/artifact/KotlinNativeLibrary.kt | 5 +- .../artifact/KotlinNativeLinkArtifactTask.kt | 72 ++++++---- .../AbstractKotlinCompileConfig.kt | 5 - 24 files changed, 530 insertions(+), 265 deletions(-) diff --git a/compiler/build-tools/kotlin-build-statistics/src/org/jetbrains/kotlin/build/report/metrics/BuildTime.kt b/compiler/build-tools/kotlin-build-statistics/src/org/jetbrains/kotlin/build/report/metrics/BuildTime.kt index 060a4a277f0..abdb7e0ce21 100644 --- a/compiler/build-tools/kotlin-build-statistics/src/org/jetbrains/kotlin/build/report/metrics/BuildTime.kt +++ b/compiler/build-tools/kotlin-build-statistics/src/org/jetbrains/kotlin/build/report/metrics/BuildTime.kt @@ -50,6 +50,9 @@ enum class JpsBuildTime(private val parent: JpsBuildTime? = null, private val re @Suppress("Reformat") enum class GradleBuildTime(private val parent: GradleBuildTime? = null, private val readableString: String) : BuildTime { + // We use tabs to organize the hierarchy of metrics, + // that's why the formatter is disabled. + // @formatter:off GRADLE_TASK(readableString = "Total Gradle task time"), GRADLE_TASK_PREPARATION(readableString = "Spent time before task action"), GRADLE_TASK_ACTION(readableString = "Task action"), @@ -65,6 +68,9 @@ enum class GradleBuildTime(private val parent: GradleBuildTime? = null, private CONNECT_TO_DAEMON(RUN_COMPILATION_IN_WORKER, "Connect to Kotlin daemon"), CALCULATE_OUTPUT_SIZE(RUN_COMPILATION_IN_WORKER, "Calculate output size"), RUN_COMPILATION(RUN_COMPILATION_IN_WORKER, "Run compilation"), + NATIVE_IN_PROCESS(RUN_COMPILATION, "Run native in process"), + RUN_ENTRY_POINT(NATIVE_IN_PROCESS, "Run entry point"), + NATIVE_IN_EXECUTOR(RUN_COMPILATION, "Run native in executor"), NON_INCREMENTAL_COMPILATION_IN_PROCESS(RUN_COMPILATION, "Non incremental inprocess compilation"), NON_INCREMENTAL_COMPILATION_OUT_OF_PROCESS(RUN_COMPILATION, "Non incremental out of process compilation"), NON_INCREMENTAL_COMPILATION_DAEMON(RUN_COMPILATION, "Non incremental compilation in daemon"), @@ -116,8 +122,8 @@ enum class GradleBuildTime(private val parent: GradleBuildTime? = null, private SNAPSHOT_KOTLIN_CLASSES(parent = SNAPSHOT_CLASSES, "Snapshot Kotlin classes"), SNAPSHOT_JAVA_CLASSES(parent = SNAPSHOT_CLASSES, "Snapshot Java classes"), SAVE_CLASSPATH_ENTRY_SNAPSHOT(parent = CLASSPATH_ENTRY_SNAPSHOT_TRANSFORM, "Save classpath entry snapshot"), - ; + // @formatter:on override fun getReadableString(): String = readableString override fun getParent(): BuildTime? = parent @@ -130,7 +136,7 @@ enum class GradleBuildTime(private val parent: GradleBuildTime? = null, private return entries } - override fun getName(): String = this.name + override fun getName(): String = this.name companion object { const val serialVersionUID = 1L diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildStatisticsWithKtorIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildStatisticsWithKtorIT.kt index 49cefc3d003..c9b91cb1fda 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildStatisticsWithKtorIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildStatisticsWithKtorIT.kt @@ -15,9 +15,9 @@ import io.ktor.server.netty.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* -import io.ktor.util.* -import io.ktor.util.collections.* +import org.gradle.api.logging.LogLevel import org.gradle.util.GradleVersion +import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import org.jetbrains.kotlin.build.report.statistics.* import org.jetbrains.kotlin.gradle.report.BuildReportType import org.jetbrains.kotlin.gradle.report.data.GradleCompileStatisticsData @@ -28,13 +28,11 @@ import java.net.HttpURLConnection import java.net.InetSocketAddress import java.net.ServerSocket import java.net.URL -import java.util.* import java.util.concurrent.ArrayBlockingQueue import java.util.concurrent.TimeUnit import kotlin.test.* @DisplayName("Build statistics") -@JvmGradlePluginTests class BuildStatisticsWithKtorIT : KGPBaseTest() { companion object { @@ -152,6 +150,7 @@ class BuildStatisticsWithKtorIT : KGPBaseTest() { @DisplayName("Http build report request problems are logged only ones") @GradleTest + @JvmGradlePluginTests fun testHttpServiceWithBadRequest(gradleVersion: GradleVersion) { runWithKtorService { port -> project("incrementalMultiproject", gradleVersion) { @@ -192,6 +191,7 @@ class BuildStatisticsWithKtorIT : KGPBaseTest() { @DisplayName("Validate mandatory field for http request body") @GradleTest + @JvmGradlePluginTests fun testHttpRequest(gradleVersion: GradleVersion) { simpleTestHttpReport(gradleVersion) { taskData -> assertContains(taskData.getTags(), StatTag.NON_INCREMENTAL) @@ -208,6 +208,7 @@ class BuildStatisticsWithKtorIT : KGPBaseTest() { @DisplayName("Compiler arguments reporting can be disabled") @GradleTest + @JvmGradlePluginTests fun testDisablingCompilerArgumentsReporting(gradleVersion: GradleVersion) { simpleTestHttpReport(gradleVersion, { project -> project.gradleProperties.append( @@ -231,6 +232,7 @@ class BuildStatisticsWithKtorIT : KGPBaseTest() { @DisplayName("Validate configuration cache tag") @GradleTest + @JvmGradlePluginTests fun testConfigurationCache(gradleVersion: GradleVersion) { runWithKtorService { port -> @@ -253,16 +255,24 @@ class BuildStatisticsWithKtorIT : KGPBaseTest() { StatTag.NON_INCREMENTAL, StatTag.CONFIGURATION_CACHE, StatTag.KOTLIN_1, - ), taskData.getTags().sorted(), + ), + taskData.getTags().sorted(), ) assertEquals( defaultBuildOptions.kotlinVersion, taskData.getKotlinVersion(), - "Unexpected kotlinVersion: ${taskData.getKotlinVersion()} instead of ${defaultBuildOptions.kotlinVersion}" + "Unexpected kotlinVersion: ${taskData.getKotlinVersion()} instead of ${defaultBuildOptions.kotlinVersion}" ) } validateTaskData(port) { taskData -> assertEquals(":app:compileKotlin", taskData.getTaskName()) - assertContentEquals(listOf(StatTag.ARTIFACT_TRANSFORM, StatTag.NON_INCREMENTAL, StatTag.CONFIGURATION_CACHE, StatTag.KOTLIN_1), taskData.getTags().sorted()) + assertContentEquals( + listOf( + StatTag.ARTIFACT_TRANSFORM, + StatTag.NON_INCREMENTAL, + StatTag.CONFIGURATION_CACHE, + StatTag.KOTLIN_1 + ), taskData.getTags().sorted() + ) assertEquals( defaultBuildOptions.kotlinVersion, taskData.getKotlinVersion(), "Unexpected kotlinVersion: ${taskData.getKotlinVersion()} instead of ${defaultBuildOptions.kotlinVersion}" @@ -274,15 +284,86 @@ class BuildStatisticsWithKtorIT : KGPBaseTest() { //second build validateTaskData(port) { taskData -> assertEquals(":lib:compileKotlin", taskData.getTaskName()) - assertContentEquals(listOf(StatTag.ARTIFACT_TRANSFORM, StatTag.INCREMENTAL, StatTag.CONFIGURATION_CACHE, StatTag.KOTLIN_1), taskData.getTags().sorted()) + assertContentEquals( + listOf(StatTag.ARTIFACT_TRANSFORM, StatTag.INCREMENTAL, StatTag.CONFIGURATION_CACHE, StatTag.KOTLIN_1), + taskData.getTags().sorted() + ) } validateTaskData(port) { taskData -> assertEquals(":app:compileKotlin", taskData.getTaskName()) - assertContentEquals(listOf(StatTag.ARTIFACT_TRANSFORM, StatTag.INCREMENTAL, StatTag.CONFIGURATION_CACHE, StatTag.KOTLIN_1), taskData.getTags().sorted()) + assertContentEquals( + listOf(StatTag.ARTIFACT_TRANSFORM, StatTag.INCREMENTAL, StatTag.CONFIGURATION_CACHE, StatTag.KOTLIN_1), + taskData.getTags().sorted() + ) } } } + @DisplayName("Build reports for native") + @GradleTest + @NativeGradlePluginTests + fun buildReportForNative(gradleVersion: GradleVersion) { + runWithKtorService { port -> + nativeProject( + "k2-native-intermediate-metadata", + gradleVersion, + buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.WARN) + ) { + setProjectForTest(port) + build( + "build", + // Disables cache for explicit task execution and metric collection + "-Pkotlin.mpp.enableNativeDistributionCommonizationCache=false", + ) { + assertOutputDoesNotContain("Failed to send statistic to") + } + } + val commonizerNativeDistributionTask = ":commonizeNativeDistribution" + validateTaskData(port) { taskReport -> + assertEquals(commonizerNativeDistributionTask, taskReport.getTaskName()) + + + assertContains( + taskReport.getBuildTimesMetrics().keys, + GradleBuildTime.NATIVE_IN_EXECUTOR, + "Assertion failed for task \"$commonizerNativeDistributionTask\"" + ) + assertEquals( + defaultBuildOptions.kotlinVersion, taskReport.getKotlinVersion(), + "Unexpected kotlinVersion: ${taskReport.getKotlinVersion()} instead of ${defaultBuildOptions.kotlinVersion}" + ) + } + + val compileNativeTasks = listOf( + ":compileCommonMainKotlinMetadata", + ":compileNativeMainKotlinMetadata", + ) + + for (task in compileNativeTasks) { + validateTaskData(port) { taskReport -> + //can be sure in task execution order + assertEquals(task, taskReport.getTaskName()) + + assertContains( + taskReport.getBuildTimesMetrics().keys, + GradleBuildTime.NATIVE_IN_PROCESS, + "Assertion failed for task \"$task\"" + ) + assertContains( + taskReport.getBuildTimesMetrics().keys, + GradleBuildTime.RUN_ENTRY_POINT, + "Assertion failed for task \"$task\"" + ) + assertEquals( + defaultBuildOptions.kotlinVersion, taskReport.getKotlinVersion(), + "Unexpected kotlinVersion: ${taskReport.getKotlinVersion()} instead of ${defaultBuildOptions.kotlinVersion}" + ) + } + } + } + } + + private fun TestProject.setProjectForTest(port: Int) { enableStatisticReports(BuildReportType.HTTP, "http://localhost:$port/put") } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/experimental/TryK2IT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/experimental/TryK2IT.kt index f3b558e10dd..135d63cdae5 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/experimental/TryK2IT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/experimental/TryK2IT.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.cli.common.arguments.K2NativeCompilerArguments import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics import org.jetbrains.kotlin.gradle.testbase.* import org.jetbrains.kotlin.gradle.util.parseCompilerArgumentsFromBuildOutput +import org.jetbrains.kotlin.konan.target.HostManager import org.junit.jupiter.api.DisplayName import kotlin.io.path.appendText @@ -65,7 +66,7 @@ class TryK2IT : KGPBaseTest() { ) { build("build") { assertOutputDoesNotContain( - "##### 'kotlin.experimental.tryK2' results (Kotlin/Native not checked) #####" + "##### 'kotlin.experimental.tryK2' results #####" ) } } @@ -85,7 +86,7 @@ class TryK2IT : KGPBaseTest() { build("build") { assertOutputContains( """ - |##### 'kotlin.experimental.tryK2' results (Kotlin/Native not checked) ##### + |##### 'kotlin.experimental.tryK2' results ##### |:lib:compileKotlin: 2.0 language version |:app:compileKotlin: 2.0 language version |##### 100% (2/2) tasks have been compiled with Kotlin 2.0 ##### @@ -95,6 +96,36 @@ class TryK2IT : KGPBaseTest() { } } + @DisplayName("Native: report is printed at the end of the build") + @MppGradlePluginTests + @GradleTest + fun buildReportForNative(gradleVersion: GradleVersion) { + project( + "k2-native-intermediate-metadata", + gradleVersion, + buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.WARN) + ) { + enableTryK2() + + build("build") { + assertOutputContains( + """ + |##### 'kotlin.experimental.tryK2' results ##### + |:compileCommonMainKotlinMetadata: 2.0 language version + |:compileNativeMainKotlinMetadata: 2.0 language version + |:compileKotlinLinuxX64: 2.0 language version${ + if (HostManager.hostIsMac) + "\n|:compileKotlinMacosArm64: 2.0 language version\n|:compileKotlinMacosX64: 2.0 language version" + else "" + } + |:compileKotlinMingwX64: 2.0 language version + |##### 100% ${if (HostManager.hostIsMac) "(6/6)" else "(4/4)"} tasks have been compiled with Kotlin 2.0 ##### + """.trimMargin().normalizeLineEndings() + ) + } + } + } + @DisplayName("JVM: report is printed at the end of the build in case of compilation error") @JvmGradlePluginTests @GradleTest @@ -116,7 +147,7 @@ class TryK2IT : KGPBaseTest() { buildAndFail("build", forceOutput = true) { assertOutputContains( """ - |##### 'kotlin.experimental.tryK2' results (Kotlin/Native not checked) ##### + |##### 'kotlin.experimental.tryK2' results ##### |:lib:compileKotlin: 2.0 language version |:app:compileKotlin: 2.0 language version |##### 100% (2/2) tasks have been compiled with Kotlin 2.0 ##### diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt index ba70399afd1..9177a730206 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt @@ -243,12 +243,6 @@ internal open class GradleCompilerRunner( ) } - //Copy of CommonCompilerArguments.parseOrConfigureLanguageVersion to avoid direct dependency - private fun parseLanguageVersion(languageVersion: String?, useK2: Boolean): KotlinVersion { - val explicitVersion = languageVersion?.let { KotlinVersion.fromVersion(languageVersion) } ?: KotlinVersion.DEFAULT - return if (useK2 && (explicitVersion < KotlinVersion.KOTLIN_2_0)) KotlinVersion.KOTLIN_2_0 else explicitVersion - } - protected open fun runCompilerAsync( workArgs: GradleKotlinCompilerWorkArguments, taskOutputsBackup: TaskOutputsBackup? diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinNativeCommonizerToolRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinNativeCommonizerToolRunner.kt index 38dca831ce2..211e29c5469 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinNativeCommonizerToolRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinNativeCommonizerToolRunner.kt @@ -5,12 +5,16 @@ package org.jetbrains.kotlin.compilerRunner +import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter +import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric +import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import java.io.File internal class KotlinNativeCommonizerToolRunner( context: GradleExecutionContext, private val settings: Settings, -) : KotlinToolRunner(context) { + metricsReporter: BuildMetricsReporter +) : KotlinToolRunner(context, metricsReporter) { class Settings( val kotlinPluginVersion: String, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinToolRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinToolRunner.kt index 738f00ab73d..3352224de2e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinToolRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinToolRunner.kt @@ -13,6 +13,7 @@ import org.gradle.api.model.ObjectFactory import org.gradle.process.ExecOperations import org.gradle.process.ExecResult import org.gradle.process.JavaExecSpec +import org.jetbrains.kotlin.build.report.metrics.* import org.jetbrains.kotlin.konan.target.HostManager import java.io.File import java.lang.reflect.InvocationTargetException @@ -22,14 +23,15 @@ import java.util.concurrent.ConcurrentHashMap // Note: this class is public because it is used in the K/N build infrastructure. abstract class KotlinToolRunner( - private val executionContext: GradleExecutionContext + private val executionContext: GradleExecutionContext, + private val metricsReporter: BuildMetricsReporter = DoNothingBuildMetricsReporter ) { @Deprecated( "Using Project object is not compatible with Gradle Configuration Cache", ReplaceWith("KotlinToolRunner(GradleExecutionContext.fromTaskContext())"), DeprecationLevel.WARNING ) - constructor(project: Project): this(GradleExecutionContext.fromProject(project)) + constructor(project: Project) : this(GradleExecutionContext.fromProject(project)) /** * Context Services that are required for [KotlinToolRunner] during Gradle Task Execution Phase @@ -60,7 +62,7 @@ abstract class KotlinToolRunner( fun fromTaskContext( objectFactory: ObjectFactory, execOperations: ExecOperations, - logger: Logger + logger: Logger, ) = GradleExecutionContext( filesProvider = objectFactory.fileCollection()::from, javaexec = { spec -> execOperations.javaexec(spec) }, // execOperations::javaexec won't work due to different Classloaders @@ -127,68 +129,77 @@ abstract class KotlinToolRunner( } open fun run(args: List) { - checkClasspath() + metricsReporter.measure(GradleBuildTime.RUN_COMPILATION_IN_WORKER) { + checkClasspath() - if (mustRunViaExec) runViaExec(args) else runInProcess(args) - } - - private fun runViaExec(args: List) { - val transformedArgs = transformArgs(args) - val classpath = executionContext.filesProvider(classpath) - val systemProperties = System.getProperties() - /* Capture 'System.getProperties()' current state to avoid potential 'ConcurrentModificationException' */ - .snapshot() - .asSequence() - .map { (k, v) -> k.toString() to v.toString() } - .filter { (k, _) -> k !in execSystemPropertiesBlacklist } - .escapeQuotesForWindows() - .toMap() + execSystemProperties - - executionContext.logger.info( - """|Run "$displayName" tool in a separate JVM process - |Main class = $mainClass - |Arguments = ${args.toPrettyString()} - |Transformed arguments = ${if (transformedArgs == args) "same as arguments" else transformedArgs.toPrettyString()} - |Classpath = ${classpath.files.map { it.absolutePath }.toPrettyString()} - |JVM options = ${jvmArgs.toPrettyString()} - |Java system properties = ${systemProperties.toPrettyString()} - |Suppressed ENV variables = ${execEnvironmentBlacklist.toPrettyString()} - |Custom ENV variables = ${execEnvironment.toPrettyString()} - """.trimMargin() - ) - - executionContext.javaexec { spec -> - spec.mainClass.set(mainClass) - spec.classpath = classpath - spec.jvmArgs(jvmArgs) - spec.systemProperties(systemProperties) - execEnvironmentBlacklist.forEach { spec.environment.remove(it) } - spec.environment(execEnvironment) - spec.args(transformedArgs) + if (mustRunViaExec) runViaExec(args, metricsReporter) else runInProcess(args, metricsReporter) } } - private fun runInProcess(args: List) { - val transformedArgs = transformArgs(args) - val isolatedClassLoader = getIsolatedClassLoader() - executionContext.logger.info( - """|Run in-process tool "$displayName" - |Entry point method = $mainClass.$daemonEntryPoint - |Classpath = ${isolatedClassLoader.urLs.map { it.file }.toPrettyString()} - |Arguments = ${args.toPrettyString()} - |Transformed arguments = ${if (transformedArgs == args) "same as arguments" else transformedArgs.toPrettyString()} - """.trimMargin() - ) + private fun runViaExec(args: List, metricsReporter: BuildMetricsReporter) { + metricsReporter.measure(GradleBuildTime.NATIVE_IN_EXECUTOR) { + val transformedArgs = transformArgs(args) + val classpath = executionContext.filesProvider(classpath) + val systemProperties = System.getProperties() + /* Capture 'System.getProperties()' current state to avoid potential 'ConcurrentModificationException' */ + .snapshot() + .asSequence() + .map { (k, v) -> k.toString() to v.toString() } + .filter { (k, _) -> k !in execSystemPropertiesBlacklist } + .escapeQuotesForWindows() + .toMap() + execSystemProperties - try { - val mainClass = isolatedClassLoader.loadClass(mainClass) - val entryPoint = mainClass.methods - .singleOrNull { it.name == daemonEntryPoint } ?: error("Couldn't find daemon entry point '$daemonEntryPoint'") + executionContext.logger.info( + """|Run "$displayName" tool in a separate JVM process + |Main class = $mainClass + |Arguments = ${args.toPrettyString()} + |Transformed arguments = ${if (transformedArgs == args) "same as arguments" else transformedArgs.toPrettyString()} + |Classpath = ${classpath.files.map { it.absolutePath }.toPrettyString()} + |JVM options = ${jvmArgs.toPrettyString()} + |Java system properties = ${systemProperties.toPrettyString()} + |Suppressed ENV variables = ${execEnvironmentBlacklist.toPrettyString()} + |Custom ENV variables = ${execEnvironment.toPrettyString()} + """.trimMargin() + ) - entryPoint.invoke(null, transformedArgs.toTypedArray()) - } catch (t: InvocationTargetException) { - throw t.targetException + executionContext.javaexec { spec -> + spec.mainClass.set(mainClass) + spec.classpath = classpath + spec.jvmArgs(jvmArgs) + spec.systemProperties(systemProperties) + execEnvironmentBlacklist.forEach { spec.environment.remove(it) } + spec.environment(execEnvironment) + spec.args(transformedArgs) + } + } + } + + private fun runInProcess(args: List, metricsReporter: BuildMetricsReporter = DoNothingBuildMetricsReporter) { + metricsReporter.measure(GradleBuildTime.NATIVE_IN_PROCESS) { + val transformedArgs = transformArgs(args) + val isolatedClassLoader = getIsolatedClassLoader() + + executionContext.logger.info( + """|Run in-process tool "$displayName" + |Entry point method = $mainClass.$daemonEntryPoint + |Classpath = ${isolatedClassLoader.urLs.map { it.file }.toPrettyString()} + |Arguments = ${args.toPrettyString()} + |Transformed arguments = ${if (transformedArgs == args) "same as arguments" else transformedArgs.toPrettyString()} + """.trimMargin() + ) + + try { + val mainClass = isolatedClassLoader.loadClass(mainClass) + val entryPoint = mainClass.methods + .singleOrNull { it.name == daemonEntryPoint } ?: error("Couldn't find daemon entry point '$daemonEntryPoint'") + + metricsReporter.measure(GradleBuildTime.RUN_ENTRY_POINT) { + entryPoint.invoke(null, transformedArgs.toTypedArray()) + } + } catch (t: InvocationTargetException) { + throw t.targetException + } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt index 4f6d8472536..e0c05cab4c5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt @@ -7,12 +7,16 @@ package org.jetbrains.kotlin.compilerRunner import org.gradle.api.Project import org.gradle.api.file.FileCollection +import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter +import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric +import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind import org.jetbrains.kotlin.gradle.dsl.NativeCacheOrchestration import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.apple.useXcodeMessageStyle import org.jetbrains.kotlin.gradle.plugin.mpp.nativeUseEmbeddableCompilerJar +import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter import org.jetbrains.kotlin.gradle.targets.native.KonanPropertiesBuildService import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader import org.jetbrains.kotlin.konan.properties.resolvablePropertyString @@ -73,7 +77,8 @@ internal abstract class KotlinNativeToolRunner( protected val toolName: String, private val settings: Settings, executionContext: GradleExecutionContext, -) : KotlinToolRunner(executionContext) { + metricsReporter: BuildMetricsReporter +) : KotlinToolRunner(executionContext, metricsReporter) { class Settings( val konanVersion: String, @@ -151,7 +156,8 @@ internal abstract class AbstractKotlinNativeCInteropRunner( toolName: String, settings: Settings, executionContext: GradleExecutionContext, -) : KotlinNativeToolRunner(toolName, settings, executionContext) { + metricsReporter: BuildMetricsReporter +) : KotlinNativeToolRunner(toolName, settings, executionContext, metricsReporter) { override val mustRunViaExec get() = true @@ -187,17 +193,19 @@ internal class KotlinNativeCInteropRunner private constructor( private val settings: Settings, gradleExecutionContext: GradleExecutionContext, -) : AbstractKotlinNativeCInteropRunner("cinterop", settings, gradleExecutionContext) { + metricsReporter: BuildMetricsReporter +) : AbstractKotlinNativeCInteropRunner("cinterop", settings, gradleExecutionContext, metricsReporter) { interface ExecutionContext { val runnerSettings: Settings val gradleExecutionContext: GradleExecutionContext + val metricsReporter: BuildMetricsReporter fun runWithContext(action: () -> Unit) } companion object { fun ExecutionContext.run(args: List) { - val runner = KotlinNativeCInteropRunner(runnerSettings, gradleExecutionContext) + val runner = KotlinNativeCInteropRunner(runnerSettings, gradleExecutionContext, metricsReporter) runWithContext { runner.run(args) } } } @@ -207,7 +215,8 @@ private constructor( internal class KotlinNativeCompilerRunner( private val settings: Settings, executionContext: GradleExecutionContext, -) : KotlinNativeToolRunner("konanc", settings.parent, executionContext) { + metricsReporter: BuildMetricsReporter +) : KotlinNativeToolRunner("konanc", settings.parent, executionContext, metricsReporter) { class Settings( val parent: KotlinNativeToolRunner.Settings, val disableKonanDaemon: Boolean, @@ -245,13 +254,15 @@ internal class KotlinNativeCompilerRunner( internal class KotlinNativeLibraryGenerationRunner( private val settings: Settings, executionContext: GradleExecutionContext, + metricsReporter: BuildMetricsReporter ) : - AbstractKotlinNativeCInteropRunner("generatePlatformLibraries", settings, executionContext) { + AbstractKotlinNativeCInteropRunner("generatePlatformLibraries", settings, executionContext, metricsReporter) { companion object { fun fromProject(project: Project) = KotlinNativeLibraryGenerationRunner( settings = Settings.fromProject(project), - executionContext = GradleExecutionContext.fromProject(project) + executionContext = GradleExecutionContext.fromProject(project), + metricsReporter = GradleBuildMetricsReporter() ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/reportUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/reportUtils.kt index 0cdc0f167e7..27292d5c413 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/reportUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/reportUtils.kt @@ -16,7 +16,10 @@ package org.jetbrains.kotlin.compilerRunner -import org.gradle.internal.impldep.org.apache.commons.lang.StringEscapeUtils +import org.jetbrains.kotlin.build.report.metrics.BuildMetrics +import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter +import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric +import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import org.jetbrains.kotlin.buildtools.api.KotlinLogger import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity @@ -26,8 +29,13 @@ import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets import org.jetbrains.kotlin.daemon.client.launchProcessWithFallback +import org.jetbrains.kotlin.gradle.dsl.KotlinVersion import org.jetbrains.kotlin.gradle.logging.GradleErrorMessageCollector import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger +import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults +import org.jetbrains.kotlin.gradle.report.TaskExecutionInfo +import org.jetbrains.kotlin.gradle.report.TaskExecutionResult +import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly import org.jetbrains.org.objectweb.asm.ClassReader @@ -35,7 +43,6 @@ import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.FieldVisitor import org.jetbrains.org.objectweb.asm.Opcodes import java.io.File -import java.io.StringWriter import java.nio.file.Files import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -240,4 +247,36 @@ internal fun exitCodeFromProcessExitCode(log: KotlinLogger, code: Int): ExitCode log.debug("Could not find exit code by value: $code") return if (code == 0) ExitCode.OK else ExitCode.COMPILATION_ERROR +} + +//Copy of CommonCompilerArguments.parseOrConfigureLanguageVersion to avoid direct dependency +internal fun parseLanguageVersion(languageVersion: String?, useK2: Boolean): KotlinVersion { + val explicitVersion = languageVersion?.let { KotlinVersion.fromVersion(languageVersion) } ?: KotlinVersion.DEFAULT + return if (useK2 && (explicitVersion < KotlinVersion.KOTLIN_2_0)) KotlinVersion.KOTLIN_2_0 else explicitVersion +} + +internal fun parseLanguageVersion(args: List): KotlinVersion { + val languageVersionIndex = args.indexOf("-language-version") + val languageVersion = if (languageVersionIndex >= 0) { + args[languageVersionIndex + 1] + } else null + val useK2 = args.indexOf("-Xuse-k2") >= 0 + return parseLanguageVersion(languageVersion, useK2) +} + +internal fun UsesBuildMetricsService.addBuildMetricsForTaskAction( + metricsReporter: BuildMetricsReporter, + languageVersion: KotlinVersion?, + fn: () -> Any +) { + metricsReporter.addTimeMetric(GradleBuildPerformanceMetric.START_TASK_ACTION_EXECUTION) + buildMetricsService.orNull?.also { it.addTask(path, this.javaClass, metricsReporter) } + + try { + fn.invoke() + } finally { + val result = TaskExecutionResult(buildMetrics = BuildMetrics(), taskInfo = TaskExecutionInfo(kotlinLanguageVersion = languageVersion)) + TaskExecutionResults[path] = result + } + } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt index 243d6c34ce7..bd3625010b9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt @@ -288,6 +288,7 @@ abstract class BuildMetricsService : BuildService SingleActionPerProject.run(project, UsesBuildMetricsService::class.java.name) { project.tasks.withType().configureEach { task -> + task.buildMetricsService.value(serviceProvider).disallowChanges() task.usesService(serviceProvider) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt index b1182fd79b4..bed2738bd1a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt @@ -270,7 +270,7 @@ class BuildReportsService { // Filtering by only KGP tasks and by those that actually do compilation it.isFromKotlinPlugin && it.kotlinLanguageVersion != null } - log.warn("##### 'kotlin.experimental.tryK2' results (Kotlin/Native not checked) #####") + log.warn("##### 'kotlin.experimental.tryK2' results #####") if (tasksData.isEmpty()) { log.warn("No Kotlin compilation tasks have been run") log.warn("#####") diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt index 147e8ac3eec..76698a9086a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.gradle.targets.js.ir import org.gradle.api.Action -import org.gradle.api.DomainObjectCollection import org.gradle.api.DomainObjectSet import org.gradle.api.Task import org.gradle.api.provider.Property @@ -16,9 +15,7 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin import org.jetbrains.kotlin.gradle.dsl.JsModuleKind import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName -import org.jetbrains.kotlin.gradle.report.BuildMetricsService import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDceDsl import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl @@ -225,9 +222,6 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : task.description = "build webpack ${mode.name.toLowerCaseAsciiOnly()} bundle" task.outputDirectory.fileValue(binary.distribution.directory).finalizeValueOnRead() - BuildMetricsService.registerIfAbsent(project)?.let { - task.buildMetricsService.value(it) - } task.dependsOn( distributeResourcesTask diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesCache.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesCache.kt index 8f6aafd9fa9..cffc4e5cc68 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesCache.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesCache.kt @@ -8,14 +8,10 @@ package org.jetbrains.kotlin.gradle.targets.js.npm import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.file.ArchiveOperations -import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileSystemOperations import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.Internal -import org.jetbrains.kotlin.gradle.report.BuildMetricsService -import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService -import org.jetbrains.kotlin.gradle.report.reportingSettings import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject import java.io.File diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt index e8042d3e7a8..207c8e940ce 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt @@ -19,7 +19,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.isMain import org.jetbrains.kotlin.gradle.plugin.mpp.isTest import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory -import org.jetbrains.kotlin.gradle.report.BuildMetricsService import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget import org.jetbrains.kotlin.gradle.targets.js.dsl.* import org.jetbrains.kotlin.gradle.targets.js.ir.executeTaskBaseName @@ -230,10 +229,6 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) : task.description = "build webpack ${type.name.toLowerCaseAsciiOnly()} bundle" task.outputDirectory.fileValue(distribution.directory).finalizeValueOnRead() - BuildMetricsService.registerIfAbsent(project)?.let { - task.buildMetricsService.value(it) - } - task.commonConfigure( compilation = compilation, dceTaskProvider = dceTaskProvider, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt index b56a75958fa..f62f6ad1fbb 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPI import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationInfo.KPM import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.ReadyForExecution import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.KOTLIN_NATIVE_IGNORE_INCORRECT_DEPENDENCIES -import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider import org.jetbrains.kotlin.gradle.plugin.internal.artifactTypeAttribute import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XcodeVersionTask @@ -38,10 +37,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled import org.jetbrains.kotlin.gradle.targets.native.* import org.jetbrains.kotlin.gradle.targets.native.internal.* -import org.jetbrains.kotlin.gradle.targets.native.internal.commonizeCInteropTask -import org.jetbrains.kotlin.gradle.targets.native.internal.createCInteropApiElementsKlibArtifact -import org.jetbrains.kotlin.gradle.targets.native.internal.locateOrCreateCInteropApiElementsConfiguration -import org.jetbrains.kotlin.gradle.targets.native.internal.locateOrCreateCInteropDependencyConfiguration import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeHostTest import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeSimulatorTest import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest @@ -415,6 +410,7 @@ open class KotlinNativeTargetConfigurator : AbstractKotl } ) .finalizeValueOnRead() + } compilationInfo.classesDirs.from(compileTaskProvider.map { it.outputFile }) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/AbstractCInteropCommonizerTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/AbstractCInteropCommonizerTask.kt index d10f6b8b90d..55543052cb3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/AbstractCInteropCommonizerTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/AbstractCInteropCommonizerTask.kt @@ -13,13 +13,14 @@ import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout.base64Hash import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout.ensureMaxFileNameLength import org.jetbrains.kotlin.commonizer.identityString +import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService import org.jetbrains.kotlin.gradle.utils.changing import org.jetbrains.kotlin.gradle.utils.future import org.jetbrains.kotlin.gradle.utils.outputFilesProvider import java.io.File @DisableCachingByDefault(because = "Abstract super-class, not to be instantiated directly") -internal abstract class AbstractCInteropCommonizerTask : DefaultTask() { +internal abstract class AbstractCInteropCommonizerTask : DefaultTask(), UsesBuildMetricsService { @get:OutputDirectory abstract val outputDirectory: File diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropCommonizerTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropCommonizerTask.kt index 117764a9389..2457894fe7c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropCommonizerTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropCommonizerTask.kt @@ -15,10 +15,13 @@ import org.gradle.api.provider.Provider import org.gradle.api.provider.SetProperty import org.gradle.api.tasks.* import org.gradle.process.ExecOperations +import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter +import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric +import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import org.jetbrains.kotlin.commonizer.* +import org.jetbrains.kotlin.compilerRunner.* import org.jetbrains.kotlin.compilerRunner.GradleCliCommonizer import org.jetbrains.kotlin.compilerRunner.KotlinNativeCommonizerToolRunner -import org.jetbrains.kotlin.compilerRunner.KotlinToolRunner import org.jetbrains.kotlin.compilerRunner.konanHome import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull @@ -26,6 +29,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.sources.withDependsOnClosure +import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerTask.CInteropCommonizerDependencies import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerTask.CInteropGist import org.jetbrains.kotlin.gradle.tasks.CInteropProcess @@ -38,7 +42,7 @@ private typealias GroupedCommonizerDependencies = Map get() = allInteropGroups.getOrThrow().map { outputDirectory(it) }.toSet() + @get:Internal + val metrics: Property> = project.objects + .property(GradleBuildMetricsReporter()) + internal fun from(task: TaskProvider) { dependsOn(task) cinterops.add(task.map { it.toGist() }) @@ -185,7 +193,10 @@ internal open class CInteropCommonizerTask @TaskAction protected fun commonizeCInteropLibraries() { - allInteropGroups.getOrThrow().forEach(::commonize) + val metricReporter = metrics.get() + addBuildMetricsForTaskAction(metricsReporter = metricReporter, languageVersion = null) { + allInteropGroups.getOrThrow().forEach(::commonize) + } } private fun commonize(group: CInteropCommonizerGroup) { @@ -195,7 +206,8 @@ internal open class CInteropCommonizerTask val commonizerRunner = KotlinNativeCommonizerToolRunner( context = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger), - settings = runnerSettings.get() + settings = runnerSettings.get(), + metricsReporter = metrics.get(), ) GradleCliCommonizer(commonizerRunner).commonizeLibraries( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CopyCInteropCommonizerTaskOutputForIdeTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CopyCInteropCommonizerTaskOutputForIdeTask.kt index 8ac039299b2..6a052c68313 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CopyCInteropCommonizerTaskOutputForIdeTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CopyCInteropCommonizerTaskOutputForIdeTask.kt @@ -5,15 +5,22 @@ package org.jetbrains.kotlin.gradle.targets.native.internal +import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.work.DisableCachingByDefault import org.gradle.work.NormalizeLineEndings +import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter +import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric +import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime +import org.jetbrains.kotlin.compilerRunner.addBuildMetricsForTaskAction +import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter +import org.jetbrains.kotlin.gradle.utils.property import java.io.File import javax.inject.Inject @DisableCachingByDefault -internal open class CopyCommonizeCInteropForIdeTask @Inject constructor( +internal abstract class CopyCommonizeCInteropForIdeTask @Inject constructor( private val commonizeCInteropTask: TaskProvider ) : AbstractCInteropCommonizerTask() { @@ -32,15 +39,22 @@ internal open class CopyCommonizeCInteropForIdeTask @Inject constructor( return commonizeCInteropTask.get().findInteropsGroup(dependent) } + @get:Internal + val metrics: Property> = project.objects + .property(GradleBuildMetricsReporter()) + @TaskAction protected fun copy() { - outputDirectory.mkdirs() - for (group in commonizeCInteropTask.get().allInteropGroups.getOrThrow()) { - val source = commonizeCInteropTask.get().outputDirectory(group) - if (!source.exists()) continue - val target = outputDirectory(group) - if (target.exists()) target.deleteRecursively() - source.copyRecursively(target, true) + val metricReporter = metrics.get() + addBuildMetricsForTaskAction(metricsReporter = metricReporter, languageVersion = null) { + outputDirectory.mkdirs() + for (group in commonizeCInteropTask.get().allInteropGroups.getOrThrow()) { + val source = commonizeCInteropTask.get().outputDirectory(group) + if (!source.exists()) continue + val target = outputDirectory(group) + if (target.exists()) target.deleteRecursively() + source.copyRecursively(target, true) + } } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/NativeDistributionCommonizerTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/NativeDistributionCommonizerTask.kt index 3b41d5ad023..83efe01eaf4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/NativeDistributionCommonizerTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/NativeDistributionCommonizerTask.kt @@ -18,14 +18,19 @@ import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.gradle.process.ExecOperations import org.gradle.work.DisableCachingByDefault +import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter +import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric +import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget +import org.jetbrains.kotlin.compilerRunner.* import org.jetbrains.kotlin.compilerRunner.GradleCliCommonizer import org.jetbrains.kotlin.compilerRunner.KotlinNativeCommonizerToolRunner -import org.jetbrains.kotlin.compilerRunner.KotlinToolRunner import org.jetbrains.kotlin.compilerRunner.konanHome import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion +import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter +import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService import org.jetbrains.kotlin.gradle.utils.chainedFinalizeValueOnRead import org.jetbrains.kotlin.gradle.utils.listProperty import org.jetbrains.kotlin.gradle.utils.property @@ -36,11 +41,11 @@ import java.net.URLEncoder import javax.inject.Inject @DisableCachingByDefault(because = "Native Distribution Commonizer Task uses internal caching mechanism with fine grained cache control") -internal open class NativeDistributionCommonizerTask +internal abstract class NativeDistributionCommonizerTask @Inject constructor( private val objectFactory: ObjectFactory, private val execOperations: ExecOperations, -) : DefaultTask() { +) : DefaultTask(), UsesBuildMetricsService { private val konanHome = project.file(project.konanHome) @@ -89,19 +94,28 @@ internal open class NativeDistributionCommonizerTask isCachingEnabled = project.kotlinPropertiesProvider.enableNativeDistributionCommonizationCache ) + @get:Internal + val metrics: Property> = project.objects + .property(GradleBuildMetricsReporter()) + @TaskAction protected fun run() { - val commonizerRunner = KotlinNativeCommonizerToolRunner( - context = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger), - settings = runnerSettings.get() - ) + val metricsReporter = metrics.get() - commonizerCache.writeCacheForUncachedTargets(commonizerTargets) { todoOutputTargets -> - val commonizer = GradleCliCommonizer(commonizerRunner) - /* Invoke commonizer with only 'to do' targets */ - commonizer.commonizeNativeDistribution( - konanHome, rootOutputDirectory, todoOutputTargets, logLevel, additionalSettings + addBuildMetricsForTaskAction(metricsReporter = metricsReporter, languageVersion = null) { + val commonizerRunner = KotlinNativeCommonizerToolRunner( + context = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger), + settings = runnerSettings.get(), + metricsReporter = metricsReporter, ) + + commonizerCache.writeCacheForUncachedTargets(commonizerTargets) { todoOutputTargets -> + val commonizer = GradleCliCommonizer(commonizerRunner) + /* Invoke commonizer with only 'to do' targets */ + commonizer.commonizeNativeDistribution( + konanHome, rootOutputDirectory, todoOutputTargets, logLevel, additionalSettings + ) + } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CInteropRunnerExecutionContextFactory.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CInteropRunnerExecutionContextFactory.kt index 556ff058f55..873facda146 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CInteropRunnerExecutionContextFactory.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/CInteropRunnerExecutionContextFactory.kt @@ -6,23 +6,30 @@ package org.jetbrains.kotlin.gradle.targets.native.tasks import org.gradle.api.Task +import org.jetbrains.kotlin.build.report.metrics.BuildMetrics +import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter +import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric +import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import org.jetbrains.kotlin.compilerRunner.KotlinNativeCInteropRunner import org.jetbrains.kotlin.compilerRunner.KotlinNativeToolRunner import org.jetbrains.kotlin.compilerRunner.KotlinToolRunner +import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter internal fun KotlinNativeCInteropRunner.Companion.createExecutionContext( task: Task, isInIdeaSync: Boolean, runnerSettings: KotlinNativeToolRunner.Settings, - gradleExecutionContext: KotlinToolRunner.GradleExecutionContext + gradleExecutionContext: KotlinToolRunner.GradleExecutionContext, + metricsReporter: BuildMetricsReporter ): KotlinNativeCInteropRunner.ExecutionContext { - return if (isInIdeaSync) IdeaSyncKotlinNativeCInteropRunnerExecutionContext(runnerSettings, gradleExecutionContext, task) - else DefaultKotlinNativeCInteropRunnerExecutionContext(runnerSettings, gradleExecutionContext) + return if (isInIdeaSync) IdeaSyncKotlinNativeCInteropRunnerExecutionContext(runnerSettings, gradleExecutionContext, task, metricsReporter) + else DefaultKotlinNativeCInteropRunnerExecutionContext(runnerSettings, gradleExecutionContext, metricsReporter) } private class DefaultKotlinNativeCInteropRunnerExecutionContext( override val runnerSettings: KotlinNativeToolRunner.Settings, - override val gradleExecutionContext: KotlinToolRunner.GradleExecutionContext + override val gradleExecutionContext: KotlinToolRunner.GradleExecutionContext, + override val metricsReporter: BuildMetricsReporter ) : KotlinNativeCInteropRunner.ExecutionContext { override fun runWithContext(action: () -> Unit) = action() } @@ -30,7 +37,8 @@ private class DefaultKotlinNativeCInteropRunnerExecutionContext( private class IdeaSyncKotlinNativeCInteropRunnerExecutionContext( override val runnerSettings: KotlinNativeToolRunner.Settings, override val gradleExecutionContext: KotlinToolRunner.GradleExecutionContext, - private val task: Task + private val task: Task, + override val metricsReporter: BuildMetricsReporter ) : KotlinNativeCInteropRunner.ExecutionContext { override fun runWithContext(action: () -> Unit) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt index cade8957f41..2ff6eeb5d21 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt @@ -14,9 +14,13 @@ import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.process.ExecOperations +import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter +import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric +import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import org.jetbrains.kotlin.cli.common.arguments.K2NativeCompilerArguments import org.jetbrains.kotlin.compilerRunner.* import org.jetbrains.kotlin.gradle.dsl.* @@ -25,6 +29,8 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerArgumentsProducer.Create import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.cocoapods.asValidFrameworkName import org.jetbrains.kotlin.gradle.plugin.mpp.* +import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter +import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService import org.jetbrains.kotlin.gradle.targets.native.UsesKonanPropertiesBuildService import org.jetbrains.kotlin.gradle.targets.native.tasks.CompilerPluginData import org.jetbrains.kotlin.gradle.utils.* @@ -49,6 +55,7 @@ constructor( private val execOperations: ExecOperations, ) : AbstractKotlinCompileTool(objectFactory), UsesKonanPropertiesBuildService, + UsesBuildMetricsService, KotlinToolTask { @Deprecated("Visibility will be lifted to private in the future releases") @@ -346,52 +353,60 @@ constructor( @TaskAction fun compile() { - validatedExportedLibraries() + val metricsReporter = metrics.get() - val output = outputFile.get() - output.parentFile.mkdirs() + addBuildMetricsForTaskAction(metricsReporter = metricsReporter, languageVersion = parseLanguageVersion(externalDependenciesArgs)) { + validatedExportedLibraries() - val executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger) - val additionalOptions = mutableListOf().apply { - addAll(externalDependenciesArgs) - when (cacheSettings.orchestration) { - NativeCacheOrchestration.Compiler -> { - if (cacheSettings.kind != NativeCacheKind.NONE - && !optimized - && konanPropertiesService.get().cacheWorksFor(konanTarget) - ) { - add("-Xauto-cache-from=${cacheSettings.gradleUserHomeDir}") - add("-Xbackend-threads=${cacheSettings.threads}") - if (cacheSettings.icEnabled) { - val icCacheDir = cacheSettings.gradleBuildDir.resolve("kotlin-native-ic-cache") - icCacheDir.mkdirs() - add("-Xenable-incremental-compilation") - add("-Xic-cache-dir=$icCacheDir") + val output = outputFile.get() + output.parentFile.mkdirs() + + val executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger) + val additionalOptions = mutableListOf().apply { + addAll(externalDependenciesArgs) + when (cacheSettings.orchestration) { + NativeCacheOrchestration.Compiler -> { + if (cacheSettings.kind != NativeCacheKind.NONE + && !optimized + && konanPropertiesService.get().cacheWorksFor(konanTarget) + ) { + add("-Xauto-cache-from=${cacheSettings.gradleUserHomeDir}") + add("-Xbackend-threads=${cacheSettings.threads}") + if (cacheSettings.icEnabled) { + val icCacheDir = cacheSettings.gradleBuildDir.resolve("kotlin-native-ic-cache") + icCacheDir.mkdirs() + add("-Xenable-incremental-compilation") + add("-Xic-cache-dir=$icCacheDir") + } } } - } - NativeCacheOrchestration.Gradle -> { - if (cacheSettings.icEnabled) { - executionContext.logger.warn( - "K/N incremental compilation only works in conjunction with kotlin.native.cacheOrchestration=compiler") + NativeCacheOrchestration.Gradle -> { + if (cacheSettings.icEnabled) { + executionContext.logger.warn( + "K/N incremental compilation only works in conjunction with kotlin.native.cacheOrchestration=compiler" + ) + } + val cacheBuilder = CacheBuilder( + executionContext = executionContext, + settings = cacheBuilderSettings, + konanPropertiesService = konanPropertiesService.get(), + metricsReporter = metricsReporter + ) + addAll(cacheBuilder.buildCompilerArgs(resolvedConfiguration)) } - val cacheBuilder = CacheBuilder( - executionContext = executionContext, - settings = cacheBuilderSettings, - konanPropertiesService = konanPropertiesService.get() - ) - addAll(cacheBuilder.buildCompilerArgs(resolvedConfiguration)) } } + + val arguments = createCompilerArguments() + val buildArguments = ArgumentUtils.convertArgumentsToStringList(arguments) + additionalOptions + + KotlinNativeCompilerRunner( + settings = runnerSettings, + executionContext = executionContext, + metricsReporter = metricsReporter + + ).run(buildArguments) } - - val arguments = createCompilerArguments() - val buildArguments = ArgumentUtils.convertArgumentsToStringList(arguments) + additionalOptions - - KotlinNativeCompilerRunner( - settings = runnerSettings, - executionContext = executionContext - ).run(buildArguments) } private inline fun lazyConvention(noinline lazyConventionValue: () -> T): Provider { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt index 28d82638581..0a8813b7df3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt @@ -23,6 +23,7 @@ import org.gradle.api.tasks.* import org.gradle.process.ExecOperations import org.gradle.work.DisableCachingByDefault import org.gradle.work.NormalizeLineEndings +import org.jetbrains.kotlin.build.report.metrics.* import org.jetbrains.kotlin.cli.common.arguments.* import org.jetbrains.kotlin.compilerRunner.* import org.jetbrains.kotlin.compilerRunner.KotlinNativeCInteropRunner.Companion.run @@ -39,9 +40,12 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmMetadataCompilationData import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmNativeCompilationData import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService +import org.jetbrains.kotlin.gradle.report.* +import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService import org.jetbrains.kotlin.gradle.targets.native.KonanPropertiesBuildService import org.jetbrains.kotlin.gradle.targets.native.tasks.* import org.jetbrains.kotlin.gradle.utils.* +import org.jetbrains.kotlin.gradle.utils.GradleLoggerAdapter import org.jetbrains.kotlin.gradle.utils.listFilesOrEmpty import org.jetbrains.kotlin.ir.linkage.partial.PartialLinkageMode import org.jetbrains.kotlin.konan.library.KLIB_INTEROP_IR_PROVIDER_IDENTIFIER @@ -122,10 +126,10 @@ internal fun FileCollection.filterKlibsPassedToCompiler(): FileCollection = filt @DisableCachingByDefault(because = "Abstract super-class, not to be instantiated directly") abstract class AbstractKotlinNativeCompile< T : KotlinCommonToolOptions, - M : CommonToolArguments + M : CommonToolArguments, > @Inject constructor( - private val objectFactory: ObjectFactory + private val objectFactory: ObjectFactory, ) : AbstractKotlinCompileTool(objectFactory) { @get:Inject @@ -309,10 +313,11 @@ internal constructor( override val compilerOptions: KotlinNativeCompilerOptions, private val objectFactory: ObjectFactory, private val providerFactory: ProviderFactory, - private val execOperations: ExecOperations + private val execOperations: ExecOperations, ) : AbstractKotlinNativeCompile(objectFactory), KotlinCompile, K2MultiplatformCompilationTask, + UsesBuildMetricsService, KotlinCompilationTask { @get:Input @@ -518,17 +523,27 @@ internal constructor( @TaskAction fun compile() { - val output = outputFile.get() - output.parentFile.mkdirs() + val buildMetrics = metrics.get() + addBuildMetricsForTaskAction( + metricsReporter = buildMetrics, + languageVersion = parseLanguageVersion(compilerOptions.languageVersion.orNull?.version, compilerOptions.useK2.get()) + ) { + val arguments = createCompilerArguments() + val buildArguments = buildMetrics.measure(GradleBuildTime.OUT_OF_WORKER_TASK_ACTION) { + val output = outputFile.get() + output.parentFile.mkdirs() - collectCommonCompilerStats() - val arguments = createCompilerArguments() - val buildArguments = ArgumentUtils.convertArgumentsToStringList(arguments) + collectCommonCompilerStats() + ArgumentUtils.convertArgumentsToStringList(arguments) + } + + KotlinNativeCompilerRunner( + settings = runnerSettings, + executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger), + metricsReporter = buildMetrics + ).run(buildArguments) + } - KotlinNativeCompilerRunner( - settings = runnerSettings, - executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger) - ).run(buildArguments) } private fun collectCommonCompilerStats() { @@ -547,7 +562,7 @@ internal constructor( internal class ExternalDependenciesBuilder( val project: Project, val compilation: KotlinCompilation<*>, - intermediateLibraryName: String? + intermediateLibraryName: String?, ) { constructor(project: Project, compilation: KotlinNativeCompilation) : this( project, compilation, compilation.compileKotlinTask.moduleName @@ -721,6 +736,7 @@ internal class CacheBuilder( private val executionContext: KotlinToolRunner.GradleExecutionContext, private val settings: Settings, private val konanPropertiesService: KonanPropertiesBuildService, + private val metricsReporter: BuildMetricsReporter ) { class Settings( val runnerSettings: KotlinNativeCompilerRunner.Settings, @@ -747,7 +763,7 @@ internal class CacheBuilder( binary: NativeBinary, konanTarget: KonanTarget, toolOptions: KotlinCommonCompilerToolOptions, - externalDependenciesArgs: List + externalDependenciesArgs: List, ): Settings { val konanCacheKind = project.getKonanCacheKind(konanTarget) return Settings( @@ -800,7 +816,7 @@ internal class CacheBuilder( private fun getCacheDirectory( resolvedConfiguration: LazyResolvedConfiguration, - dependency: ResolvedDependencyResult + dependency: ResolvedDependencyResult, ): File = getCacheDirectory( rootCacheDirectory = rootCacheDirectory, dependency = dependency, @@ -814,7 +830,7 @@ internal class CacheBuilder( private fun LazyResolvedConfiguration.ensureDependencyPrecached( dependency: ResolvedDependencyResult, - visitedDependencies: MutableSet + visitedDependencies: MutableSet, ) { if (dependency in visitedDependencies) return @@ -903,7 +919,7 @@ internal class CacheBuilder( args += "-l" args += it.libraryFile.absolutePath } - KotlinNativeCompilerRunner(settings.runnerSettings, executionContext).run(args) + KotlinNativeCompilerRunner(settings.runnerSettings, executionContext, GradleBuildMetricsReporter()).run(args) } } @@ -913,7 +929,7 @@ internal class CacheBuilder( private fun ensureCompilerProvidedLibPrecached( platformLibName: String, platformLibs: Map, - visitedLibs: MutableSet + visitedLibs: MutableSet, ) { if (platformLibName in visitedLibs) return @@ -944,7 +960,7 @@ internal class CacheBuilder( } args += "-Xadd-cache=${platformLib.absolutePath}" args += "-Xcache-directory=${rootCacheDirectory.absolutePath}" - KotlinNativeCompilerRunner(settings.runnerSettings, executionContext).run(args) + KotlinNativeCompilerRunner(settings.runnerSettings, executionContext, metricsReporter).run(args) } private fun ensureCompilerProvidedLibsPrecached() { @@ -995,7 +1011,8 @@ internal class CacheBuilder( } @CacheableTask -open class CInteropProcess @Inject internal constructor(params: Params) : DefaultTask() { +abstract class CInteropProcess @Inject internal constructor(params: Params) : + DefaultTask(), UsesBuildMetricsService { internal class Params( val settings: DefaultCInteropSettings, @@ -1003,11 +1020,11 @@ open class CInteropProcess @Inject internal constructor(params: Params) : Defaul val compilationName: String, val konanTarget: KonanTarget, val baseKlibName: String, - val services: Services + val services: Services, ) { internal open class Services @Inject constructor( val objectFactory: ObjectFactory, - val execOperations: ExecOperations + val execOperations: ExecOperations, ) } @@ -1104,48 +1121,57 @@ open class CInteropProcess @Inject internal constructor(params: Params) : Defaul @get:Input val extraOpts: List get() = settings.extraOpts + @get:Internal + val metrics: Property> = project.objects + .property(GradleBuildMetricsReporter()) + private val isInIdeaSync = project.isInIdeaSync // Task action. @TaskAction fun processInterop() { - val args = mutableListOf().apply { - addArg("-o", outputFile.absolutePath) + val buildMetrics = metrics.get() - addArgIfNotNull("-target", konanTarget.visibleName) - addArgIfNotNull("-def", defFile.canonicalPath) - addArgIfNotNull("-pkg", packageName) + val args = + mutableListOf().apply { + addArg("-o", outputFile.absolutePath) - addFileArgs("-header", headers) + addArgIfNotNull("-target", konanTarget.visibleName) + addArgIfNotNull("-def", defFile.canonicalPath) + addArgIfNotNull("-pkg", packageName) + + addFileArgs("-header", headers) + + compilerOpts.forEach { + addArg("-compiler-option", it) + } + + linkerOpts.forEach { + addArg("-linker-option", it) + } + + libraries.files.filterKlibsPassedToCompiler().forEach { library -> + addArg("-library", library.absolutePath) + } + + addArgs("-compiler-option", allHeadersDirs.map { "-I${it.absolutePath}" }) + addArgs("-headerFilterAdditionalSearchPrefix", headerFilterDirs.map { it.absolutePath }) + addArg("-Xmodule-name", moduleName) + + addArg("-libraryVersion", libraryVersion) + + addAll(extraOpts) - compilerOpts.forEach { - addArg("-compiler-option", it) } - - linkerOpts.forEach { - addArg("-linker-option", it) - } - - libraries.files.filterKlibsPassedToCompiler().forEach { library -> - addArg("-library", library.absolutePath) - } - - addArgs("-compiler-option", allHeadersDirs.map { "-I${it.absolutePath}" }) - addArgs("-headerFilterAdditionalSearchPrefix", headerFilterDirs.map { it.absolutePath }) - addArg("-Xmodule-name", moduleName) - - // TODO: uncomment after advancing bootstrap. - //addArg("-libraryVersion", libraryVersion) - - addAll(extraOpts) + addBuildMetricsForTaskAction(buildMetrics, languageVersion = parseLanguageVersion(args)) { + outputFile.parentFile.mkdirs() + KotlinNativeCInteropRunner.createExecutionContext( + task = this, + isInIdeaSync = isInIdeaSync, + runnerSettings = runnerSettings, + gradleExecutionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger), + metricsReporter = buildMetrics + ).run(args) } - - outputFile.parentFile.mkdirs() - KotlinNativeCInteropRunner.createExecutionContext( - task = this, - isInIdeaSync = isInIdeaSync, - runnerSettings = runnerSettings, - gradleExecutionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger) - ).run(args) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt index 12ae9d62793..cd2c8cb5a6e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLibrary.kt @@ -10,7 +10,10 @@ import org.gradle.api.Task import org.gradle.api.plugins.BasePlugin import org.gradle.api.plugins.ExtensionAware import org.gradle.language.base.plugins.LifecycleBasePlugin -import org.jetbrains.kotlin.gradle.dsl.* +import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerToolOptions +import org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions +import org.jetbrains.kotlin.gradle.dsl.KotlinNativeLibrary +import org.jetbrains.kotlin.gradle.dsl.KotlinNativeLibraryConfig import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind import org.jetbrains.kotlin.gradle.plugin.mpp.enabledOnCurrentHost diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt index fb1bb090847..49a6ae65750 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt @@ -20,16 +20,23 @@ import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.process.ExecOperations import org.gradle.work.DisableCachingByDefault +import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter +import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric +import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import org.jetbrains.kotlin.compilerRunner.KotlinNativeCompilerRunner import org.jetbrains.kotlin.compilerRunner.KotlinToolRunner +import org.jetbrains.kotlin.compilerRunner.addBuildMetricsForTaskAction import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode +import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter +import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService import org.jetbrains.kotlin.gradle.targets.native.tasks.buildKotlinNativeBinaryLinkerArgs import org.jetbrains.kotlin.gradle.tasks.KotlinToolTask import org.jetbrains.kotlin.gradle.utils.XcodeUtils import org.jetbrains.kotlin.gradle.utils.newInstance +import org.jetbrains.kotlin.gradle.utils.property import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.util.visibleName @@ -45,6 +52,7 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor( private val execOperations: ExecOperations, private val projectLayout: ProjectLayout ) : DefaultTask(), + UsesBuildMetricsService, KotlinToolTask { @get:Input @@ -163,6 +171,10 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor( destinationDir.asFile.get().resolve(outFileName) } + @get:Internal + val metrics: Property> = project.objects + .property(GradleBuildMetricsReporter()) + private val runnerSettings = KotlinNativeCompilerRunner.Settings.fromProject(project) init { @@ -183,36 +195,42 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor( @TaskAction fun link() { - val outFile = outputFile.get() - outFile.ensureParentDirsCreated() + val metricReporter = metrics.get() - fun FileCollection.klibs() = files.filter { it.extension == "klib" } + addBuildMetricsForTaskAction(metricsReporter = metricReporter, languageVersion = null) { - val buildArgs = buildKotlinNativeBinaryLinkerArgs( - outFile = outFile, - optimized = optimized.get(), - debuggable = debuggable.get(), - target = konanTarget, - outputKind = outputKind, - libraries = libraries.klibs(), - friendModules = emptyList(), //FriendModules aren't needed here because it's no test artifact - toolOptions = toolOptions, - compilerPlugins = emptyList(),//CompilerPlugins aren't needed here because it's no compilation but linking - processTests = processTests.get(), - entryPoint = entryPoint.getOrNull(), - embedBitcode = bitcodeEmbeddingMode(), - linkerOpts = linkerOptions.get(), - binaryOptions = allBinaryOptions.get(), - isStaticFramework = staticFramework.get(), - exportLibraries = exportLibraries.klibs(), - includeLibraries = includeLibraries.klibs(), - additionalOptions = emptyList()//todo support org.jetbrains.kotlin.gradle.tasks.CacheBuilder and org.jetbrains.kotlin.gradle.tasks.ExternalDependenciesBuilder - ) + val outFile = outputFile.get() + outFile.ensureParentDirsCreated() - KotlinNativeCompilerRunner( - settings = runnerSettings, - executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger) - ).run(buildArgs) + fun FileCollection.klibs() = files.filter { it.extension == "klib" } + + val buildArgs = buildKotlinNativeBinaryLinkerArgs( + outFile = outFile, + optimized = optimized.get(), + debuggable = debuggable.get(), + target = konanTarget, + outputKind = outputKind, + libraries = libraries.klibs(), + friendModules = emptyList(), //FriendModules aren't needed here because it's no test artifact + toolOptions = toolOptions, + compilerPlugins = emptyList(),//CompilerPlugins aren't needed here because it's no compilation but linking + processTests = processTests.get(), + entryPoint = entryPoint.getOrNull(), + embedBitcode = bitcodeEmbeddingMode(), + linkerOpts = linkerOptions.get(), + binaryOptions = allBinaryOptions.get(), + isStaticFramework = staticFramework.get(), + exportLibraries = exportLibraries.klibs(), + includeLibraries = includeLibraries.klibs(), + additionalOptions = emptyList()//todo support org.jetbrains.kotlin.gradle.tasks.CacheBuilder and org.jetbrains.kotlin.gradle.tasks.ExternalDependenciesBuilder + ) + + KotlinNativeCompilerRunner( + settings = runnerSettings, + executionContext = KotlinToolRunner.GradleExecutionContext.fromTaskContext(objectFactory, execOperations, logger), + metricReporter, + ).run(buildArgs) + } } private fun bitcodeEmbeddingMode(): BitcodeEmbeddingMode { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/AbstractKotlinCompileConfig.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/AbstractKotlinCompileConfig.kt index 576d44e8bb8..f8980faba71 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/AbstractKotlinCompileConfig.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/AbstractKotlinCompileConfig.kt @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.gradle.plugin.internal.BuildIdService import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget import org.jetbrains.kotlin.gradle.plugin.mpp.internal -import org.jetbrains.kotlin.gradle.report.BuildMetricsService import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile import org.jetbrains.kotlin.gradle.tasks.KOTLIN_BUILD_DIR_NAME import org.jetbrains.kotlin.gradle.utils.providerWithLazyConvention @@ -43,7 +42,6 @@ internal abstract class AbstractKotlinCompileConfig - task.buildMetricsService.value(metricsService).disallowChanges() - } task.systemPropertiesService.value(compilerSystemPropertiesService).disallowChanges() task.incrementalModuleInfoProvider.value(incrementalModuleInfoProvider).disallowChanges()