[Commonizer] Don't fail when one of targets is not supported at the host
^KMM-214
This commit is contained in:
+3
-5
@@ -5,18 +5,16 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.descriptors.commonizer.cli
|
package org.jetbrains.kotlin.descriptors.commonizer.cli
|
||||||
|
|
||||||
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.target.KonanTarget.Companion.predefinedTargets
|
||||||
|
|
||||||
internal object NativeTargetsOptionType : OptionType<List<KonanTarget>>("targets", "Comma-separated list of hardware targets") {
|
internal object NativeTargetsOptionType : OptionType<List<KonanTarget>>("targets", "Comma-separated list of hardware targets") {
|
||||||
private val hostManager = HostManager()
|
|
||||||
|
|
||||||
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<List<KonanTarget>> {
|
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<List<KonanTarget>> {
|
||||||
val targetNames = rawValue.split(',')
|
val targetNames = rawValue.split(',')
|
||||||
if (targetNames.isEmpty()) onError("No hardware targets specified: $rawValue")
|
if (targetNames.isEmpty()) onError("No hardware targets specified: $rawValue")
|
||||||
|
|
||||||
val targets = targetNames.mapTo(HashSet<KonanTarget>()) { targetName ->
|
val targets = targetNames.mapTo(HashSet()) { targetName ->
|
||||||
hostManager.targets[targetName] ?: onError("Unknown hardware target: $targetName")
|
predefinedTargets[targetName] ?: onError("Unknown hardware target: $targetName")
|
||||||
}.toList()
|
}.toList()
|
||||||
|
|
||||||
return Option(this, targets)
|
return Option(this, targets)
|
||||||
|
|||||||
+86
-48
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVe
|
|||||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.metadataVersion
|
import org.jetbrains.kotlin.backend.common.serialization.metadata.metadataVersion
|
||||||
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
|
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.*
|
import org.jetbrains.kotlin.descriptors.commonizer.*
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.Target
|
import org.jetbrains.kotlin.descriptors.commonizer.Target
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.ResettableClockMark
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.ResettableClockMark
|
||||||
@@ -80,17 +81,19 @@ class NativeDistributionCommonizer(
|
|||||||
val stdlib = loadLibrary(stdlibPath)
|
val stdlib = loadLibrary(stdlibPath)
|
||||||
|
|
||||||
return targets.associate { target ->
|
return targets.associate { target ->
|
||||||
val platformLibsPath = repository.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
val inputTarget = InputTarget(target.name, target)
|
||||||
.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR)
|
|
||||||
.resolve(target.name)
|
|
||||||
|
|
||||||
val platformLibs = platformLibsPath.takeIf { it.isDirectory }
|
val platformLibs = inputTarget.platformLibrariesSource
|
||||||
|
.takeIf { it.isDirectory }
|
||||||
?.listFiles()
|
?.listFiles()
|
||||||
?.takeIf { it.isNotEmpty() }
|
?.takeIf { it.isNotEmpty() }
|
||||||
?.map { loadLibrary(it) }
|
?.map { loadLibrary(it) }
|
||||||
?: logger.fatal("no platform libraries found for target $target in $platformLibsPath")
|
.orEmpty()
|
||||||
|
|
||||||
InputTarget(target.name, target) to NativeDistributionLibraries(stdlib, platformLibs)
|
if (platformLibs.isEmpty())
|
||||||
|
logger.warning("no platform libraries found for target $target, this target will be excluded from commonization")
|
||||||
|
|
||||||
|
inputTarget to NativeDistributionLibraries(stdlib, platformLibs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,15 +122,18 @@ class NativeDistributionCommonizer(
|
|||||||
return library
|
return library
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun commonize(librariesByTargets: Map<InputTarget, NativeDistributionLibraries>): CommonizationPerformed {
|
private fun commonize(librariesByTargets: Map<InputTarget, NativeDistributionLibraries>): Result {
|
||||||
val statsCollector = if (withStats) NativeStatsCollector(targets, destination) else null
|
val statsCollector = if (withStats) NativeStatsCollector(targets, destination) else null
|
||||||
statsCollector.use {
|
statsCollector.use {
|
||||||
val parameters = Parameters(statsCollector).apply {
|
val parameters = Parameters(statsCollector).apply {
|
||||||
librariesByTargets.forEach { (target, libraries) ->
|
librariesByTargets.forEach { (target, libraries) ->
|
||||||
|
if (libraries.platformLibs.isEmpty()) return@forEach
|
||||||
|
|
||||||
val provider = NativeDistributionModulesProvider(
|
val provider = NativeDistributionModulesProvider(
|
||||||
storageManager = LockBasedStorageManager("Target $target"),
|
storageManager = LockBasedStorageManager("Target $target"),
|
||||||
libraries = libraries
|
libraries = libraries
|
||||||
)
|
)
|
||||||
|
|
||||||
addTarget(
|
addTarget(
|
||||||
TargetProvider(
|
TargetProvider(
|
||||||
target = target,
|
target = target,
|
||||||
@@ -139,20 +145,53 @@ class NativeDistributionCommonizer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = runCommonization(parameters)
|
return runCommonization(parameters)
|
||||||
return when (result) {
|
|
||||||
is NothingToCommonize -> logger.fatal("too few targets specified: ${librariesByTargets.keys}")
|
|
||||||
is CommonizationPerformed -> result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveModules(
|
private fun saveModules(
|
||||||
originalLibrariesByTargets: Map<InputTarget, NativeDistributionLibraries>,
|
originalLibrariesByTargets: Map<InputTarget, NativeDistributionLibraries>,
|
||||||
result: CommonizationPerformed
|
result: Result
|
||||||
) {
|
) {
|
||||||
// optimization: stdlib and endorsed libraries effectively remain the same across all Kotlin/Native targets,
|
// optimization: stdlib and endorsed libraries effectively remain the same across all Kotlin/Native targets,
|
||||||
// so they can be just copied to the new destination without running serializer
|
// so they can be just copied to the new destination without running serializer
|
||||||
|
copyCommonStandardLibraries()
|
||||||
|
|
||||||
|
when (result) {
|
||||||
|
is NothingToCommonize -> {
|
||||||
|
// It may happen that all targets to be commonized (or at least all but one target) miss platform libraries.
|
||||||
|
// In such case commonizer will do nothing and return a special result value 'NothingToCommonize'.
|
||||||
|
// So, let's just copy platform libraries from those target where they are to the new destination.
|
||||||
|
originalLibrariesByTargets.keys.forEach(::copyTargetAsIs)
|
||||||
|
}
|
||||||
|
|
||||||
|
is CommonizationPerformed -> {
|
||||||
|
val serializer = KlibMetadataMonolithicSerializer(
|
||||||
|
languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
|
||||||
|
metadataVersion = KlibMetadataVersion.INSTANCE,
|
||||||
|
skipExpects = false
|
||||||
|
)
|
||||||
|
|
||||||
|
// 'targetsToCopy' are some targets with empty set of platform libraries
|
||||||
|
val targetsToCopy = originalLibrariesByTargets.keys - result.concreteTargets
|
||||||
|
targetsToCopy.forEach(::copyTargetAsIs)
|
||||||
|
|
||||||
|
val targetsToSerialize = result.concreteTargets + result.commonTarget
|
||||||
|
targetsToSerialize.forEach { target ->
|
||||||
|
val newModules = result.modulesByTargets.getValue(target)
|
||||||
|
|
||||||
|
val manifestProvider = when (target) {
|
||||||
|
is InputTarget -> originalLibrariesByTargets.getValue(target)
|
||||||
|
is OutputTarget -> CommonNativeManifestDataProvider(originalLibrariesByTargets.values)
|
||||||
|
}
|
||||||
|
|
||||||
|
serializeTarget(target, newModules, manifestProvider, serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyCommonStandardLibraries() {
|
||||||
if (copyStdlib || copyEndorsedLibs) {
|
if (copyStdlib || copyEndorsedLibs) {
|
||||||
repository.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
repository.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||||
.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
|
.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
|
||||||
@@ -168,50 +207,38 @@ class NativeDistributionCommonizer(
|
|||||||
libraryOrigin.copyRecursively(libraryDestination)
|
libraryOrigin.copyRecursively(libraryDestination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val commonManifestProvider = CommonNativeManifestDataProvider(originalLibrariesByTargets.values)
|
private fun copyTargetAsIs(target: InputTarget) {
|
||||||
|
val librariesDestination = target.librariesDestination
|
||||||
|
librariesDestination.mkdirs() // always create an empty directory even if there is nothing to copy
|
||||||
|
|
||||||
val serializer = KlibMetadataMonolithicSerializer(
|
val librariesSource = target.platformLibrariesSource
|
||||||
languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
|
if (librariesSource.isDirectory) librariesSource.copyRecursively(librariesDestination)
|
||||||
metadataVersion = KlibMetadataVersion.INSTANCE,
|
}
|
||||||
skipExpects = false
|
|
||||||
)
|
|
||||||
|
|
||||||
fun serializeTarget(target: Target) {
|
private fun serializeTarget(
|
||||||
val libsDestination: File
|
target: Target,
|
||||||
val manifestProvider: NativeManifestDataProvider
|
newModules: Collection<ModuleDescriptor>,
|
||||||
|
manifestProvider: NativeManifestDataProvider,
|
||||||
|
serializer: KlibMetadataMonolithicSerializer
|
||||||
|
) {
|
||||||
|
val librariesDestination = target.librariesDestination
|
||||||
|
|
||||||
when (target) {
|
for (newModule in newModules) {
|
||||||
is InputTarget -> {
|
val libraryName = newModule.name
|
||||||
libsDestination = destination.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR).resolve(target.konanTarget!!.name)
|
|
||||||
manifestProvider = originalLibrariesByTargets.getValue(target)
|
|
||||||
}
|
|
||||||
is OutputTarget -> {
|
|
||||||
libsDestination = destination.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
|
|
||||||
manifestProvider = commonManifestProvider
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val newModules = result.modulesByTargets.getValue(target)
|
if (!shouldBeSerialized(libraryName))
|
||||||
|
continue
|
||||||
|
|
||||||
for (newModule in newModules) {
|
val metadata = serializer.serializeModule(newModule)
|
||||||
val libraryName = newModule.name
|
val plainName = libraryName.asString().removePrefix("<").removeSuffix(">")
|
||||||
|
|
||||||
if (!shouldBeSerialized(libraryName))
|
val manifestData = manifestProvider.getManifest(plainName)
|
||||||
continue
|
val libraryDestination = librariesDestination.resolve(plainName)
|
||||||
|
|
||||||
val metadata = serializer.serializeModule(newModule)
|
writeLibrary(metadata, manifestData, libraryDestination)
|
||||||
val plainName = libraryName.asString().removePrefix("<").removeSuffix(">")
|
|
||||||
|
|
||||||
val manifestData = manifestProvider.getManifest(plainName)
|
|
||||||
val libraryDestination = libsDestination.resolve(plainName)
|
|
||||||
|
|
||||||
writeLibrary(metadata, manifestData, libraryDestination)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.concreteTargets.forEach(::serializeTarget)
|
|
||||||
result.commonTarget.let(::serializeTarget)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun writeLibrary(
|
private fun writeLibrary(
|
||||||
@@ -233,6 +260,17 @@ class NativeDistributionCommonizer(
|
|||||||
library.commit()
|
library.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val InputTarget.platformLibrariesSource: File
|
||||||
|
get() = repository.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||||
|
.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR)
|
||||||
|
.resolve(name)
|
||||||
|
|
||||||
|
private val Target.librariesDestination: File
|
||||||
|
get() = when (this) {
|
||||||
|
is InputTarget -> destination.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR).resolve(name)
|
||||||
|
is OutputTarget -> destination.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
|
||||||
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
fun shouldBeSerialized(libraryName: Name) =
|
fun shouldBeSerialized(libraryName: Name) =
|
||||||
libraryName != NATIVE_STDLIB_MODULE_NAME && libraryName != KlibResolvedModuleDescriptorsFactoryImpl.FORWARD_DECLARATIONS_MODULE_NAME
|
libraryName != NATIVE_STDLIB_MODULE_NAME && libraryName != KlibResolvedModuleDescriptorsFactoryImpl.FORWARD_DECLARATIONS_MODULE_NAME
|
||||||
|
|||||||
Reference in New Issue
Block a user