From e8040fcf77e69a95ad7cae9c3ea481d3cb4276eb Mon Sep 17 00:00:00 2001 From: Anton Lakotka Date: Mon, 23 May 2022 11:56:28 +0200 Subject: [PATCH] [Gradle] Replace project with GradleExecutionContext in KotlinToolRunner Gradle Project cannot be used during Task Execution Phase with enabled Configuration Cache. This change allows to avoid using Project. ^KT-43293 --- .../kotlin/compilerRunner/KotlinToolRunner.kt | 49 +++++++++++++++++-- 1 file changed, 44 insertions(+), 5 deletions(-) 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 6492bc13c17..5b03aaf7465 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 @@ -7,6 +7,12 @@ package org.jetbrains.kotlin.compilerRunner import com.intellij.openapi.util.text.StringUtil.escapeStringCharacters import org.gradle.api.Project +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.logging.Logger +import org.gradle.api.model.ObjectFactory +import org.gradle.process.ExecOperations +import org.gradle.process.ExecResult +import org.gradle.process.JavaExecSpec import org.gradle.util.GradleVersion import org.jetbrains.kotlin.konan.target.HostManager import java.io.File @@ -17,8 +23,41 @@ import java.util.concurrent.ConcurrentHashMap // Note: this class is public because it is used in the K/N build infrastructure. abstract class KotlinToolRunner( - val project: Project + private val executionContext: GradleExecutionContext ) { + /** + * Context Services that are required for [KotlinToolRunner] during Gradle Task Execution Phase + */ + class GradleExecutionContext( + val filesProvider: (Any) -> ConfigurableFileCollection, + val javaexec: ((JavaExecSpec) -> Unit) -> ExecResult, + val logger: Logger, + ) { + companion object { + @Deprecated( + "Building execution context from Project object isn't compatible with Gradle Configuration Cache", + ReplaceWith("fromTaskContext()"), + DeprecationLevel.WARNING + ) + fun fromProject(project: Project) = GradleExecutionContext( + filesProvider = project::files, + javaexec = project::javaexec, + logger = project.logger + ) + + /** Gradle Configuration Cache friendly context, should be used inside Task Execution Phase */ + fun fromTaskContext( + objectFactory: ObjectFactory, + execOperations: ExecOperations, + logger: Logger + ) = GradleExecutionContext( + filesProvider = objectFactory.fileCollection()::from, + javaexec = execOperations::javaexec, + logger = logger + ) + } + } + // name that will be used in logs abstract val displayName: String @@ -84,7 +123,7 @@ abstract class KotlinToolRunner( private fun runViaExec(args: List) { val transformedArgs = transformArgs(args) - val classpath = project.files(classpath) + val classpath = executionContext.filesProvider(classpath) val systemProperties = System.getProperties() /* Capture 'System.getProperties()' as List to avoid potential 'ConcurrentModificationException' */ .toListSynchronized() @@ -94,7 +133,7 @@ abstract class KotlinToolRunner( .escapeQuotesForWindows() .toMap() + execSystemProperties - project.logger.info( + executionContext.logger.info( """|Run "$displayName" tool in a separate JVM process |Main class = $mainClass |Arguments = ${args.toPrettyString()} @@ -107,7 +146,7 @@ abstract class KotlinToolRunner( """.trimMargin() ) - project.javaexec { spec -> + executionContext.javaexec { spec -> @Suppress("DEPRECATION") if (GradleVersion.current() >= GradleVersion.version("7.0")) spec.mainClass.set(mainClass) else spec.main = mainClass @@ -124,7 +163,7 @@ abstract class KotlinToolRunner( val transformedArgs = transformArgs(args) val isolatedClassLoader = getIsolatedClassLoader() - project.logger.info( + executionContext.logger.info( """|Run in-process tool "$displayName" |Entry point method = $mainClass.$daemonEntryPoint |Classpath = ${isolatedClassLoader.urLs.map { it.file }.toPrettyString()}