Gradle, Native: More verbose logging in KotlinToolRunner

Especially for tools executed in a separate JVM process:
JVM options, Java system properties, custom ENV variables.
This commit is contained in:
Dmitriy Dolovov
2020-11-02 17:32:23 +03:00
parent 734dff6282
commit fae3ba35e9
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.compilerRunner package org.jetbrains.kotlin.compilerRunner
import com.intellij.openapi.util.text.StringUtil.escapeStringCharacters
import org.gradle.api.Project import org.gradle.api.Project
import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.HostManager
import java.io.File import java.io.File
@@ -67,37 +68,58 @@ internal abstract class KotlinToolRunner(
} }
fun run(args: List<String>) { fun run(args: List<String>) {
project.logger.info("Run tool: \"$displayName\" with args: ${args.joinToString(separator = " ")}")
checkClasspath() checkClasspath()
if (mustRunViaExec) runViaExec(args) else runInProcess(args) if (mustRunViaExec) runViaExec(args) else runInProcess(args)
} }
private fun runViaExec(args: List<String>) { private fun runViaExec(args: List<String>) {
val transformedArgs = transformArgs(args)
val classpath = project.files(classpath)
val systemProperties = System.getProperties().asSequence()
.map { (k, v) -> k.toString() to v.toString() }
.filter { (k, _) -> k !in execSystemPropertiesBlacklist }
.escapeQuotesForWindows()
.toMap() + execSystemProperties
project.logger.info(
"""|Run "$displayName" tool in a separate JVM process
|Main class = $mainClass
|Arguments = ${transformedArgs.toPrettyString()}
|Classpath = ${classpath.files.map { it.absolutePath }.toPrettyString()}
|JVM options = ${jvmArgs.toPrettyString()}
|Java system properties = ${systemProperties.toPrettyString()}
|Suppressed ENV variables = ${execEnvironmentBlacklist.toPrettyString()}
|Custom ENV variables = ${execEnvironment.toPrettyString()}
""".trimMargin()
)
project.javaexec { spec -> project.javaexec { spec ->
spec.main = mainClass spec.main = mainClass
spec.classpath = project.files(classpath) spec.classpath = classpath
spec.jvmArgs(jvmArgs) spec.jvmArgs(jvmArgs)
spec.systemProperties( spec.systemProperties(systemProperties)
System.getProperties().asSequence()
.map { (k, v) -> k.toString() to v.toString() }
.filter { (k, _) -> k !in execSystemPropertiesBlacklist }
.escapeQuotesForWindows()
.toMap()
)
spec.systemProperties(execSystemProperties)
execEnvironmentBlacklist.forEach { spec.environment.remove(it) } execEnvironmentBlacklist.forEach { spec.environment.remove(it) }
spec.environment(execEnvironment) spec.environment(execEnvironment)
spec.args(transformArgs(args)) spec.args(transformedArgs)
} }
} }
private fun runInProcess(args: List<String>) { private fun runInProcess(args: List<String>) {
val transformedArgs = transformArgs(args)
project.logger.info(
"""|Run in-process tool "$displayName"
|Entry point method = $mainClass.$daemonEntryPoint
|Arguments = ${transformedArgs.toPrettyString()}
""".trimMargin()
)
try { try {
val mainClass = getIsolatedClassLoader().loadClass(mainClass) val mainClass = getIsolatedClassLoader().loadClass(mainClass)
val entryPoint = mainClass.methods.single { it.name == daemonEntryPoint } val entryPoint = mainClass.methods.single { it.name == daemonEntryPoint }
entryPoint.invoke(null, transformArgs(args).toTypedArray()) entryPoint.invoke(null, transformedArgs.toTypedArray())
} catch (t: InvocationTargetException) { } catch (t: InvocationTargetException) {
throw t.targetException throw t.targetException
} }
@@ -110,5 +132,24 @@ internal abstract class KotlinToolRunner(
if (HostManager.hostIsMingw) map { (key, value) -> key.escapeQuotes() to value.escapeQuotes() } else this if (HostManager.hostIsMingw) map { (key, value) -> key.escapeQuotes() to value.escapeQuotes() } else this
private val isolatedClassLoadersMap = ConcurrentHashMap<Any, ClassLoader>() private val isolatedClassLoadersMap = ConcurrentHashMap<Any, ClassLoader>()
private fun Map<String, String>.toPrettyString(): String = buildString {
append('{')
if (this@toPrettyString.isNotEmpty()) append('\n')
this@toPrettyString.entries.forEach { (key, value) ->
append('\t').append(key).append(" = ").append(value.toPrettyString()).append('\n')
}
append('}')
}
private fun Collection<String>.toPrettyString(): String = buildString {
append('[')
if (this@toPrettyString.isNotEmpty()) append('\n')
this@toPrettyString.forEach { append('\t').append(it.toPrettyString()).append('\n') }
append(']')
}
private fun String.toPrettyString(): String =
if (isEmpty()) "\"\"" else escapeStringCharacters(this).let { if (any(Char::isWhitespace)) "\"$it\"" else it }
} }
} }