[Commonizer] Integrate commonizer to the Gradle plugin, p.2

Call commonizer CLI via Gradle tool runner.
This commit is contained in:
Dmitriy Dolovov
2020-02-01 18:14:17 +07:00
parent d7e82bf899
commit 7cf4395ccd
9 changed files with 62 additions and 45 deletions
@@ -6,18 +6,29 @@
package org.jetbrains.kotlin.compilerRunner package org.jetbrains.kotlin.compilerRunner
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.file.FileCollection import org.jetbrains.kotlin.gradle.plugin.KLIB_COMMONIZER_CLASSPATH_CONFIGURATION_NAME
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
import java.io.File
// TODO: implement this runner
internal class KotlinNativeKlibCommonizerToolRunner(project: Project) : KotlinToolRunner(project) { internal class KotlinNativeKlibCommonizerToolRunner(project: Project) : KotlinToolRunner(project) {
override val displayName get() = "Kotlin/Native KLIB commonizer" override val displayName get() = "Kotlin/Native KLIB commonizer"
override val mainClass: String get() = TODO("not implemented") override val mainClass: String get() = "org.jetbrains.kotlin.descriptors.commonizer.cli.CommonizerCLI"
override val classpath: FileCollection get() = TODO("not implemented")
override fun getIsolatedClassLoader(): ClassLoader { override val classpath by lazy {
TODO("not implemented") try {
project.configurations.getByName(KLIB_COMMONIZER_CLASSPATH_CONFIGURATION_NAME).resolve() as Set<File>
} catch (e: Exception) {
project.logger.error(
"Could not resolve KLIB commonizer classpath. Check if Kotlin Gradle plugin repository is configured in $project."
)
throw e
}
} }
override val mustRunViaExec get() = false override val isolatedClassLoaderCacheKey get() = project.getKotlinPluginVersion()!!
override val defaultMaxHeapSize: String get() = "4G"
override val mustRunViaExec get() = true // because it's not enough the standard Gradle wrapper's heap size
} }
@@ -6,9 +6,11 @@
package org.jetbrains.kotlin.compilerRunner package org.jetbrains.kotlin.compilerRunner
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.HostManager
import java.io.File
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
import java.net.URLClassLoader
import java.util.concurrent.ConcurrentHashMap
internal abstract class KotlinToolRunner( internal abstract class KotlinToolRunner(
val project: Project val project: Project
@@ -25,9 +27,14 @@ internal abstract class KotlinToolRunner(
open val systemProperties: Map<String, String> = emptyMap() open val systemProperties: Map<String, String> = emptyMap()
open val systemPropertiesBlacklist: Set<String> = emptySet() open val systemPropertiesBlacklist: Set<String> = emptySet()
abstract val classpath: FileCollection abstract val classpath: Set<File>
open fun checkClasspath(): Unit = check(!classpath.isEmpty) { "Classpath of the tool is empty: $displayName" } open fun checkClasspath(): Unit = check(classpath.isNotEmpty()) { "Classpath of the tool is empty: $displayName" }
abstract fun getIsolatedClassLoader(): ClassLoader
abstract val isolatedClassLoaderCacheKey: Any
private fun getIsolatedClassLoader(): ClassLoader = isolatedClassLoadersMap.computeIfAbsent(isolatedClassLoaderCacheKey) {
val arrayOfURLs = classpath.map { File(it.absolutePath).toURI().toURL() }.toTypedArray()
URLClassLoader(arrayOfURLs, null)
}
open val defaultMaxHeapSize: String get() = "3G" open val defaultMaxHeapSize: String get() = "3G"
open val enableAssertions: Boolean get() = true open val enableAssertions: Boolean get() = true
@@ -67,7 +74,7 @@ internal abstract class KotlinToolRunner(
private fun runViaExec(args: List<String>) { private fun runViaExec(args: List<String>) {
project.javaexec { spec -> project.javaexec { spec ->
spec.main = mainClass spec.main = mainClass
spec.classpath = classpath spec.classpath = project.files(classpath)
spec.jvmArgs(jvmArgs) spec.jvmArgs(jvmArgs)
spec.systemProperties( spec.systemProperties(
System.getProperties().asSequence() System.getProperties().asSequence()
@@ -87,9 +94,7 @@ internal abstract class KotlinToolRunner(
val oldProperties = setUpSystemProperties() val oldProperties = setUpSystemProperties()
try { try {
val classLoader = getIsolatedClassLoader() val mainClass = getIsolatedClassLoader().loadClass(mainClass)
val mainClass = classLoader.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, transformArgs(args).toTypedArray())
@@ -129,5 +134,7 @@ internal abstract class KotlinToolRunner(
private fun Sequence<Pair<String, String>>.escapeQuotesForWindows() = private fun Sequence<Pair<String, String>>.escapeQuotesForWindows() =
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>()
} }
} }
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.compilerRunner package org.jetbrains.kotlin.compilerRunner
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
@@ -15,10 +14,7 @@ import org.jetbrains.kotlin.konan.CompilerVersion
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.DependencyDirectories import org.jetbrains.kotlin.konan.util.DependencyDirectories
import java.io.File
import java.net.URLClassLoader
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap
private val Project.jvmArgs private val Project.jvmArgs
get() = PropertiesProvider(this).nativeJvmArgs?.split("\\s+".toRegex()).orEmpty() get() = PropertiesProvider(this).nativeJvmArgs?.split("\\s+".toRegex()).orEmpty()
@@ -65,10 +61,12 @@ internal abstract class KotlinNativeToolRunner(
} }
final override val systemPropertiesBlacklist = setOf("java.endorsed.dirs") final override val systemPropertiesBlacklist = setOf("java.endorsed.dirs")
final override val classpath: FileCollection = project.fileTree("${project.konanHome}/konan/lib/").apply { include("*.jar") } final override val classpath by lazy {
project.fileTree("${project.konanHome}/konan/lib/").apply { include("*.jar") }.toSet()
}
final override fun checkClasspath() = final override fun checkClasspath() =
check(!classpath.isEmpty) { check(classpath.isNotEmpty()) {
""" """
Classpath of the tool is empty: $toolName Classpath of the tool is empty: $toolName
Probably the '${PropertiesProvider.KOTLIN_NATIVE_HOME}' project property contains an incorrect path. Probably the '${PropertiesProvider.KOTLIN_NATIVE_HOME}' project property contains an incorrect path.
@@ -76,19 +74,11 @@ internal abstract class KotlinNativeToolRunner(
""".trimIndent() """.trimIndent()
} }
final override fun getIsolatedClassLoader() = final override val isolatedClassLoaderCacheKey get() = project.konanHome
isolatedClassLoadersMap.computeIfAbsent(project.konanHome) {
val arrayOfURLs = classpath.map { File(it.absolutePath).toURI().toURL() }.toTypedArray()
URLClassLoader(arrayOfURLs, null)
}
override fun transformArgs(args: List<String>) = listOf(toolName) + args override fun transformArgs(args: List<String>) = listOf(toolName) + args
final override fun getCustomJvmArgs() = project.jvmArgs final override fun getCustomJvmArgs() = project.jvmArgs
companion object {
private val isolatedClassLoadersMap = ConcurrentHashMap<String, ClassLoader>()
}
} }
/** Kotlin/Native C-interop tool runner */ /** Kotlin/Native C-interop tool runner */
@@ -48,6 +48,8 @@ import java.util.jar.Manifest
const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath" const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath"
const val NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinNativeCompilerPluginClasspath" const val NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinNativeCompilerPluginClasspath"
internal const val COMPILER_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerClasspath" internal const val COMPILER_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerClasspath"
internal const val KLIB_COMMONIZER_CLASSPATH_CONFIGURATION_NAME = "kotlinKlibCommonizerClasspath"
val KOTLIN_DSL_NAME = "kotlin" val KOTLIN_DSL_NAME = "kotlin"
val KOTLIN_JS_DSL_NAME = "kotlin2js" val KOTLIN_JS_DSL_NAME = "kotlin2js"
val KOTLIN_OPTIONS_DSL_NAME = "kotlinOptions" val KOTLIN_OPTIONS_DSL_NAME = "kotlinOptions"
@@ -34,11 +34,10 @@ import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.addNpmDependencyExtension import org.jetbrains.kotlin.gradle.targets.js.npm.addNpmDependencyExtension
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_COMPILER_EMBEDDABLE import org.jetbrains.kotlin.gradle.tasks.KOTLIN_COMPILER_EMBEDDABLE
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_MODULE_GROUP import org.jetbrains.kotlin.gradle.tasks.KOTLIN_MODULE_GROUP
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_KLIB_COMMONIZER_EMBEDDABLE
import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry
import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility
import org.jetbrains.kotlin.gradle.utils.loadPropertyFromResources import org.jetbrains.kotlin.gradle.utils.loadPropertyFromResources
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
import org.jetbrains.kotlin.statistics.metrics.StringMetrics import org.jetbrains.kotlin.statistics.metrics.StringMetrics
import javax.inject.Inject import javax.inject.Inject
import kotlin.reflect.KClass import kotlin.reflect.KClass
@@ -67,6 +66,9 @@ abstract class KotlinBasePluginWrapper(
project.configurations.maybeCreate(NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME).apply { project.configurations.maybeCreate(NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME).apply {
isTransitive = false isTransitive = false
} }
project.configurations.maybeCreate(KLIB_COMMONIZER_CLASSPATH_CONFIGURATION_NAME).defaultDependencies {
it.add(project.dependencies.create("$KOTLIN_MODULE_GROUP:$KOTLIN_KLIB_COMMONIZER_EMBEDDABLE:$kotlinPluginVersion"))
}
// TODO: consider only set if if daemon or parallel compilation are enabled, though this way it should be safe too // TODO: consider only set if if daemon or parallel compilation are enabled, though this way it should be safe too
System.setProperty(org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true") System.setProperty(org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true")
@@ -134,7 +134,7 @@ class NativeCompilerDownloader(
} }
fun downloadIfNeeded() { fun downloadIfNeeded() {
if (KotlinNativeCompilerRunner(project).classpath.isEmpty) { if (KotlinNativeCompilerRunner(project).classpath.isEmpty()) {
downloadAndExtract() downloadAndExtract()
} }
} }
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.gradle.targets.native.internal package org.jetbrains.kotlin.gradle.targets.native.internal
import org.gradle.api.Project
import org.jetbrains.kotlin.compilerRunner.KotlinNativeKlibCommonizerToolRunner
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_KLIB_DIR import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_KLIB_DIR
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
import java.io.File import java.io.File
@@ -16,12 +18,13 @@ import java.nio.file.StandardCopyOption
import java.util.* import java.util.*
internal fun runCommonizerInBulk( internal fun runCommonizerInBulk(
project: Project,
distributionDir: File, distributionDir: File,
baseDestinationDir: File, baseDestinationDir: File,
targetGroups: List<Set<KonanTarget>>, targetGroups: List<Set<KonanTarget>>,
kotlinVersion: String kotlinVersion: String
): List<File> { ): List<File> {
val commandLineParameters = mutableListOf<String>() val commandLineArguments = mutableListOf<String>()
val postActions = mutableListOf<() -> Unit>() val postActions = mutableListOf<() -> Unit>()
val result = targetGroups.map { targets -> val result = targetGroups.map { targets ->
@@ -54,13 +57,13 @@ internal fun runCommonizerInBulk(
directory = parentDir directory = parentDir
) )
commandLineParameters += "native-dist-commonize" commandLineArguments += "native-dist-commonize"
commandLineParameters += "-distribution-path" commandLineArguments += "-distribution-path"
commandLineParameters += distributionDir.toString() commandLineArguments += distributionDir.toString()
commandLineParameters += "-output-path" commandLineArguments += "-output-path"
commandLineParameters += destinationTmpDir.toString() commandLineArguments += destinationTmpDir.toString()
commandLineParameters += "-targets" commandLineArguments += "-targets"
commandLineParameters += orderedTargets.joinToString(separator = ",") commandLineArguments += orderedTargets.joinToString(separator = ",")
postActions.add { renameDirectory(destinationTmpDir, destinationDir) } postActions.add { renameDirectory(destinationTmpDir, destinationDir) }
} }
@@ -69,17 +72,17 @@ internal fun runCommonizerInBulk(
} }
} }
callCommonizerCLI(commandLineParameters) callCommonizerCLI(project, commandLineArguments)
postActions.forEach { it() } postActions.forEach { it() }
return result return result
} }
private fun callCommonizerCLI(commandLineParameters: List<String>) { private fun callCommonizerCLI(project: Project, commandLineArguments: List<String>) {
if (commandLineParameters.isEmpty()) return if (commandLineArguments.isEmpty()) return
// TODO: implement KotlinNativeKlibCommonizerToolRunner(project).run(commandLineArguments)
} }
private fun renameDirectory(source: File, destination: File) { private fun renameDirectory(source: File, destination: File) {
@@ -88,6 +88,7 @@ private class NativePlatformDependencyResolver(val project: Project, val kotlinV
val commonizedLibsDirs: Map<CommonizedCommon, File> = val commonizedLibsDirs: Map<CommonizedCommon, File> =
runCommonizerInBulk( runCommonizerInBulk(
project = project,
distributionDir = distributionDir, distributionDir = distributionDir,
baseDestinationDir = distributionDir.resolve(KONAN_DISTRIBUTION_KLIB_DIR).resolve(KONAN_DISTRIBUTION_COMMONIZED_LIBS_DIR), baseDestinationDir = distributionDir.resolve(KONAN_DISTRIBUTION_KLIB_DIR).resolve(KONAN_DISTRIBUTION_COMMONIZED_LIBS_DIR),
targetGroups = targetGroups.map { it.second }, targetGroups = targetGroups.map { it.second },
@@ -48,6 +48,7 @@ private val KOTLIN_SCRIPT_RUNTIME = "kotlin-script-runtime"
private val KOTLIN_SCRIPT_COMMON = "kotlin-scripting-common" private val KOTLIN_SCRIPT_COMMON = "kotlin-scripting-common"
private val KOTLIN_SCRIPT_JVM = "kotlin-scripting-jvm" private val KOTLIN_SCRIPT_JVM = "kotlin-scripting-jvm"
private val KOTLIN_REFLECT = "kotlin-reflect" private val KOTLIN_REFLECT = "kotlin-reflect"
internal const val KOTLIN_KLIB_COMMONIZER_EMBEDDABLE = "kotlin-klib-commonizer-embeddable"
internal fun findKotlinJvmCompilerClasspath(project: Project): List<File> = internal fun findKotlinJvmCompilerClasspath(project: Project): List<File> =
findKotlinModuleJar(project, K2JVM_COMPILER_CLASS, KOTLIN_COMPILER_EMBEDDABLE).let { findKotlinModuleJar(project, K2JVM_COMPILER_CLASS, KOTLIN_COMPILER_EMBEDDABLE).let {