Revert "[K/N][build] Refactored K/N tool runner"
This reverts commit fa587a61fd.
This commit is contained in:
+133
-88
@@ -16,125 +16,172 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.konan
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import org.gradle.jvm.toolchain.JavaLauncher
|
||||
import org.gradle.jvm.toolchain.JavaToolchainService
|
||||
import org.gradle.jvm.toolchain.JavaToolchainSpec
|
||||
import org.gradle.process.ExecSpec
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.KonanPlugin.ProjectProperty.KONAN_HOME
|
||||
import org.jetbrains.kotlin.konan.target.Family
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||
import java.nio.file.Files
|
||||
import org.jetbrains.kotlin.*
|
||||
import org.jetbrains.kotlin.konan.properties.resolvablePropertyString
|
||||
import org.jetbrains.kotlin.konan.util.DependencyDirectories
|
||||
import java.io.File
|
||||
import java.util.Properties
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinToolRunner
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
internal interface KonanToolRunner : Named {
|
||||
val mainClass: String
|
||||
val classpath: FileCollection
|
||||
val jvmArgs: List<String>
|
||||
val environment: Map<String, Any>
|
||||
|
||||
internal interface KonanToolRunner {
|
||||
fun run(args: List<String>)
|
||||
fun run(vararg args: String) = run(args.toList())
|
||||
}
|
||||
|
||||
internal fun KonanToolRunner.run(vararg args: String) = run(args.toList())
|
||||
|
||||
internal abstract class KonanCliRunner(
|
||||
protected val toolName: String,
|
||||
project: Project,
|
||||
val additionalJvmArgs: List<String> = emptyList(),
|
||||
val konanHome: String = project.konanHome
|
||||
) : KotlinToolRunner(project), KonanToolRunner {
|
||||
final override val displayName get() = toolName
|
||||
val toolName: String,
|
||||
val fullName: String,
|
||||
val project: Project,
|
||||
private val additionalJvmArgs: List<String>,
|
||||
private val konanHome: String
|
||||
) : KonanToolRunner {
|
||||
override val mainClass = "org.jetbrains.kotlin.cli.utilities.MainKt"
|
||||
|
||||
final override val mainClass get() = "org.jetbrains.kotlin.cli.utilities.MainKt"
|
||||
final override val daemonEntryPoint get() = "daemonMain"
|
||||
override fun getName() = toolName
|
||||
|
||||
// We need to unset some environment variables which are set by XCode and may potentially affect the tool executed.
|
||||
final override val execEnvironmentBlacklist: Set<String> by lazy {
|
||||
HashSet<String>().also { collector ->
|
||||
KonanPlugin::class.java.getResourceAsStream("/env_blacklist")?.let { stream ->
|
||||
stream.reader().use { r -> r.forEachLine { collector.add(it) } }
|
||||
}
|
||||
}
|
||||
protected val blacklistEnvironment: List<String> by lazy {
|
||||
KonanPlugin::class.java.getResourceAsStream("/env_blacklist")?.let { stream ->
|
||||
stream.reader().use { it.readLines() }
|
||||
} ?: emptyList<String>()
|
||||
}
|
||||
|
||||
final override val execSystemProperties by lazy { mapOf("konan.home" to konanHome) }
|
||||
protected val blacklistProperties: Set<String> =
|
||||
setOf(
|
||||
"java.endorsed.dirs", // Fix for KT-25887
|
||||
"user.dir" // Don't propagate the working dir of the current Gradle process
|
||||
)
|
||||
|
||||
final override val classpath by lazy { project.fileTree("$konanHome/konan/lib/").apply { include("*.jar") }.files }
|
||||
override val classpath: FileCollection =
|
||||
project.fileTree("$konanHome/konan/lib/")
|
||||
.apply { include("*.jar") }
|
||||
|
||||
final override fun checkClasspath() =
|
||||
check(classpath.isNotEmpty()) {
|
||||
"""
|
||||
Classpath of the tool is empty: $toolName
|
||||
Probably the '${KONAN_HOME.propertyName}' project property contains an incorrect path.
|
||||
Please change it to the compiler root directory and rerun the build.
|
||||
""".trimIndent()
|
||||
override val jvmArgs = HostManager.defaultJvmArgs.toMutableList().apply {
|
||||
if (additionalJvmArgs.none { it.startsWith("-Xmx") } &&
|
||||
project.jvmArgs.none { it.startsWith("-Xmx") }) {
|
||||
add("-Xmx3G")
|
||||
}
|
||||
addAll(additionalJvmArgs)
|
||||
addAll(project.jvmArgs)
|
||||
}
|
||||
|
||||
override val environment = mutableMapOf("LIBCLANG_DISABLE_CRASH_RECOVERY" to "1")
|
||||
|
||||
private fun String.escapeQuotes() = replace("\"", "\\\"")
|
||||
|
||||
private fun Sequence<Pair<String, String>>.escapeQuotesForWindows() =
|
||||
if (HostManager.hostIsMingw) {
|
||||
map { (key, value) -> key.escapeQuotes() to value.escapeQuotes() }
|
||||
} else {
|
||||
this
|
||||
}
|
||||
|
||||
data class IsolatedClassLoaderCacheKey(val classpath: Set<java.io.File>)
|
||||
open protected fun transformArgs(args: List<String>): List<String> = args
|
||||
|
||||
// TODO: can't we use this for other implementations too?
|
||||
final override val isolatedClassLoaderCacheKey get() = IsolatedClassLoaderCacheKey(classpath)
|
||||
override fun run(args: List<String>) {
|
||||
project.logger.info("Run tool: $toolName with args: ${args.joinToString(separator = " ")}")
|
||||
if (classpath.isEmpty) {
|
||||
throw IllegalStateException("Classpath of the tool is empty: $toolName\n" +
|
||||
"Probably the '${KONAN_HOME.propertyName}' project property contains an incorrect path.\n" +
|
||||
"Please change it to the compiler root directory and rerun the build.")
|
||||
}
|
||||
|
||||
override fun transformArgs(args: List<String>) = listOf(toolName) + args
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val launcher = project.getProperty(KonanPlugin.ProjectProperty.KONAN_JVM_LAUNCHER) as? Provider<JavaLauncher>
|
||||
?: throw IllegalStateException("Missing property: ${KonanPlugin.ProjectProperty.KONAN_JVM_LAUNCHER}")
|
||||
|
||||
final override fun getCustomJvmArgs() = additionalJvmArgs
|
||||
val out = ByteArrayOutputStream()
|
||||
val err = ByteArrayOutputStream()
|
||||
|
||||
val execResult = project.exec(object : Action<ExecSpec> {
|
||||
override fun execute(exec: ExecSpec) {
|
||||
exec.executable = launcher.get().executablePath.toString()
|
||||
val properties = System.getProperties().asSequence()
|
||||
.map { (k, v) -> k.toString() to v.toString() }
|
||||
.filter { (k, _) -> k !in this@KonanCliRunner.blacklistProperties }
|
||||
.filter { (k, _) -> !k.startsWith("sun") && !k.startsWith("java") }
|
||||
.escapeQuotesForWindows()
|
||||
.toMap()
|
||||
.toMutableMap()
|
||||
properties.put("konan.home", project.kotlinNativeDist.absolutePath)
|
||||
|
||||
exec.args(mutableListOf<String>().apply {
|
||||
addAll(jvmArgs)
|
||||
addAll(properties.entries.map { "-D${it.key}=${it.value}" })
|
||||
add("-cp")
|
||||
add(classpath.joinToString(separator = System.getProperty("path.separator")))
|
||||
add(mainClass)
|
||||
addAll(listOf(toolName) + transformArgs(args))
|
||||
})
|
||||
blacklistEnvironment.forEach { environment.remove(it) }
|
||||
exec.environment(environment)
|
||||
exec.errorOutput = err
|
||||
exec.standardOutput = out
|
||||
exec.isIgnoreExitValue = true
|
||||
}
|
||||
})
|
||||
|
||||
check(execResult.exitValue == 0) {
|
||||
"""
|
||||
stdout:$out
|
||||
stderr:$err
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Kotlin/Native compiler runner */
|
||||
internal class KonanCliCompilerRunner(
|
||||
internal class KonanInteropRunner(
|
||||
project: Project,
|
||||
additionalJvmArgs: List<String> = emptyList(),
|
||||
konanHome: String = project.konanHome
|
||||
) : KonanCliRunner("cinterop", "Kotlin/Native cinterop tool", project, additionalJvmArgs, konanHome) {
|
||||
init {
|
||||
if (HostManager.host == KonanTarget.MINGW_X64) {
|
||||
//TODO: Oh-ho-ho fix it in more convinient way.
|
||||
environment.put("PATH", DependencyProcessor.defaultDependenciesRoot.absolutePath +
|
||||
"\\llvm-11.1.0-windows-x64" +
|
||||
"\\bin;${environment.get("PATH")}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class KonanCompilerRunner(
|
||||
project: Project,
|
||||
additionalJvmArgs: List<String> = emptyList(),
|
||||
val useArgFile: Boolean = true,
|
||||
konanHome: String = project.konanHome
|
||||
) : KonanCliRunner("konanc", project, additionalJvmArgs, konanHome) {
|
||||
override val mustRunViaExec get() = false
|
||||
|
||||
) : KonanCliRunner("konanc", "Kotlin/Native compiler", project, additionalJvmArgs, konanHome) {
|
||||
override fun transformArgs(args: List<String>): List<String> {
|
||||
if (!useArgFile) return super.transformArgs(args)
|
||||
|
||||
val argFile = Files.createTempFile(/* prefix = */ "konancArgs", /* suffix = */ ".lst").toFile().apply { deleteOnExit() }
|
||||
argFile.printWriter().use { w ->
|
||||
for (arg in args) {
|
||||
val escapedArg = arg
|
||||
.replace("\\", "\\\\")
|
||||
.replace("\"", "\\\"")
|
||||
w.println("\"$escapedArg\"")
|
||||
}
|
||||
if (!useArgFile) {
|
||||
return args
|
||||
}
|
||||
|
||||
return listOf(toolName, "@${argFile.absolutePath}")
|
||||
}
|
||||
}
|
||||
|
||||
/** Kotlin/Native C-interop tool runner */
|
||||
internal class KonanCliInteropRunner(
|
||||
project: Project,
|
||||
additionalJvmArgs: List<String> = emptyList(),
|
||||
konanHome: String = project.konanHome
|
||||
) : KonanCliRunner("cinterop", project, additionalJvmArgs, konanHome) {
|
||||
override val mustRunViaExec get() = false
|
||||
|
||||
override val execEnvironment by lazy {
|
||||
val result = mutableMapOf<String, String>()
|
||||
result.putAll(super.execEnvironment)
|
||||
result["LIBCLANG_DISABLE_CRASH_RECOVERY"] = "1"
|
||||
llvmExecutablesPath?.let {
|
||||
result["PATH"] = "$it;${System.getenv("PATH")}"
|
||||
val argFile = Files.createTempFile("konancArgs", ".lst").toAbsolutePath().apply {
|
||||
toFile().deleteOnExit()
|
||||
}
|
||||
result
|
||||
}
|
||||
Files.write(argFile, args)
|
||||
|
||||
private val llvmExecutablesPath: String? by lazy {
|
||||
if (HostManager.host == KonanTarget.MINGW_X64) {
|
||||
// TODO: Read it from Platform properties when it is accessible.
|
||||
val konanProperties = Properties().apply {
|
||||
project.file("$konanHome/konan/konan.properties").inputStream().use(::load)
|
||||
}
|
||||
|
||||
konanProperties.resolvablePropertyString("llvmHome.mingw_x64")?.let { toolchainDir ->
|
||||
DependencyDirectories.defaultDependenciesRoot
|
||||
.resolve("$toolchainDir/bin")
|
||||
.absolutePath
|
||||
}
|
||||
} else
|
||||
null
|
||||
return listOf("@${argFile}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +189,4 @@ internal class KonanKlibRunner(
|
||||
project: Project,
|
||||
additionalJvmArgs: List<String> = emptyList(),
|
||||
konanHome: String = project.konanHome
|
||||
) : KonanCliRunner("klib", project, additionalJvmArgs, konanHome) {
|
||||
override val mustRunViaExec get() = false
|
||||
}
|
||||
) : KonanCliRunner("klib", "Klib management tool", project, additionalJvmArgs, konanHome)
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.Directory
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.KonanCliCompilerRunner
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.KonanCompilerRunner
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.konanHome
|
||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
@@ -79,6 +79,6 @@ open class KonanCacheTask: DefaultTask() {
|
||||
"-Xadd-cache=${originalKlib?.absolutePath}",
|
||||
"-Xcache-directory=${cacheDirectory.absolutePath}"
|
||||
) + additionalCacheFlags + cachedLibraries.map { "-Xcached-library=${it.key},${it.value}" }
|
||||
KonanCliCompilerRunner(project, konanHome = konanHome).run(args)
|
||||
KonanCompilerRunner(project, konanHome = konanHome).run(args)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -36,7 +36,7 @@ import java.io.File
|
||||
abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
|
||||
|
||||
@get:Internal
|
||||
override val toolRunner = KonanCliCompilerRunner(project, project.konanExtension.jvmArgs)
|
||||
override val toolRunner = KonanCompilerRunner(project, project.konanExtension.jvmArgs)
|
||||
|
||||
abstract val produce: CompilerOutputKind
|
||||
@Internal get
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ open class KonanCompilerDownloadTask : DefaultTask() {
|
||||
|
||||
// Download dependencies if a user said so.
|
||||
if (downloadDependencies) {
|
||||
val runner = KonanCliCompilerRunner(project, project.konanExtension.jvmArgs)
|
||||
val runner = KonanCompilerRunner(project, project.konanExtension.jvmArgs)
|
||||
project.konanTargets.forEach {
|
||||
runner.run("-Xcheck_dependencies", "-target", it.visibleName)
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ import javax.inject.Inject
|
||||
open class KonanInteropTask @Inject constructor(@Internal val workerExecutor: WorkerExecutor) : KonanBuildingTask(), KonanInteropSpec {
|
||||
|
||||
@get:Internal
|
||||
override val toolRunner: KonanToolRunner = KonanCliInteropRunner(project, project.konanExtension.jvmArgs)
|
||||
override val toolRunner: KonanToolRunner = KonanInteropRunner(project, project.konanExtension.jvmArgs)
|
||||
|
||||
override fun init(config: KonanBuildingConfig<*>, destinationDir: File, artifactName: String, target: KonanTarget) {
|
||||
super.init(config, destinationDir, artifactName, target)
|
||||
|
||||
Reference in New Issue
Block a user