Move commonizer to gradle task and attach to lazy file collection.
This commit is contained in:
+79
-54
@@ -5,8 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.native.internal
|
package org.jetbrains.kotlin.gradle.targets.native.internal
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
import org.jetbrains.kotlin.compilerRunner.KotlinNativeKlibCommonizerToolRunner
|
import org.jetbrains.kotlin.compilerRunner.KotlinNativeKlibCommonizerToolRunner
|
||||||
|
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_COMMONIZED_LIBS_DIR
|
||||||
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,73 +19,95 @@ import java.nio.file.*
|
|||||||
import java.nio.file.attribute.*
|
import java.nio.file.attribute.*
|
||||||
import java.time.*
|
import java.time.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal fun runCommonizerInBulk(
|
internal data class CommonizerTaskParams(
|
||||||
project: Project,
|
@get:InputDirectory val distributionDir: File,
|
||||||
distributionDir: File,
|
@get:InputDirectory val baseDestinationDir: File,
|
||||||
baseDestinationDir: File,
|
@Internal val targetGroups: List<Set<KonanTarget>>,
|
||||||
targetGroups: List<Set<KonanTarget>>,
|
@get:Input val kotlinVersion: String
|
||||||
kotlinVersion: String
|
) {
|
||||||
): List<File> {
|
@Internal
|
||||||
val commandLineArguments = mutableListOf<String>()
|
val commandLineArguments = mutableListOf<String>()
|
||||||
|
|
||||||
|
@Internal
|
||||||
val successPostActions = mutableListOf<() -> Unit>()
|
val successPostActions = mutableListOf<() -> Unit>()
|
||||||
|
|
||||||
|
@Internal
|
||||||
val failurePostActions = mutableListOf<() -> Unit>()
|
val failurePostActions = mutableListOf<() -> Unit>()
|
||||||
|
|
||||||
val destinationDirs = targetGroups.map { targets ->
|
// It isn't best option for "up-to-date" checker (for multi project build it will be started few times)
|
||||||
if (targets.size == 1) {
|
// but commonizer has inner check
|
||||||
// no need to commonize, just use the libraries from the distribution
|
@get:OutputDirectories
|
||||||
distributionDir.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
val destinationDirs: List<File>
|
||||||
} else {
|
|
||||||
// need stable order of targets for consistency
|
|
||||||
val orderedTargets = targets.sortedBy { it.name }
|
|
||||||
|
|
||||||
val discriminator = buildString {
|
// need stable order of targets for consistency
|
||||||
orderedTargets.joinTo(this, separator = "-")
|
private val orderedTargetGroups = targetGroups.map { it.sortedBy { target -> target.name } }
|
||||||
append("-")
|
|
||||||
append(kotlinVersion.toLowerCase().base64)
|
@Input
|
||||||
|
fun getTargetNames() = orderedTargetGroups.map { it.map { target -> target.name } }
|
||||||
|
|
||||||
|
init {
|
||||||
|
destinationDirs = orderedTargetGroups.map { orderedTargets ->
|
||||||
|
if (orderedTargets.size == 1) {
|
||||||
|
// no need to commonize, just use the libraries from the distribution
|
||||||
|
distributionDir.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||||
|
} else {
|
||||||
|
val discriminator = buildString {
|
||||||
|
orderedTargets.joinTo(this, separator = "-")
|
||||||
|
append("-")
|
||||||
|
append(kotlinVersion.toLowerCase().base64)
|
||||||
|
}
|
||||||
|
|
||||||
|
val destinationDir = baseDestinationDir.resolve(discriminator)
|
||||||
|
if (!destinationDir.isDirectory) {
|
||||||
|
val parentDir = destinationDir.parentFile
|
||||||
|
parentDir.mkdirs()
|
||||||
|
|
||||||
|
val destinationTmpDir = createTempDir(
|
||||||
|
prefix = "tmp-" + destinationDir.name,
|
||||||
|
suffix = ".new",
|
||||||
|
directory = parentDir
|
||||||
|
)
|
||||||
|
|
||||||
|
commandLineArguments += "native-dist-commonize"
|
||||||
|
commandLineArguments += "-distribution-path"
|
||||||
|
commandLineArguments += distributionDir.toString()
|
||||||
|
commandLineArguments += "-output-path"
|
||||||
|
commandLineArguments += destinationTmpDir.toString()
|
||||||
|
commandLineArguments += "-targets"
|
||||||
|
commandLineArguments += orderedTargets.joinToString(separator = ",")
|
||||||
|
|
||||||
|
successPostActions.add { renameDirectory(destinationTmpDir, destinationDir) }
|
||||||
|
failurePostActions.add { renameToTempAndDelete(destinationTmpDir) }
|
||||||
|
}
|
||||||
|
|
||||||
|
destinationDir
|
||||||
}
|
}
|
||||||
|
|
||||||
val destinationDir = baseDestinationDir.resolve(discriminator)
|
|
||||||
if (!destinationDir.isDirectory) {
|
|
||||||
val parentDir = destinationDir.parentFile
|
|
||||||
parentDir.mkdirs()
|
|
||||||
|
|
||||||
val destinationTmpDir = createTempDir(
|
|
||||||
prefix = "tmp-" + destinationDir.name,
|
|
||||||
suffix = ".new",
|
|
||||||
directory = parentDir
|
|
||||||
)
|
|
||||||
|
|
||||||
commandLineArguments += "native-dist-commonize"
|
|
||||||
commandLineArguments += "-distribution-path"
|
|
||||||
commandLineArguments += distributionDir.toString()
|
|
||||||
commandLineArguments += "-output-path"
|
|
||||||
commandLineArguments += destinationTmpDir.toString()
|
|
||||||
commandLineArguments += "-targets"
|
|
||||||
commandLineArguments += orderedTargets.joinToString(separator = ",")
|
|
||||||
|
|
||||||
successPostActions.add { renameDirectory(destinationTmpDir, destinationDir) }
|
|
||||||
failurePostActions.add { renameToTempAndDelete(destinationTmpDir) }
|
|
||||||
}
|
|
||||||
|
|
||||||
destinationDir
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// first of all remove directories with unused commonized libraries plus temporary directories with commonized libraries
|
internal const val COMMONIZER_TASK_NAME = "runCommonizer"
|
||||||
// that accidentally were not cleaned up before
|
|
||||||
cleanUp(baseDestinationDir, excludedDirectories = destinationDirs)
|
|
||||||
|
|
||||||
try {
|
internal open class CommonizerTask @Inject constructor(
|
||||||
callCommonizerCLI(project, commandLineArguments)
|
@Nested val params: CommonizerTaskParams
|
||||||
successPostActions.forEach { it() }
|
) : DefaultTask() {
|
||||||
} catch (e: Exception) {
|
|
||||||
failurePostActions.forEach { it() }
|
@TaskAction
|
||||||
throw e
|
fun run() {
|
||||||
|
// first of all remove directories with unused commonized libraries plus temporary directories with commonized libraries
|
||||||
|
// that accidentally were not cleaned up before
|
||||||
|
cleanUp(params.baseDestinationDir, excludedDirectories = params.destinationDirs)
|
||||||
|
|
||||||
|
try {
|
||||||
|
callCommonizerCLI(project, params.commandLineArguments)
|
||||||
|
params.successPostActions.forEach { it() }
|
||||||
|
} catch (e: Exception) {
|
||||||
|
params.failurePostActions.forEach { it() }
|
||||||
|
throw e
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return destinationDirs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun callCommonizerCLI(project: Project, commandLineArguments: List<String>) {
|
private fun callCommonizerCLI(project: Project, commandLineArguments: List<String>) {
|
||||||
+55
-32
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.native.internal
|
package org.jetbrains.kotlin.gradle.targets.native.internal
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
import org.jetbrains.kotlin.compilerRunner.konanHome
|
import org.jetbrains.kotlin.compilerRunner.konanHome
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||||
@@ -18,15 +19,31 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
|||||||
import org.jetbrains.kotlin.gradle.targets.metadata.getMetadataCompilationForSourceSet
|
import org.jetbrains.kotlin.gradle.targets.metadata.getMetadataCompilationForSourceSet
|
||||||
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.NativePlatformDependency.*
|
import org.jetbrains.kotlin.gradle.targets.native.internal.NativePlatformDependency.*
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
|
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
|
||||||
import org.jetbrains.kotlin.konan.library.*
|
import org.jetbrains.kotlin.konan.library.*
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
|
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
private val Project.isNativeDependencyPropagationEnabled: Boolean
|
private val Project.isNativeDependencyPropagationEnabled: Boolean
|
||||||
get() = (findProperty("kotlin.native.enableDependencyPropagation") as? String)?.toBoolean() ?: true
|
get() = (findProperty("kotlin.native.enableDependencyPropagation") as? String)?.toBoolean() ?: true
|
||||||
|
|
||||||
|
//for reflection call from KotlinCommonizerModelBuilder
|
||||||
|
@JvmOverloads
|
||||||
|
@JvmName("isAllowCommonizer")
|
||||||
|
internal fun Project.isAllowCommonizer(
|
||||||
|
kotlinVersion: String = getKotlinPluginVersion()!!
|
||||||
|
): Boolean {
|
||||||
|
multiplatformExtensionOrNull ?: return false
|
||||||
|
|
||||||
|
//register commonizer only for 1.4+, only for HMPP projects
|
||||||
|
return compareVersionNumbers(kotlinVersion, "1.4") >= 0
|
||||||
|
&& isKotlinGranularMetadataEnabled
|
||||||
|
&& !isNativeDependencyPropagationEnabled // temporary fix: turn on commonizer only when native deps propagation is disabled
|
||||||
|
}
|
||||||
|
|
||||||
internal fun Project.setUpKotlinNativePlatformDependencies() {
|
internal fun Project.setUpKotlinNativePlatformDependencies() {
|
||||||
if (multiplatformExtensionOrNull == null) {
|
if (multiplatformExtensionOrNull == null) {
|
||||||
// not a multiplatform project, nothing to set up
|
// not a multiplatform project, nothing to set up
|
||||||
@@ -34,26 +51,19 @@ internal fun Project.setUpKotlinNativePlatformDependencies() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val kotlinVersion = getKotlinPluginVersion()!!
|
val kotlinVersion = getKotlinPluginVersion()!!
|
||||||
|
val allowCommonizer = isAllowCommonizer(kotlinVersion)
|
||||||
// run commonizer only for 1.4+, only for HMPP projects and only on IDE sync
|
|
||||||
val allowCommonizer = compareVersionNumbers(kotlinVersion, "1.4") >= 0
|
|
||||||
&& isKotlinGranularMetadataEnabled
|
|
||||||
&& !isNativeDependencyPropagationEnabled // temporary fix: turn on commonizer only when native deps propagation is disabled
|
|
||||||
|
|
||||||
val dependencyResolver = NativePlatformDependencyResolver(this, kotlinVersion)
|
val dependencyResolver = NativePlatformDependencyResolver(this, kotlinVersion)
|
||||||
|
|
||||||
findSourceSetsToAddDependencies(allowCommonizer).forEach { (sourceSet: KotlinSourceSet, sourceSetDeps: Set<NativePlatformDependency>) ->
|
findSourceSetsToAddDependencies(allowCommonizer).forEach { (sourceSet: KotlinSourceSet, sourceSetDeps: Set<NativePlatformDependency>) ->
|
||||||
sourceSetDeps.forEach { sourceSetDep: NativePlatformDependency ->
|
sourceSetDeps.forEach { sourceSetDep: NativePlatformDependency ->
|
||||||
dependencyResolver.addForResolve(sourceSetDep) { resolvedFiles: Set<File> ->
|
dependencyResolver.addForResolve(sourceSetDep) { resolvedFiles: FileCollection ->
|
||||||
//add commonized klibs to metadata compilation
|
//add commonized klibs to metadata compilation
|
||||||
if (sourceSetDep is CommonizedCommon) {
|
if (sourceSetDep is CommonizedCommon) {
|
||||||
getMetadataCompilationForSourceSet(sourceSet)?.let { compilation ->
|
getMetadataCompilationForSourceSet(sourceSet)?.let { compilation ->
|
||||||
compilation.compileDependencyFiles += project.files(resolvedFiles)
|
compilation.compileDependencyFiles += resolvedFiles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resolvedFiles.forEach { resolvedFile ->
|
dependencies.add(sourceSet.implementationMetadataConfigurationName, dependencies.create(resolvedFiles))
|
||||||
dependencies.add(sourceSet.implementationMetadataConfigurationName, dependencies.create(files(resolvedFile)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,9 +90,9 @@ private class NativePlatformDependencyResolver(val project: Project, val kotlinV
|
|||||||
private val distributionLibsDir = distributionDir.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
private val distributionLibsDir = distributionDir.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||||
|
|
||||||
private var alreadyResolved = false
|
private var alreadyResolved = false
|
||||||
private val dependencies = mutableMapOf<NativePlatformDependency, MutableList<(Set<File>) -> Unit>>()
|
private val dependencies = mutableMapOf<NativePlatformDependency, MutableList<(FileCollection) -> Unit>>()
|
||||||
|
|
||||||
fun addForResolve(dependency: NativePlatformDependency, whenResolved: (Set<File>) -> Unit) {
|
fun addForResolve(dependency: NativePlatformDependency, whenResolved: (FileCollection) -> Unit) {
|
||||||
check(!alreadyResolved)
|
check(!alreadyResolved)
|
||||||
dependencies.computeIfAbsent(dependency) { mutableListOf() }.add(whenResolved)
|
dependencies.computeIfAbsent(dependency) { mutableListOf() }.add(whenResolved)
|
||||||
}
|
}
|
||||||
@@ -91,24 +101,32 @@ private class NativePlatformDependencyResolver(val project: Project, val kotlinV
|
|||||||
check(!alreadyResolved)
|
check(!alreadyResolved)
|
||||||
alreadyResolved = true
|
alreadyResolved = true
|
||||||
|
|
||||||
// first, run commonization
|
val targetGroups: List<Pair<CommonizedCommon, Set<KonanTarget>>> =
|
||||||
val targetGroups: List<Pair<CommonizedCommon, Set<KonanTarget>>> = dependencies.keys.filterIsInstance<CommonizedCommon>()
|
dependencies.keys
|
||||||
.map { it to it.targets }
|
.filterIsInstance<CommonizedCommon>()
|
||||||
|
.map { it to it.targets }
|
||||||
|
|
||||||
val commonizedLibsDirs: Map<CommonizedCommon, File> =
|
val commonizerTaskParams = CommonizerTaskParams(
|
||||||
runCommonizerInBulk(
|
distributionDir,
|
||||||
project = project,
|
distributionDir.resolve(KONAN_DISTRIBUTION_KLIB_DIR).resolve(KONAN_DISTRIBUTION_COMMONIZED_LIBS_DIR),
|
||||||
distributionDir = distributionDir,
|
targetGroups.map { it.second },
|
||||||
baseDestinationDir = distributionDir.resolve(KONAN_DISTRIBUTION_KLIB_DIR).resolve(KONAN_DISTRIBUTION_COMMONIZED_LIBS_DIR),
|
kotlinVersion
|
||||||
targetGroups = targetGroups.map { it.second },
|
)
|
||||||
kotlinVersion = kotlinVersion
|
|
||||||
).mapIndexed { index: Int, commonizedLibsDir: File ->
|
val commonizerTaskProvider = project.registerTask(
|
||||||
targetGroups[index].first to commonizedLibsDir
|
COMMONIZER_TASK_NAME,
|
||||||
}.toMap()
|
CommonizerTask::class.java,
|
||||||
|
listOf(commonizerTaskParams)
|
||||||
|
) {}
|
||||||
|
|
||||||
|
val commonizedLibsDirs =
|
||||||
|
commonizerTaskParams.destinationDirs
|
||||||
|
.mapIndexed { index: Int, commonizedLibsDir: File -> targetGroups[index].first to commonizedLibsDir }
|
||||||
|
.toMap()
|
||||||
|
|
||||||
// then, resolve dependencies one by one
|
// then, resolve dependencies one by one
|
||||||
dependencies.forEach { (dependency, actions) ->
|
dependencies.forEach { (dependency, actions) ->
|
||||||
val libs = when (dependency) {
|
val fileCollection = when (dependency) {
|
||||||
is OutOfDistributionCommon -> {
|
is OutOfDistributionCommon -> {
|
||||||
/* stdlib, endorsed libs */
|
/* stdlib, endorsed libs */
|
||||||
var hasStdlib = false
|
var hasStdlib = false
|
||||||
@@ -122,28 +140,33 @@ private class NativePlatformDependencyResolver(val project: Project, val kotlinV
|
|||||||
|
|
||||||
if (!hasStdlib) warnAboutMissingNativeStdlib()
|
if (!hasStdlib) warnAboutMissingNativeStdlib()
|
||||||
|
|
||||||
libs
|
project.files(libs)
|
||||||
}
|
}
|
||||||
|
|
||||||
is OutOfDistributionPlatform -> {
|
is OutOfDistributionPlatform -> {
|
||||||
/* platform libs for a specific target */
|
/* platform libs for a specific target */
|
||||||
libsInPlatformDir(distributionLibsDir, dependency.target)
|
project.files(libsInPlatformDir(distributionLibsDir, dependency.target))
|
||||||
}
|
}
|
||||||
|
|
||||||
is CommonizedCommon -> {
|
is CommonizedCommon -> {
|
||||||
/* commonized platform libs with expect declarations */
|
/* commonized platform libs with expect declarations */
|
||||||
val commonizedLibsDir = commonizedLibsDirs.getValue(dependency)
|
val commonizedLibsDir = commonizedLibsDirs.getValue(dependency)
|
||||||
libsInCommonDir(commonizedLibsDir)
|
project.files(Callable {
|
||||||
|
libsInCommonDir(commonizedLibsDir)
|
||||||
|
}).builtBy(commonizerTaskProvider)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is CommonizedPlatform -> {
|
is CommonizedPlatform -> {
|
||||||
/* commonized platform libs with actual declarations */
|
/* commonized platform libs with actual declarations */
|
||||||
val commonizedLibsDir = commonizedLibsDirs.getValue(dependency.common)
|
val commonizedLibsDir = commonizedLibsDirs.getValue(dependency.common)
|
||||||
libsInPlatformDir(commonizedLibsDir, dependency.target) + libsInCommonDir(commonizedLibsDir)
|
project.files(Callable {
|
||||||
|
libsInPlatformDir(commonizedLibsDir, dependency.target) + libsInCommonDir(commonizedLibsDir)
|
||||||
|
}).builtBy(commonizerTaskProvider)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actions.forEach { it(libs) }
|
actions.forEach { it(fileCollection) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user