[Gradle] Add GradleBuildToolsApiCompilerRunner

It could be enabled via the `kotlin.compiler.runViaBuildToolsApi` Gradle property globally or the `AbstractKotlinCompileTool.runViaBuildToolsApi` task property for a particular task
#KT-57397 In Progress
This commit is contained in:
Alexander.Likhachev
2023-03-17 15:48:28 +01:00
committed by Space Team
parent 9127919e01
commit 3b69a4c770
14 changed files with 143 additions and 5 deletions
@@ -65,6 +65,7 @@ dependencies {
commonImplementation(project(":kotlin-util-klib"))
commonImplementation(project(":native:kotlin-klib-commonizer-api"))
commonImplementation(project(":kotlin-project-model"))
commonImplementation(project(":compiler:build-tools:build-tools-api"))
commonRuntimeOnly(project(":kotlin-compiler-embeddable"))
commonRuntimeOnly(project(":kotlin-annotation-processing-embeddable"))
@@ -12,12 +12,14 @@ import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.api.tasks.bundling.Zip
import org.gradle.jvm.tasks.Jar
import org.gradle.workers.WorkQueue
import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
import org.jetbrains.kotlin.build.report.metrics.BuildPerformanceMetric
import org.jetbrains.kotlin.build.report.metrics.BuildTime
import org.jetbrains.kotlin.build.report.metrics.measure
import org.jetbrains.kotlin.cli.common.arguments.*
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.compilerRunner.btapi.GradleBuildToolsApiCompilerRunner
import org.jetbrains.kotlin.daemon.client.CompileServiceSession
import org.jetbrains.kotlin.daemon.common.CompilerId
import org.jetbrains.kotlin.daemon.common.configureDaemonJVMOptions
@@ -52,6 +54,33 @@ const val EXISTING_SESSION_FILE_PREFIX = "Existing session-is-alive flag file: "
const val DELETED_SESSION_FILE_PREFIX = "Deleted session-is-alive flag file: "
const val COULD_NOT_CONNECT_TO_DAEMON_MESSAGE = "Could not connect to Kotlin compile daemon"
internal fun createGradleCompilerRunner(
taskProvider: GradleCompileTaskProvider,
toolsJar: File?,
compilerExecutionSettings: CompilerExecutionSettings,
buildMetricsReporter: BuildMetricsReporter,
workerExecutor: WorkerExecutor,
runViaBuildToolsApi: Boolean
): GradleCompilerRunner {
return if (runViaBuildToolsApi) {
GradleBuildToolsApiCompilerRunner(
taskProvider,
toolsJar,
compilerExecutionSettings,
buildMetricsReporter,
workerExecutor,
)
} else {
GradleCompilerRunnerWithWorkers(
taskProvider,
toolsJar,
compilerExecutionSettings,
buildMetricsReporter,
workerExecutor,
)
}
}
/*
Using real taskProvider cause "field 'taskProvider' from type 'org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner':
value 'fixed(class org.jetbrains.kotlin.gradle.tasks.KotlinCompile_Decorated, task ':compileKotlin')'
@@ -0,0 +1,32 @@
/*
* 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.btapi
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters
import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
import org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWorkArguments
import java.io.File
internal abstract class BuildToolsApiCompilationWork : WorkAction<BuildToolsApiCompilationWork.BuildToolsApiCompilationParameters> {
internal interface BuildToolsApiCompilationParameters : WorkParameters {
val compilerWorkArguments: Property<GradleKotlinCompilerWorkArguments>
val taskOutputsToRestore: ListProperty<File>
val snapshotsDir: DirectoryProperty
val buildDir: DirectoryProperty
val metricsReporter: Property<BuildMetricsReporter>
}
private val workArguments
get() = parameters.compilerWorkArguments.get()
override fun execute() {
println("I'm simulating compilation, the compilation classpath would be ${workArguments.compilerFullClasspath}")
}
}
@@ -0,0 +1,44 @@
/*
* 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.btapi
import org.gradle.workers.WorkQueue
import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
import org.jetbrains.kotlin.build.report.metrics.BuildPerformanceMetric
import org.jetbrains.kotlin.compilerRunner.CompilerExecutionSettings
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
import org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWorkArguments
import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider
import org.jetbrains.kotlin.gradle.tasks.TaskOutputsBackup
import java.io.File
internal class GradleBuildToolsApiCompilerRunner(
taskProvider: GradleCompileTaskProvider,
jdkToolsJar: File?,
compilerExecutionSettings: CompilerExecutionSettings,
buildMetrics: BuildMetricsReporter,
private val workerExecutor: WorkerExecutor
) : GradleCompilerRunner(taskProvider, jdkToolsJar, compilerExecutionSettings, buildMetrics) {
override fun runCompilerAsync(
workArgs: GradleKotlinCompilerWorkArguments,
taskOutputsBackup: TaskOutputsBackup?
): WorkQueue {
buildMetrics.addTimeMetric(BuildPerformanceMetric.CALL_WORKER)
val workQueue = workerExecutor.noIsolation()
workQueue.submit(BuildToolsApiCompilationWork::class.java) { params ->
params.compilerWorkArguments.set(workArgs)
if (taskOutputsBackup != null) {
params.taskOutputsToRestore.set(taskOutputsBackup.outputsToRestore)
params.buildDir.set(taskOutputsBackup.buildDirectory)
params.snapshotsDir.set(taskOutputsBackup.snapshotsDir)
params.metricsReporter.set(buildMetrics)
}
}
return workQueue
}
}
@@ -13,6 +13,8 @@ import org.gradle.api.internal.plugins.DslObject
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.jvm.toolchain.JavaToolchainSpec
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.internal.KOTLIN_BUILD_TOOLS_API_IMPL
import org.jetbrains.kotlin.gradle.internal.KOTLIN_MODULE_GROUP
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.gradle.utils.withType
internal const val KOTLIN_MODULE_GROUP = "org.jetbrains.kotlin"
internal const val KOTLIN_COMPILER_EMBEDDABLE = "kotlin-compiler-embeddable"
internal const val KOTLIN_BUILD_TOOLS_API_IMPL = "build-tools-impl"
internal const val PLATFORM_INTEGERS_SUPPORT_LIBRARY = "platform-integers"
internal fun customizeKotlinDependencies(project: Project) {
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.gradle.tasks.*
const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath"
const val NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinNativeCompilerPluginClasspath"
internal const val COMPILER_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerClasspath"
internal const val BUILD_TOOLS_API_CLASSPATH_CONFIGURATION_NAME = "kotlinBuildToolsApiClasspath"
internal const val KLIB_COMMONIZER_CLASSPATH_CONFIGURATION_NAME = "kotlinKlibCommonizerClasspath"
const val KOTLIN_DSL_NAME = "kotlin"
@@ -27,6 +27,7 @@ import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import org.jetbrains.kotlin.compilerRunner.maybeCreateCommonizerClasspathConfiguration
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.internal.KOTLIN_BUILD_TOOLS_API_IMPL
import org.jetbrains.kotlin.gradle.internal.KOTLIN_COMPILER_EMBEDDABLE
import org.jetbrains.kotlin.gradle.internal.KOTLIN_MODULE_GROUP
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
@@ -116,12 +117,27 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin {
project.dependencies.create("$KOTLIN_MODULE_GROUP:$KOTLIN_COMPILER_EMBEDDABLE:${project.getKotlinPluginVersion()}")
)
}
project
.configurations
.maybeCreate(BUILD_TOOLS_API_CLASSPATH_CONFIGURATION_NAME)
.markResolvable()
.defaultDependencies {
it.add(
project.dependencies.create("$KOTLIN_MODULE_GROUP:$KOTLIN_BUILD_TOOLS_API_IMPL:${project.getKotlinPluginVersion()}")
)
}
project
.tasks
.withType(AbstractKotlinCompileTool::class.java)
.configureEach { task ->
task.defaultCompilerClasspath.setFrom(
project.configurations.named(COMPILER_CLASSPATH_CONFIGURATION_NAME)
{
val classpathConfiguration = when (task.runViaBuildToolsApi.get()) {
true -> BUILD_TOOLS_API_CLASSPATH_CONFIGURATION_NAME
false -> COMPILER_CLASSPATH_CONFIGURATION_NAME
}
project.configurations.named(classpathConfiguration)
}
)
}
}
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLI
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_IMPORT_ENABLE_SLOW_SOURCES_JAR_RESOLVER
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_DEPENDENCY_PROPAGATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_USE_XCODE_MESSAGE_STYLE
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_RUN_COMPILER_VIA_BUILD_TOOLS_API
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_STDLIB_DEFAULT_DEPENDENCY
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_STDLIB_JDK_VARIANTS_VERSION_ALIGNMENT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_SUPPRESS_EXPERIMENTAL_IC_OPTIMIZATIONS_WARNING
@@ -513,6 +514,9 @@ internal class PropertiesProvider private constructor(private val project: Proje
val createDefaultMultiplatformPublications: Boolean
get() = booleanProperty(KOTLIN_CREATE_DEFAULT_MULTIPLATFORM_PUBLICATIONS) ?: true
val runKotlinCompilerViaBuildToolsApi: Boolean
get() = booleanProperty(KOTLIN_RUN_COMPILER_VIA_BUILD_TOOLS_API) ?: false
/**
* Retrieves a comma-separated list of browsers to use when running karma tests for [target]
* @see KOTLIN_JS_KARMA_BROWSERS
@@ -599,6 +603,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
const val KOTLIN_COMPILER_KEEP_INCREMENTAL_COMPILATION_CACHES_IN_MEMORY = "kotlin.compiler.keepIncrementalCompilationCachesInMemory"
const val KOTLIN_SUPPRESS_EXPERIMENTAL_IC_OPTIMIZATIONS_WARNING = "kotlin.compiler.suppressExperimentalICOptimizationsWarning"
const val KOTLIN_CREATE_DEFAULT_MULTIPLATFORM_PUBLICATIONS = "kotlin.internal.mpp.createDefaultMultiplatformPublications"
const val KOTLIN_RUN_COMPILER_VIA_BUILD_TOOLS_API = "kotlin.compiler.runViaBuildToolsApi"
}
companion object {
@@ -342,7 +342,7 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) :
?: compilation.npmProject.dir.resolve(if (dev) DCE_DEV_DIR else DCE_DIR)
)
it.defaultCompilerClasspath.setFrom(project.configurations.named(COMPILER_CLASSPATH_CONFIGURATION_NAME))
it.runViaBuildToolsApi.value(false).disallowChanges() // The legacy backend task is not going to be supported
it.setSource(kotlinTask.map { it.outputFileProperty })
}
}
@@ -73,6 +73,7 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
it.usesService(konanPropertiesBuildService)
it.toolOptions.freeCompilerArgs.value(compilationCompilerOptions.options.freeCompilerArgs)
it.toolOptions.freeCompilerArgs.addAll(providers.provider { PropertiesProvider(project).nativeLinkArgs })
it.runViaBuildToolsApi.value(false).disallowChanges() // K/N is not yet supported
}
@@ -398,6 +399,7 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
it.compilerOptions.useK2.set(true)
}
it.compilerOptions.useK2.disallowChanges()
it.runViaBuildToolsApi.value(false).disallowChanges() // K/N is not yet supported
}
compilationInfo.classesDirs.from(compileTaskProvider.map { it.outputFile })
@@ -27,8 +27,8 @@ import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.compilerRunner.CompilerExecutionSettings
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers
import org.jetbrains.kotlin.compilerRunner.UsesCompilerSystemPropertiesService
import org.jetbrains.kotlin.compilerRunner.createGradleCompilerRunner
import org.jetbrains.kotlin.daemon.common.MultiModuleICSettings
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
import org.jetbrains.kotlin.gradle.incremental.UsesIncrementalModuleInfoBuildService
@@ -173,7 +173,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constr
defaultKotlinJavaToolchain
.map {
val toolsJar = it.currentJvmJdkToolsJar.orNull
GradleCompilerRunnerWithWorkers(
createGradleCompilerRunner(
taskProvider,
toolsJar,
CompilerExecutionSettings(
@@ -182,7 +182,8 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constr
useDaemonFallbackStrategy.get()
),
params.first,
workerExecutor
workerExecutor,
runViaBuildToolsApi.get(),
)
}
}
@@ -122,6 +122,9 @@ abstract class AbstractKotlinCompileTool<T : CommonToolArguments> @Inject constr
internal val defaultCompilerClasspath: ConfigurableFileCollection =
project.objects.fileCollection()
@get:Internal
internal abstract val runViaBuildToolsApi: Property<Boolean>
protected fun validateCompilerClasspath() {
// Note that the check triggers configuration resolution
require(!defaultCompilerClasspath.isEmpty) {
@@ -122,6 +122,7 @@ internal abstract class AbstractKotlinCompileConfig<TASK : AbstractKotlinCompile
if (propertiesProvider.useK2 == true) {
task.compilerOptions.useK2.value(true)
}
task.runViaBuildToolsApi.convention(propertiesProvider.runKotlinCompilerViaBuildToolsApi).finalizeValueOnRead()
}
}