From ed881f3f3124dce8026fd5694ed1e58d2dd5f80f Mon Sep 17 00:00:00 2001 From: Alexander Shabalin Date: Mon, 30 May 2022 15:52:08 +0000 Subject: [PATCH] [K/N] Make PlatformManager serializable Merge-request: KT-MR-6358 Merged-by: Alexander Shabalin --- .../kotlin/org/jetbrains/kotlin/ExecClang.kt | 10 +++--- .../kotlin/org/jetbrains/kotlin/ExecLlvm.kt | 10 ++++++ .../kotlin/bitcode/CompileToBitcode.kt | 18 ++++------ .../kotlin/testing/native/NativeTest.kt | 31 ++++++++--------- .../jetbrains/kotlin/konan/target/Platform.kt | 22 +++++++++++-- .../kotlin/konan/target/Distribution.kt | 33 +++++++++++++++---- 6 files changed, 80 insertions(+), 44 deletions(-) diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecClang.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecClang.kt index 013fac5f18a..71b437c4eca 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecClang.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecClang.kt @@ -33,8 +33,7 @@ import javax.inject.Inject abstract class ExecClang @Inject constructor( private val platformManager: PlatformManager, - private val llvmDir: File - ) { +) { @get:Inject protected abstract val fileOperations: FileOperations @@ -54,7 +53,7 @@ abstract class ExecClang @Inject constructor( val executable = executableOrNull ?: "clang" if (listOf("clang", "clang++").contains(executable)) { - return "${llvmDir.absolutePath}/bin/$executable" + return "${platformManager.hostPlatform.absoluteLlvmHome}/bin/$executable" } else { throw GradleException("unsupported clang executable: $executable") } @@ -146,11 +145,10 @@ abstract class ExecClang @Inject constructor( fun create(project: Project): ExecClang = create( project.objects, project.project(":kotlin-native").findProperty("platformManager") as PlatformManager, - project.file(project.findProperty("llvmDir")!!) ) @JvmStatic - fun create(objects: ObjectFactory, platformManager: PlatformManager, llvmDir: File) = - objects.newInstance(ExecClang::class.java, platformManager, llvmDir) + fun create(objects: ObjectFactory, platformManager: PlatformManager) = + objects.newInstance(ExecClang::class.java, platformManager) } } diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecLlvm.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecLlvm.kt index 04c94a418ea..4f4ee78f478 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecLlvm.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecLlvm.kt @@ -8,8 +8,10 @@ package org.jetbrains.kotlin import groovy.lang.Closure import org.gradle.api.Action import org.gradle.api.Project +import org.gradle.process.ExecOperations import org.gradle.process.ExecResult import org.gradle.process.ExecSpec +import org.jetbrains.kotlin.konan.target.PlatformManager import org.jetbrains.kotlin.konan.util.DependencyProcessor fun execLlvmUtility(project: Project, utility: String, action: Action): ExecResult { @@ -23,3 +25,11 @@ fun execLlvmUtility(project: Project, utility: String, action: Action): ExecResult { return execLlvmUtility(project, utility) { project.configure(this, closure) } } + +fun ExecOperations.execLlvmUtility(platformManager: PlatformManager, utility: String, action: Action): ExecResult { + val llvmBinDirectory = "${platformManager.hostPlatform.absoluteLlvmHome}/bin" + return exec { + action.execute(this) + executable = "$llvmBinDirectory/$utility" + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt index ac9cd51b4f7..2a942ec679c 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt @@ -15,11 +15,14 @@ import javax.inject.Inject import kotlinBuildProperties import org.gradle.api.Project import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property import org.gradle.process.ExecOperations import org.gradle.workers.WorkAction import org.gradle.workers.WorkParameters import org.gradle.workers.WorkerExecutor +import org.jetbrains.kotlin.execLlvmUtility import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.platformManager interface CompileToBitcodeParameters : WorkParameters { var objDir: File @@ -27,10 +30,7 @@ interface CompileToBitcodeParameters : WorkParameters { var compilerExecutable: String var compilerArgs: List var llvmLinkArgs: List - - var konanHome: File - var llvmDir: File - var experimentalDistribution: Boolean + val platformManager: Property } abstract class CompileToBitcodeJob : WorkAction { @@ -44,8 +44,7 @@ abstract class CompileToBitcodeJob : WorkAction { with(parameters) { objDir.mkdirs() - val platformManager = PlatformManager(buildDistribution(konanHome.absolutePath), experimentalDistribution) - val execClang = ExecClang.create(objects, platformManager, llvmDir) + val execClang = ExecClang.create(objects, platformManager.get()) execClang.execKonanClang(target) { workingDir = objDir @@ -53,8 +52,7 @@ abstract class CompileToBitcodeJob : WorkAction { args = compilerArgs } - execOperations.exec { - executable = "${llvmDir.absolutePath}/bin/llvm-link" + execOperations.execLlvmUtility(platformManager.get(), "llvm-link") { args = llvmLinkArgs } } @@ -234,9 +232,7 @@ abstract class CompileToBitcode @Inject constructor( inputFiles.map { bitcodeFileForInputFile(it).absolutePath } - - it.konanHome = project.project(":kotlin-native").projectDir - it.llvmDir = project.file(project.findProperty("llvmDir")!!) + it.platformManager.set(project.platformManager) } workQueue.submit(CompileToBitcodeJob::class.java, parameters) diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/NativeTest.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/NativeTest.kt index 6421882d211..513763953f4 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/NativeTest.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/NativeTest.kt @@ -10,13 +10,16 @@ import java.io.File import javax.inject.Inject import org.gradle.api.* import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.logging.Logging import org.gradle.api.tasks.* import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property import org.gradle.process.ExecOperations import org.gradle.workers.WorkAction import org.gradle.workers.WorkParameters import org.gradle.workers.WorkerExecutor import org.jetbrains.kotlin.ExecClang +import org.jetbrains.kotlin.execLlvmUtility import org.jetbrains.kotlin.konan.target.* import java.io.OutputStream @@ -28,11 +31,7 @@ interface CompileNativeTestParameters : WorkParameters { var targetName: String var compilerArgs: List var linkCommands: List> - - var konanHome: File - var llvmDir: File - var experimentalDistribution: Boolean - var isInfoEnabled: Boolean + val platformManager: Property } abstract class CompileNativeTestJob : WorkAction { @@ -55,13 +54,11 @@ abstract class CompileNativeTestJob : WorkAction { // errors at the link stage. So we have to run llvm-link twice: the first one links all modules // except the one containing the entry point to a single *.bc without internalization. The second // run internalizes this big module and links it with a module containing the entry point. - execOperations.exec { - executable = "$llvmDir/bin/llvm-link" + execOperations.execLlvmUtility(platformManager.get(), "llvm-link") { args = listOf("-o", tmpOutput.absolutePath) + inputFiles.map { it.absolutePath } } - execOperations.exec { - executable = "$llvmDir/bin/llvm-link" + execOperations.execLlvmUtility(platformManager.get(), "llvm-link") { args = listOf( "-o", llvmLinkOutputFile.absolutePath, mainFile.absolutePath, @@ -74,11 +71,10 @@ abstract class CompileNativeTestJob : WorkAction { private fun compile() { with(parameters) { - val platformManager = PlatformManager(buildDistribution(konanHome.absolutePath), experimentalDistribution) - val execClang = ExecClang.create(objects, platformManager, llvmDir) - val target = platformManager.targetByName(targetName) + val execClang = ExecClang.create(objects, platformManager.get()) + val target = platformManager.get().targetByName(targetName) - val clangFlags = buildClangFlags(platformManager.platform(target).configurables) + val clangFlags = buildClangFlags(platformManager.get().platform(target).configurables) if (target.family.isAppleFamily) { execClang.execToolchainClang(target) { @@ -95,11 +91,13 @@ abstract class CompileNativeTestJob : WorkAction { } private fun link() { + val logging = Logging.getLogger(CompileNativeTestJob::class.java) + with(parameters) { for (command in linkCommands) { execOperations.exec { commandLine(command) - if (!isInfoEnabled && command[0].endsWith("dsymutil")) { + if (!logging.isInfoEnabled && command[0].endsWith("dsymutil")) { // Suppress dsymutl's warnings. // See: https://bugs.swift.org/browse/SR-11539. val nullOutputStream = object: OutputStream() { @@ -197,10 +195,7 @@ abstract class CompileNativeTest @Inject constructor( it.targetName = target.name it.compilerArgs = clangArgs + sanitizerFlags it.linkCommands = linkCommands - - it.konanHome = project.project(":kotlin-native").projectDir - it.llvmDir = project.file(project.findProperty("llvmDir")!!) - it.isInfoEnabled = logger.isInfoEnabled + it.platformManager.set(platformManager) } workQueue.submit(CompileNativeTestJob::class.java, parameters) diff --git a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt index d069526d61d..f2445661140 100644 --- a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt +++ b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt @@ -34,10 +34,13 @@ class Platform(val configurables: Configurables) } } -class PlatformManager(private val distribution: Distribution, experimental: Boolean = false) : - HostManager(distribution, experimental) { +class PlatformManager private constructor(private val serialized: Serialized) : + HostManager(serialized.distribution, serialized.experimental), java.io.Serializable { - constructor(konanHome: String, experimental: Boolean = false): this(Distribution(konanHome), experimental) + constructor(konanHome: String, experimental: Boolean = false) : this(Distribution(konanHome), experimental) + constructor(distribution: Distribution, experimental: Boolean = false) : this(Serialized(distribution, experimental)) + + private val distribution by serialized::distribution private val loaders = enabled.map { it to loadConfigurables(it, distribution.properties, DependencyProcessor.defaultDependenciesRoot.absolutePath) @@ -51,5 +54,18 @@ class PlatformManager(private val distribution: Distribution, experimental: Bool val hostPlatform = platforms.getValue(host) fun loader(target: KonanTarget) = loaders.getValue(target) + + private fun writeReplace(): Any = serialized + + private data class Serialized( + val distribution: Distribution, + val experimental: Boolean + ) : java.io.Serializable { + companion object { + private const val serialVersionUID: Long = 0L + } + + private fun readResolve(): Any = PlatformManager(this) + } } diff --git a/native/utils/src/org/jetbrains/kotlin/konan/target/Distribution.kt b/native/utils/src/org/jetbrains/kotlin/konan/target/Distribution.kt index 16d6985d5c1..9dcc724d65c 100644 --- a/native/utils/src/org/jetbrains/kotlin/konan/target/Distribution.kt +++ b/native/utils/src/org/jetbrains/kotlin/konan/target/Distribution.kt @@ -11,12 +11,18 @@ import org.jetbrains.kotlin.konan.properties.keepOnlyDefaultProfiles import org.jetbrains.kotlin.konan.properties.loadProperties import org.jetbrains.kotlin.konan.util.DependencyDirectories -class Distribution( - val konanHome: String, - private val onlyDefaultProfiles: Boolean = false, - private val runtimeFileOverride: String? = null, - private val propertyOverrides: Map? = null -) { +class Distribution private constructor(private val serialized: Serialized) : java.io.Serializable { + constructor( + konanHome: String, + onlyDefaultProfiles: Boolean = false, + runtimeFileOverride: String? = null, + propertyOverrides: Map? = null + ) : this(Serialized(konanHome, onlyDefaultProfiles, runtimeFileOverride, propertyOverrides)) + + val konanHome by serialized::konanHome + private val onlyDefaultProfiles by serialized::onlyDefaultProfiles + private val runtimeFileOverride by serialized::runtimeFileOverride + private val propertyOverrides by serialized::propertyOverrides val localKonanDir = DependencyDirectories.localKonanDir @@ -110,6 +116,21 @@ class Distribution( fun getCompilerVersion(propertyVersion: String?, konanHome: String): String? = propertyVersion ?: getBundleVersion(konanHome) } + + private fun writeReplace(): Any = serialized + + private data class Serialized( + val konanHome: String, + val onlyDefaultProfiles: Boolean, + val runtimeFileOverride: String?, + val propertyOverrides: Map?, + ) : java.io.Serializable { + companion object { + private const val serialVersionUID: Long = 0L + } + + private fun readResolve(): Any = Distribution(this) + } } // TODO: Move into K/N?