diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinNativeKlibCommonizerToolRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinNativeKlibCommonizerToolRunner.kt index 8f1a712ae22..83174143593 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinNativeKlibCommonizerToolRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinNativeKlibCommonizerToolRunner.kt @@ -6,18 +6,29 @@ package org.jetbrains.kotlin.compilerRunner 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) { override val displayName get() = "Kotlin/Native KLIB commonizer" - override val mainClass: String get() = TODO("not implemented") - override val classpath: FileCollection get() = TODO("not implemented") + override val mainClass: String get() = "org.jetbrains.kotlin.descriptors.commonizer.cli.CommonizerCLI" - override fun getIsolatedClassLoader(): ClassLoader { - TODO("not implemented") + override val classpath by lazy { + try { + project.configurations.getByName(KLIB_COMMONIZER_CLASSPATH_CONFIGURATION_NAME).resolve() as Set + } 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 } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinToolRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinToolRunner.kt index 5cda838284c..5fa1408fcb2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinToolRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/KotlinToolRunner.kt @@ -6,9 +6,11 @@ package org.jetbrains.kotlin.compilerRunner import org.gradle.api.Project -import org.gradle.api.file.FileCollection import org.jetbrains.kotlin.konan.target.HostManager +import java.io.File import java.lang.reflect.InvocationTargetException +import java.net.URLClassLoader +import java.util.concurrent.ConcurrentHashMap internal abstract class KotlinToolRunner( val project: Project @@ -25,9 +27,14 @@ internal abstract class KotlinToolRunner( open val systemProperties: Map = emptyMap() open val systemPropertiesBlacklist: Set = emptySet() - abstract val classpath: FileCollection - open fun checkClasspath(): Unit = check(!classpath.isEmpty) { "Classpath of the tool is empty: $displayName" } - abstract fun getIsolatedClassLoader(): ClassLoader + abstract val classpath: Set + open fun checkClasspath(): Unit = check(classpath.isNotEmpty()) { "Classpath of the tool is empty: $displayName" } + + 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 enableAssertions: Boolean get() = true @@ -67,7 +74,7 @@ internal abstract class KotlinToolRunner( private fun runViaExec(args: List) { project.javaexec { spec -> spec.main = mainClass - spec.classpath = classpath + spec.classpath = project.files(classpath) spec.jvmArgs(jvmArgs) spec.systemProperties( System.getProperties().asSequence() @@ -87,9 +94,7 @@ internal abstract class KotlinToolRunner( val oldProperties = setUpSystemProperties() try { - val classLoader = getIsolatedClassLoader() - - val mainClass = classLoader.loadClass(mainClass) + val mainClass = getIsolatedClassLoader().loadClass(mainClass) val entryPoint = mainClass.methods.single { it.name == daemonEntryPoint } entryPoint.invoke(null, transformArgs(args).toTypedArray()) @@ -129,5 +134,7 @@ internal abstract class KotlinToolRunner( private fun Sequence>.escapeQuotesForWindows() = if (HostManager.hostIsMingw) map { (key, value) -> key.escapeQuotes() to value.escapeQuotes() } else this + + private val isolatedClassLoadersMap = ConcurrentHashMap() } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt index e9935d6dad0..ac397d08060 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.compilerRunner import org.gradle.api.Project -import org.gradle.api.file.FileCollection import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind 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.KonanTarget import org.jetbrains.kotlin.konan.util.DependencyDirectories -import java.io.File -import java.net.URLClassLoader import java.util.* -import java.util.concurrent.ConcurrentHashMap private val Project.jvmArgs 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 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() = - check(!classpath.isEmpty) { + check(classpath.isNotEmpty()) { """ Classpath of the tool is empty: $toolName Probably the '${PropertiesProvider.KOTLIN_NATIVE_HOME}' project property contains an incorrect path. @@ -76,19 +74,11 @@ internal abstract class KotlinNativeToolRunner( """.trimIndent() } - final override fun getIsolatedClassLoader() = - isolatedClassLoadersMap.computeIfAbsent(project.konanHome) { - val arrayOfURLs = classpath.map { File(it.absolutePath).toURI().toURL() }.toTypedArray() - URLClassLoader(arrayOfURLs, null) - } + final override val isolatedClassLoaderCacheKey get() = project.konanHome override fun transformArgs(args: List) = listOf(toolName) + args final override fun getCustomJvmArgs() = project.jvmArgs - - companion object { - private val isolatedClassLoadersMap = ConcurrentHashMap() - } } /** Kotlin/Native C-interop tool runner */ diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index f74a246316b..96f6b0509c4 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -48,6 +48,8 @@ import java.util.jar.Manifest const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath" const val NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinNativeCompilerPluginClasspath" internal const val COMPILER_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerClasspath" +internal const val KLIB_COMMONIZER_CLASSPATH_CONFIGURATION_NAME = "kotlinKlibCommonizerClasspath" + val KOTLIN_DSL_NAME = "kotlin" val KOTLIN_JS_DSL_NAME = "kotlin2js" val KOTLIN_OPTIONS_DSL_NAME = "kotlinOptions" diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index d2a000503f8..c0e958c90a6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -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.tasks.KOTLIN_COMPILER_EMBEDDABLE 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.utils.checkGradleCompatibility 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 javax.inject.Inject import kotlin.reflect.KClass @@ -67,6 +66,9 @@ abstract class KotlinBasePluginWrapper( project.configurations.maybeCreate(NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME).apply { 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 System.setProperty(org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true") diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt index 1f96be83f97..5cf31a3d7db 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt @@ -134,7 +134,7 @@ class NativeCompilerDownloader( } fun downloadIfNeeded() { - if (KotlinNativeCompilerRunner(project).classpath.isEmpty) { + if (KotlinNativeCompilerRunner(project).classpath.isEmpty()) { downloadAndExtract() } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/KotlinNativeKlibCommonizer.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/KotlinNativeKlibCommonizer.kt index 7f4096263fb..21c00521c4e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/KotlinNativeKlibCommonizer.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/KotlinNativeKlibCommonizer.kt @@ -5,6 +5,8 @@ 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.target.KonanTarget import java.io.File @@ -16,12 +18,13 @@ import java.nio.file.StandardCopyOption import java.util.* internal fun runCommonizerInBulk( + project: Project, distributionDir: File, baseDestinationDir: File, targetGroups: List>, kotlinVersion: String ): List { - val commandLineParameters = mutableListOf() + val commandLineArguments = mutableListOf() val postActions = mutableListOf<() -> Unit>() val result = targetGroups.map { targets -> @@ -54,13 +57,13 @@ internal fun runCommonizerInBulk( directory = parentDir ) - commandLineParameters += "native-dist-commonize" - commandLineParameters += "-distribution-path" - commandLineParameters += distributionDir.toString() - commandLineParameters += "-output-path" - commandLineParameters += destinationTmpDir.toString() - commandLineParameters += "-targets" - commandLineParameters += orderedTargets.joinToString(separator = ",") + commandLineArguments += "native-dist-commonize" + commandLineArguments += "-distribution-path" + commandLineArguments += distributionDir.toString() + commandLineArguments += "-output-path" + commandLineArguments += destinationTmpDir.toString() + commandLineArguments += "-targets" + commandLineArguments += orderedTargets.joinToString(separator = ",") postActions.add { renameDirectory(destinationTmpDir, destinationDir) } } @@ -69,17 +72,17 @@ internal fun runCommonizerInBulk( } } - callCommonizerCLI(commandLineParameters) + callCommonizerCLI(project, commandLineArguments) postActions.forEach { it() } return result } -private fun callCommonizerCLI(commandLineParameters: List) { - if (commandLineParameters.isEmpty()) return +private fun callCommonizerCLI(project: Project, commandLineArguments: List) { + if (commandLineArguments.isEmpty()) return - // TODO: implement + KotlinNativeKlibCommonizerToolRunner(project).run(commandLineArguments) } private fun renameDirectory(source: File, destination: File) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/KotlinNativePlatformDependencies.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/KotlinNativePlatformDependencies.kt index 274f3996bc6..17204b8fec7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/KotlinNativePlatformDependencies.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/KotlinNativePlatformDependencies.kt @@ -88,6 +88,7 @@ private class NativePlatformDependencyResolver(val project: Project, val kotlinV val commonizedLibsDirs: Map = runCommonizerInBulk( + project = project, distributionDir = distributionDir, baseDestinationDir = distributionDir.resolve(KONAN_DISTRIBUTION_KLIB_DIR).resolve(KONAN_DISTRIBUTION_COMMONIZED_LIBS_DIR), targetGroups = targetGroups.map { it.second }, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt index 62af57293d0..2dc57c81f0f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt @@ -48,6 +48,7 @@ private val KOTLIN_SCRIPT_RUNTIME = "kotlin-script-runtime" private val KOTLIN_SCRIPT_COMMON = "kotlin-scripting-common" private val KOTLIN_SCRIPT_JVM = "kotlin-scripting-jvm" private val KOTLIN_REFLECT = "kotlin-reflect" +internal const val KOTLIN_KLIB_COMMONIZER_EMBEDDABLE = "kotlin-klib-commonizer-embeddable" internal fun findKotlinJvmCompilerClasspath(project: Project): List = findKotlinModuleJar(project, K2JVM_COMPILER_CLASS, KOTLIN_COMPILER_EMBEDDABLE).let {