Revert "[K/N][build] Refactored K/N tool runner"

This reverts commit fa587a61fd.
This commit is contained in:
Igor Chevdar
2021-11-26 14:04:06 +05:00
parent 07adab561c
commit fed76a87af
5 changed files with 138 additions and 93 deletions
@@ -16,125 +16,172 @@
package org.jetbrains.kotlin.gradle.plugin.konan package org.jetbrains.kotlin.gradle.plugin.konan
import org.gradle.api.Named
import org.gradle.api.Project 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.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.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.util.DependencyProcessor
import java.nio.file.Files import java.nio.file.Files
import org.jetbrains.kotlin.* import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.konan.properties.resolvablePropertyString import java.io.ByteArrayOutputStream
import org.jetbrains.kotlin.konan.util.DependencyDirectories
import java.io.File internal interface KonanToolRunner : Named {
import java.util.Properties val mainClass: String
import org.jetbrains.kotlin.compilerRunner.KotlinToolRunner val classpath: FileCollection
val jvmArgs: List<String>
val environment: Map<String, Any>
internal interface KonanToolRunner {
fun run(args: List<String>) 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( internal abstract class KonanCliRunner(
protected val toolName: String, val toolName: String,
project: Project, val fullName: String,
val additionalJvmArgs: List<String> = emptyList(), val project: Project,
val konanHome: String = project.konanHome private val additionalJvmArgs: List<String>,
) : KotlinToolRunner(project), KonanToolRunner { private val konanHome: String
final override val displayName get() = toolName ) : KonanToolRunner {
override val mainClass = "org.jetbrains.kotlin.cli.utilities.MainKt"
final override val mainClass get() = "org.jetbrains.kotlin.cli.utilities.MainKt" override fun getName() = toolName
final override val daemonEntryPoint get() = "daemonMain"
// We need to unset some environment variables which are set by XCode and may potentially affect the tool executed. // 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 { protected val blacklistEnvironment: List<String> by lazy {
HashSet<String>().also { collector -> KonanPlugin::class.java.getResourceAsStream("/env_blacklist")?.let { stream ->
KonanPlugin::class.java.getResourceAsStream("/env_blacklist")?.let { stream -> stream.reader().use { it.readLines() }
stream.reader().use { r -> r.forEachLine { collector.add(it) } } } ?: 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() = override val jvmArgs = HostManager.defaultJvmArgs.toMutableList().apply {
check(classpath.isNotEmpty()) { if (additionalJvmArgs.none { it.startsWith("-Xmx") } &&
""" project.jvmArgs.none { it.startsWith("-Xmx") }) {
Classpath of the tool is empty: $toolName add("-Xmx3G")
Probably the '${KONAN_HOME.propertyName}' project property contains an incorrect path. }
Please change it to the compiler root directory and rerun the build. addAll(additionalJvmArgs)
""".trimIndent() 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? override fun run(args: List<String>) {
final override val isolatedClassLoaderCacheKey get() = IsolatedClassLoaderCacheKey(classpath) 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 KonanInteropRunner(
internal class KonanCliCompilerRunner( 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, project: Project,
additionalJvmArgs: List<String> = emptyList(), additionalJvmArgs: List<String> = emptyList(),
val useArgFile: Boolean = true, val useArgFile: Boolean = true,
konanHome: String = project.konanHome konanHome: String = project.konanHome
) : KonanCliRunner("konanc", project, additionalJvmArgs, konanHome) { ) : KonanCliRunner("konanc", "Kotlin/Native compiler", project, additionalJvmArgs, konanHome) {
override val mustRunViaExec get() = false
override fun transformArgs(args: List<String>): List<String> { override fun transformArgs(args: List<String>): List<String> {
if (!useArgFile) return super.transformArgs(args) if (!useArgFile) {
return 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\"")
}
} }
return listOf(toolName, "@${argFile.absolutePath}") val argFile = Files.createTempFile("konancArgs", ".lst").toAbsolutePath().apply {
} toFile().deleteOnExit()
}
/** 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")}"
} }
result Files.write(argFile, args)
}
private val llvmExecutablesPath: String? by lazy { return listOf("@${argFile}")
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
} }
} }
@@ -142,6 +189,4 @@ internal class KonanKlibRunner(
project: Project, project: Project,
additionalJvmArgs: List<String> = emptyList(), additionalJvmArgs: List<String> = emptyList(),
konanHome: String = project.konanHome konanHome: String = project.konanHome
) : KonanCliRunner("klib", project, additionalJvmArgs, konanHome) { ) : KonanCliRunner("klib", "Klib management tool", project, additionalJvmArgs, konanHome)
override val mustRunViaExec get() = false
}
@@ -4,7 +4,7 @@ import org.gradle.api.DefaultTask
import org.gradle.api.file.Directory import org.gradle.api.file.Directory
import org.gradle.api.provider.Property import org.gradle.api.provider.Property
import org.gradle.api.tasks.* 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.gradle.plugin.konan.konanHome
import org.jetbrains.kotlin.konan.library.defaultResolver import org.jetbrains.kotlin.konan.library.defaultResolver
import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.CompilerOutputKind
@@ -79,6 +79,6 @@ open class KonanCacheTask: DefaultTask() {
"-Xadd-cache=${originalKlib?.absolutePath}", "-Xadd-cache=${originalKlib?.absolutePath}",
"-Xcache-directory=${cacheDirectory.absolutePath}" "-Xcache-directory=${cacheDirectory.absolutePath}"
) + additionalCacheFlags + cachedLibraries.map { "-Xcached-library=${it.key},${it.value}" } ) + additionalCacheFlags + cachedLibraries.map { "-Xcached-library=${it.key},${it.value}" }
KonanCliCompilerRunner(project, konanHome = konanHome).run(args) KonanCompilerRunner(project, konanHome = konanHome).run(args)
} }
} }
@@ -36,7 +36,7 @@ import java.io.File
abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec { abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
@get:Internal @get:Internal
override val toolRunner = KonanCliCompilerRunner(project, project.konanExtension.jvmArgs) override val toolRunner = KonanCompilerRunner(project, project.konanExtension.jvmArgs)
abstract val produce: CompilerOutputKind abstract val produce: CompilerOutputKind
@Internal get @Internal get
@@ -70,7 +70,7 @@ open class KonanCompilerDownloadTask : DefaultTask() {
// Download dependencies if a user said so. // Download dependencies if a user said so.
if (downloadDependencies) { if (downloadDependencies) {
val runner = KonanCliCompilerRunner(project, project.konanExtension.jvmArgs) val runner = KonanCompilerRunner(project, project.konanExtension.jvmArgs)
project.konanTargets.forEach { project.konanTargets.forEach {
runner.run("-Xcheck_dependencies", "-target", it.visibleName) runner.run("-Xcheck_dependencies", "-target", it.visibleName)
} }
@@ -37,7 +37,7 @@ import javax.inject.Inject
open class KonanInteropTask @Inject constructor(@Internal val workerExecutor: WorkerExecutor) : KonanBuildingTask(), KonanInteropSpec { open class KonanInteropTask @Inject constructor(@Internal val workerExecutor: WorkerExecutor) : KonanBuildingTask(), KonanInteropSpec {
@get:Internal @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) { override fun init(config: KonanBuildingConfig<*>, destinationDir: File, artifactName: String, target: KonanTarget) {
super.init(config, destinationDir, artifactName, target) super.init(config, destinationDir, artifactName, target)