[BT] Implement basic non-incremental in-process JVM compilation

This commit is contained in:
Alexander.Likhachev
2023-06-27 22:43:48 +02:00
committed by Space Team
parent 6356a40fe8
commit 28c059f25b
8 changed files with 186 additions and 28 deletions
@@ -20,7 +20,6 @@ class BuildToolsApiJvmCompilationIT : KGPBaseTest() {
override val defaultBuildOptions = super.defaultBuildOptions.copy(runViaBuildToolsApi = true)
@GradleTest
@Disabled
@DisplayName("Simple project non-incremental in-process compilation")
fun compileJvmInProcessNonIncremental(gradleVersion: GradleVersion) = testSimpleProject(
gradleVersion, defaultBuildOptions.copy(
@@ -13,12 +13,18 @@ import org.gradle.workers.WorkParameters
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.CompilationService
import org.jetbrains.kotlin.buildtools.api.ExperimentalBuildToolsApi
import org.jetbrains.kotlin.buildtools.api.SharedApiClassesClassLoader
import org.jetbrains.kotlin.buildtools.api.*
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWorkArguments
import org.jetbrains.kotlin.compilerRunner.asFinishLogMessage
import org.jetbrains.kotlin.gradle.internal.ClassLoadersCachingBuildService
import org.jetbrains.kotlin.gradle.internal.ParentClassLoaderProvider
import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
import org.jetbrains.kotlin.gradle.logging.SL4JKotlinLogger
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy
import org.jetbrains.kotlin.gradle.tasks.throwExceptionIfCompilationFailed
import org.slf4j.LoggerFactory
import java.io.File
@OptIn(ExperimentalBuildToolsApi::class)
@@ -35,21 +41,57 @@ internal abstract class BuildToolsApiCompilationWork : WorkAction<BuildToolsApiC
private val workArguments
get() = parameters.compilerWorkArguments.get()
override fun execute() {
val classLoader = parameters.classLoadersCachingService.get()
.getClassLoader(workArguments.compilerFullClasspath, SharedApiClassesClassLoaderProvider)
val compilationService = CompilationService.loadImplementation(classLoader)
val executionConfig = compilationService.makeCompilerExecutionStrategyConfiguration().apply {
useInProcessStrategy()
}
val jvmCompilationConfig = compilationService.makeJvmCompilationConfiguration()
compilationService.compileJvm(
executionConfig,
jvmCompilationConfig,
emptyList(),
emptyList(),
)
private val taskPath
get() = workArguments.taskPath
private val log: KotlinLogger by lazy(LazyThreadSafetyMode.NONE) {
TaskLoggers.get(taskPath)?.let { GradleKotlinLogger(it).apply { debug("Using '$taskPath' logger") } }
?: run {
val logger = LoggerFactory.getLogger("GradleKotlinCompilerWork")
val kotlinLogger = if (logger is org.gradle.api.logging.Logger) {
GradleKotlinLogger(logger)
} else SL4JKotlinLogger(logger)
kotlinLogger.apply {
debug("Could not get logger for '$taskPath'. Falling back to sl4j logger")
}
}
}
override fun execute() {
val executionStrategy = workArguments.compilerExecutionSettings.strategy
try {
val classLoader = parameters.classLoadersCachingService.get()
.getClassLoader(workArguments.compilerFullClasspath, SharedApiClassesClassLoaderProvider)
val compilationService = CompilationService.loadImplementation(classLoader)
val executionConfig = compilationService.makeCompilerExecutionStrategyConfiguration().apply {
when (executionStrategy) {
KotlinCompilerExecutionStrategy.DAEMON -> TODO("The daemon strategy is not yet supported in the Build Tools API")
KotlinCompilerExecutionStrategy.IN_PROCESS -> useInProcessStrategy()
else -> error("The \"$executionStrategy\" execution strategy is not supported by the Build Tools API")
}
}
val jvmCompilationConfig = compilationService.makeJvmCompilationConfiguration()
val result = compilationService.compileJvm(
executionConfig,
jvmCompilationConfig,
emptyList(),
workArguments.compilerArgs.toList(),
)
throwExceptionIfCompilationFailed(result.asExitCode, executionStrategy)
} finally {
log.info(executionStrategy.asFinishLogMessage)
}
}
// temporary adapter property
private val CompilationResult.asExitCode
get() = when (this) {
CompilationResult.COMPILATION_ERROR -> ExitCode.COMPILATION_ERROR
CompilationResult.COMPILER_INTERNAL_ERROR -> ExitCode.INTERNAL_ERROR
CompilationResult.COMPILATION_OOM_ERROR -> ExitCode.OOM_ERROR
else -> ExitCode.OK
}
}
@OptIn(ExperimentalBuildToolsApi::class)