[Gradle] Make Kotlin Native tool runners GCC friendly
Remove project usage with either GradleExecutionContext or associated Settings class. Set of Setting classes are meant to be created upon configuration phase. Therefore, they have to be easily serializable without heavy payload. They also annotated for Input/Output checks. ^KT-43293
This commit is contained in:
+6
-1
@@ -34,6 +34,11 @@ abstract class KotlinToolRunner(
|
||||
val logger: Logger,
|
||||
) {
|
||||
companion object {
|
||||
/**
|
||||
* Executing [KotlinToolRunner] during Gradle Configuration Phase is undesired behaviour.
|
||||
* Currently only [KotlinNativeLibraryGenerationRunner] used in this way.
|
||||
* It should be fixed as part of KT-51255
|
||||
*/
|
||||
@Deprecated(
|
||||
"Building execution context from Project object isn't compatible with Gradle Configuration Cache",
|
||||
ReplaceWith("fromTaskContext()"),
|
||||
@@ -41,7 +46,7 @@ abstract class KotlinToolRunner(
|
||||
)
|
||||
fun fromProject(project: Project) = GradleExecutionContext(
|
||||
filesProvider = project::files,
|
||||
javaexec = project::javaexec,
|
||||
javaexec = { spec -> project.javaexec(spec) }, // project::javaexec won't work due to different Classloaders
|
||||
logger = project.logger
|
||||
)
|
||||
|
||||
|
||||
+94
-28
@@ -6,6 +6,10 @@
|
||||
package org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.Classpath
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Nested
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||
@@ -18,6 +22,7 @@ import org.jetbrains.kotlin.konan.properties.resolvablePropertyString
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.DependencyDirectories
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.util.*
|
||||
|
||||
@@ -45,10 +50,46 @@ internal fun Project.getKonanCacheKind(target: KonanTarget): NativeCacheKind {
|
||||
}
|
||||
}
|
||||
|
||||
private val Project.kotlinNativeCompilerJar: String
|
||||
get() = if (nativeUseEmbeddableCompilerJar)
|
||||
"$konanHome/konan/lib/kotlin-native-compiler-embeddable.jar"
|
||||
else
|
||||
"$konanHome/konan/lib/kotlin-native.jar"
|
||||
|
||||
internal abstract class KotlinNativeToolRunner(
|
||||
protected val toolName: String,
|
||||
project: Project
|
||||
) : KotlinToolRunner(project) {
|
||||
private val settings: Settings,
|
||||
executionContext: GradleExecutionContext
|
||||
) : KotlinToolRunner(executionContext) {
|
||||
|
||||
class Settings(
|
||||
@get:Input
|
||||
val konanVersion: CompilerVersion,
|
||||
@get:Input
|
||||
val konanHome: String,
|
||||
@get:InputFile
|
||||
val konanPropertiesFile: File,
|
||||
@get:Input
|
||||
val jvmArgs: List<String>,
|
||||
classpathProvider: () -> Set<File>,
|
||||
) {
|
||||
@get:Classpath
|
||||
val classpath by lazy(classpathProvider)
|
||||
|
||||
constructor(project: Project) : this(
|
||||
konanVersion = project.konanVersion,
|
||||
konanHome = project.konanHome,
|
||||
konanPropertiesFile = project.file("${project.konanHome}/konan/konan.properties"),
|
||||
jvmArgs = project.jvmArgs,
|
||||
classpathProvider = {
|
||||
project.files(
|
||||
project.kotlinNativeCompilerJar,
|
||||
"${project.konanHome}/konan/lib/trove4j.jar"
|
||||
).files
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
final override val displayName get() = toolName
|
||||
|
||||
final override val mainClass get() = "org.jetbrains.kotlin.cli.utilities.MainKt"
|
||||
@@ -65,29 +106,18 @@ internal abstract class KotlinNativeToolRunner(
|
||||
|
||||
final override val execSystemProperties by lazy {
|
||||
// Still set konan.home for versions prior to 1.4-M3.
|
||||
val konanHomeRequired = project.konanVersion.let {
|
||||
val konanHomeRequired = settings.konanVersion.let {
|
||||
!it.isAtLeast(1, 4, 0) ||
|
||||
it.toString(showMeta = false, showBuild = false) in listOf("1.4-M1", "1.4-M2")
|
||||
}
|
||||
|
||||
listOfNotNull(
|
||||
if (konanHomeRequired) "konan.home" to project.konanHome else null,
|
||||
if (konanHomeRequired) "konan.home" to settings.konanHome else null,
|
||||
MessageRenderer.PROPERTY_KEY to MessageRenderer.GRADLE_STYLE.name
|
||||
).toMap()
|
||||
}
|
||||
|
||||
final override val classpath by lazy {
|
||||
project.files(
|
||||
project.kotlinNativeCompilerJar,
|
||||
"${project.konanHome}/konan/lib/trove4j.jar"
|
||||
).files
|
||||
}
|
||||
|
||||
private val Project.kotlinNativeCompilerJar: String
|
||||
get() = if (nativeUseEmbeddableCompilerJar)
|
||||
"$konanHome/konan/lib/kotlin-native-compiler-embeddable.jar"
|
||||
else
|
||||
"$konanHome/konan/lib/kotlin-native.jar"
|
||||
final override val classpath get() = settings.classpath
|
||||
|
||||
final override fun checkClasspath() =
|
||||
check(classpath.isNotEmpty()) {
|
||||
@@ -98,18 +128,23 @@ internal abstract class KotlinNativeToolRunner(
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
data class IsolatedClassLoaderCacheKey(val classpath: Set<java.io.File>)
|
||||
data class IsolatedClassLoaderCacheKey(val classpath: Set<File>)
|
||||
|
||||
// TODO: can't we use this for other implementations too?
|
||||
final override val isolatedClassLoaderCacheKey get() = IsolatedClassLoaderCacheKey(classpath)
|
||||
|
||||
override fun transformArgs(args: List<String>) = listOf(toolName) + args
|
||||
|
||||
final override fun getCustomJvmArgs() = project.jvmArgs
|
||||
final override fun getCustomJvmArgs() = settings.jvmArgs
|
||||
}
|
||||
|
||||
/** A common ancestor for all runners that run the cinterop tool. */
|
||||
internal abstract class AbstractKotlinNativeCInteropRunner(toolName: String, project: Project) : KotlinNativeToolRunner(toolName, project) {
|
||||
internal abstract class AbstractKotlinNativeCInteropRunner(
|
||||
toolName: String,
|
||||
settings: Settings,
|
||||
executionContext: GradleExecutionContext
|
||||
) : KotlinNativeToolRunner(toolName, settings, executionContext) {
|
||||
|
||||
override val mustRunViaExec get() = true
|
||||
|
||||
override val execEnvironment by lazy {
|
||||
@@ -126,7 +161,7 @@ internal abstract class AbstractKotlinNativeCInteropRunner(toolName: String, pro
|
||||
if (HostManager.host == KonanTarget.MINGW_X64) {
|
||||
// TODO: Read it from Platform properties when it is accessible.
|
||||
val konanProperties = Properties().apply {
|
||||
project.file("${project.konanHome}/konan/konan.properties").inputStream().use(::load)
|
||||
settings.konanPropertiesFile.inputStream().use(::load)
|
||||
}
|
||||
|
||||
konanProperties.resolvablePropertyString("llvmHome.mingw_x64")?.let { toolchainDir ->
|
||||
@@ -140,25 +175,47 @@ internal abstract class AbstractKotlinNativeCInteropRunner(toolName: String, pro
|
||||
}
|
||||
|
||||
/** Kotlin/Native C-interop tool runner */
|
||||
internal class KotlinNativeCInteropRunner private constructor(project: Project) : AbstractKotlinNativeCInteropRunner("cinterop", project) {
|
||||
internal class KotlinNativeCInteropRunner
|
||||
private constructor(
|
||||
private val settings: Settings,
|
||||
gradleExecutionContext: GradleExecutionContext,
|
||||
) : AbstractKotlinNativeCInteropRunner("cinterop", settings, gradleExecutionContext) {
|
||||
|
||||
interface ExecutionContext {
|
||||
val project: Project
|
||||
val runnerSettings: Settings
|
||||
val gradleExecutionContext: GradleExecutionContext
|
||||
fun runWithContext(action: () -> Unit)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun ExecutionContext.run(args: List<String>) {
|
||||
val runner = KotlinNativeCInteropRunner(project)
|
||||
val runner = KotlinNativeCInteropRunner(runnerSettings, gradleExecutionContext)
|
||||
runWithContext { runner.run(args) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Kotlin/Native compiler runner */
|
||||
internal class KotlinNativeCompilerRunner(project: Project) : KotlinNativeToolRunner("konanc", project) {
|
||||
private val useArgFile get() = project.disableKonanDaemon
|
||||
internal class KotlinNativeCompilerRunner(
|
||||
private val settings: Settings,
|
||||
executionContext: GradleExecutionContext
|
||||
) : KotlinNativeToolRunner("konanc", settings.parent, executionContext) {
|
||||
class Settings(
|
||||
@get:Nested
|
||||
val parent: KotlinNativeToolRunner.Settings,
|
||||
|
||||
override val mustRunViaExec get() = project.disableKonanDaemon
|
||||
@get:Input
|
||||
val disableKonanDaemon: Boolean,
|
||||
) {
|
||||
constructor(project: Project) : this(
|
||||
parent = KotlinNativeToolRunner.Settings(project),
|
||||
disableKonanDaemon = project.disableKonanDaemon,
|
||||
)
|
||||
}
|
||||
|
||||
private val useArgFile get() = settings.disableKonanDaemon
|
||||
|
||||
override val mustRunViaExec get() = settings.disableKonanDaemon
|
||||
|
||||
override fun transformArgs(args: List<String>): List<String> {
|
||||
if (!useArgFile) return super.transformArgs(args)
|
||||
@@ -178,8 +235,17 @@ internal class KotlinNativeCompilerRunner(project: Project) : KotlinNativeToolRu
|
||||
}
|
||||
|
||||
/** Platform libraries generation tool. Runs the cinterop tool under the hood. */
|
||||
internal class KotlinNativeLibraryGenerationRunner(project: Project) :
|
||||
AbstractKotlinNativeCInteropRunner("generatePlatformLibraries", project) {
|
||||
internal class KotlinNativeLibraryGenerationRunner(
|
||||
private val settings: Settings,
|
||||
executionContext: GradleExecutionContext
|
||||
) :
|
||||
AbstractKotlinNativeCInteropRunner("generatePlatformLibraries", settings, executionContext) {
|
||||
|
||||
constructor(project: Project): this(
|
||||
settings = Settings(project),
|
||||
executionContext = GradleExecutionContext.fromProject(project)
|
||||
)
|
||||
|
||||
// The library generator works for a long time so enabling C2 can improve performance.
|
||||
override val disableC2: Boolean = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user