[Commonizer] Gracefully handle absent targets for hierarchical commonization

This commit is contained in:
sebastian.sellmair
2021-04-06 15:52:00 +02:00
parent bbe499c1b6
commit 933c52d470
26 changed files with 297 additions and 118 deletions
@@ -14,16 +14,17 @@ class CommonizerParameters(
val outputTarget: SharedCommonizerTarget,
val manifestProvider: TargetDependent<NativeManifestDataProvider>,
val dependenciesProvider: TargetDependent<ModulesProvider?>,
val targetProviders: TargetDependent<TargetProvider>,
val targetProviders: TargetDependent<TargetProvider?>,
val resultsConsumer: ResultsConsumer,
val statsCollector: StatsCollector? = null,
val progressLogger: ((String) -> Unit)? = null
val progressLogger: ((String) -> Unit)? = null,
)
fun CommonizerParameters.getCommonModuleNames(): Set<String> {
if (targetProviders.size < 2) return emptySet() // too few targets
val supportedTargets = targetProviders.filterNonNull()
if (supportedTargets.size < 2) return emptySet() // too few targets
val allModuleNames: List<Set<String>> = targetProviders.toList().map { targetProvider ->
val allModuleNames: List<Set<String>> = supportedTargets.toList().map { targetProvider ->
targetProvider.modulesProvider.loadModuleInfos().mapTo(HashSet()) { it.name }
}
@@ -12,7 +12,7 @@ sealed interface TargetDependent<T> : Iterable<T> {
val targets: List<CommonizerTarget>
fun indexOf(target: CommonizerTarget): Int = targets.indexOf(target)
fun <R : Any> map(mapper: (target: CommonizerTarget, T) -> R): TargetDependent<R> {
fun <R> map(mapper: (target: CommonizerTarget, T) -> R): TargetDependent<R> {
return TargetDependent(targets) { target ->
mapper(target, get(target))
}
@@ -54,6 +54,9 @@ internal fun <T, R> TargetDependent<T>.mapTargets(mapper: (CommonizerTarget) ->
return TargetDependent(targets) { target -> mapper(target) }
}
internal inline fun <T> TargetDependent<T>.forEachWithTarget(action: (target: CommonizerTarget, T) -> Unit) {
targets.forEach { target -> action(target, this[target]) }
}
internal fun <T> TargetDependent(map: Map<out CommonizerTarget, T>): TargetDependent<T> {
return MapBasedTargetDependent(map.toMap())
@@ -66,6 +69,7 @@ internal fun <T> TargetDependent(keys: Iterable<CommonizerTarget>, factory: (tar
internal fun <T> EagerTargetDependent(keys: Iterable<CommonizerTarget>, factory: (target: CommonizerTarget) -> T): TargetDependent<T> {
return keys.associateWith(factory).toTargetDependent()
}
private class MapBasedTargetDependent<T>(private val map: Map<CommonizerTarget, T>) : TargetDependent<T> {
override val targets: List<CommonizerTarget> = map.keys.toList()
override fun get(target: CommonizerTarget): T = map.getValue(target)
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.cli
import org.jetbrains.kotlin.commonizer.CommonizerDependency
import org.jetbrains.kotlin.commonizer.parseCommonizerDependency
internal abstract class DependenciesLibrariesSetOptionType(
mandatory: Boolean,
alias: String,
description: String
) : OptionType<List<CommonizerDependency>>(
mandatory = mandatory,
alias = alias,
description = description
) {
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<List<CommonizerDependency>> {
if (rawValue.isBlank()) {
return Option(this, emptyList())
}
return Option(this, rawValue.split(";").map(::parseCommonizerDependency))
}
}
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.commonizer.cli
internal object DependencyLibrariesOptionType : LibrariesSetOptionType(
internal object DependencyLibrariesOptionType : DependenciesLibrariesSetOptionType(
mandatory = false,
alias = "dependency-libraries",
description = "';' separated list of klib file paths that can be used as dependency"
@@ -47,7 +47,7 @@ internal class NativeKlibCommonize(options: Collection<Option<*>>) : Task(option
val distribution = KonanDistribution(getMandatory<File, NativeDistributionOptionType>())
val destination = getMandatory<File, OutputOptionType>()
val targetLibraries = getMandatory<List<File>, InputLibrariesOptionType>()
val dependencyLibraries = getOptional<List<File>, DependencyLibrariesOptionType>().orEmpty()
val dependencyLibraries = getOptional<List<CommonizerDependency>, DependencyLibrariesOptionType>().orEmpty()
val outputCommonizerTarget = compatGetOutputTarget()
val statsType = getOptional<StatsType, StatsTypeOptionType> { it == "log-stats" } ?: StatsType.NONE
@@ -71,7 +71,7 @@ internal class NativeKlibCommonize(options: Collection<Option<*>>) : Task(option
outputTarget = outputCommonizerTarget,
repository = repository,
dependencies = StdlibRepository(distribution, libraryLoader) +
FilesRepository(dependencyLibraries.toSet(), libraryLoader),
CommonizerDependencyRepository(dependencyLibraries.toSet(), libraryLoader),
resultsConsumer = resultsConsumer,
statsCollector = statsCollector,
progressLogger = progressLogger
@@ -100,7 +100,7 @@ internal class NativeDistributionCommonize(options: Collection<Option<*>>) : Tas
val progressLogger = ProgressLogger(CliLoggerAdapter(2), startImmediately = true)
val libraryLoader = DefaultNativeLibraryLoader(progressLogger)
val repository = KonanDistributionRepository(distribution, outputTarget.allLeaves(), libraryLoader)
val repository = KonanDistributionRepository(distribution, outputTarget.konanTargets, libraryLoader)
val statsCollector = StatsCollector(statsType, outputTarget.withAllAncestors().toList())
val resultsConsumer = buildResultsConsumer {
@@ -7,14 +7,15 @@ package org.jetbrains.kotlin.commonizer
import kotlinx.metadata.klib.ChunkedKlibModuleFragmentWriteStrategy
import org.jetbrains.kotlin.commonizer.ResultsConsumer.ModuleResult
import org.jetbrains.kotlin.commonizer.ResultsConsumer.ModuleResult.Missing
import org.jetbrains.kotlin.commonizer.ResultsConsumer.Status
import org.jetbrains.kotlin.commonizer.core.CommonizationVisitor
import org.jetbrains.kotlin.commonizer.mergedtree.CirCommonizedClassifierNodes
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.indexOfCommon
import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.indices
import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.targetIndices
import org.jetbrains.kotlin.commonizer.mergedtree.CirRootNode
import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer
import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer.serializeSingleTarget
import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot
import org.jetbrains.kotlin.commonizer.tree.assembleCirTree
import org.jetbrains.kotlin.commonizer.tree.deserializeCirTree
@@ -38,7 +39,7 @@ private fun commonize(
parameters: CommonizerParameters,
storageManager: StorageManager,
target: SharedCommonizerTarget,
): CirRootNode {
): CirRootNode? {
val cirTrees = getCirTree(parameters, storageManager, target)
parameters.progressLogger?.invoke("Build cir tree for $target")
@@ -48,11 +49,11 @@ private fun commonize(
commonDependencies = parameters.dependencyClassifiers(target)
)
val mergedTree = mergeCirTree(storageManager, classifiers, cirTrees)
val mergedTree = merge(storageManager, classifiers, cirTrees) ?: return null
mergedTree.accept(CommonizationVisitor(classifiers, mergedTree), Unit)
parameters.progressLogger?.invoke("Commonized declarations for $target")
serialize(mergedTree, parameters)
serialize(parameters, mergedTree, target)
parameters.progressLogger?.invoke("Commonized target $target")
return mergedTree
@@ -60,40 +61,61 @@ private fun commonize(
private fun getCirTree(
parameters: CommonizerParameters, storageManager: StorageManager, target: SharedCommonizerTarget
): TargetDependent<CirTreeRoot> {
): TargetDependent<CirTreeRoot?> {
return EagerTargetDependent(target.targets) { childTarget ->
when (childTarget) {
is LeafCommonizerTarget -> deserializeCirTree(parameters, parameters.targetProviders[childTarget])
is SharedCommonizerTarget -> commonize(parameters, storageManager, childTarget).assembleCirTree()
is LeafCommonizerTarget -> deserialize(parameters, childTarget)
is SharedCommonizerTarget -> commonize(parameters, storageManager, childTarget)?.assembleCirTree()
}
}
}
private fun serialize(mergedTree: CirRootNode, parameters: CommonizerParameters) {
for (targetIndex in mergedTree.indices) {
serializeTarget(mergedTree, targetIndex, parameters)
}
private fun deserialize(parameters: CommonizerParameters, target: CommonizerTarget): CirTreeRoot? {
val targetProvider = parameters.targetProviders[target] ?: return null
return deserializeCirTree(parameters, targetProvider)
}
private fun serializeTarget(mergedTree: CirRootNode, targetIndex: Int, parameters: CommonizerParameters) {
val target = mergedTree.getTarget(targetIndex)
private fun merge(
storageManager: StorageManager, classifiers: CirKnownClassifiers, cirTrees: TargetDependent<CirTreeRoot?>,
): CirRootNode? {
val availableTrees = cirTrees.filterNonNull()
/* Nothing to merge */
if (availableTrees.size == 0) return null
if (target in parameters.targetProviders.targets) {
parameters.targetProviders[target].modulesProvider.loadModuleInfos()
/* No propagation from leaves */
if (availableTrees.size == 1 && availableTrees.targets.single() is LeafCommonizerTarget) return null
return mergeCirTree(storageManager, classifiers, availableTrees)
}
private fun serialize(parameters: CommonizerParameters, mergedTree: CirRootNode, commonTarget: CommonizerTarget) {
for (targetIndex in mergedTree.targetIndices) {
val target = mergedTree.targetDeclarations[targetIndex]?.target ?: continue
serializeMissingModules(parameters, target)
if (target is LeafCommonizerTarget) {
serialize(parameters, mergedTree, target, targetIndex)
}
}
serialize(parameters, mergedTree, commonTarget, mergedTree.indexOfCommon)
}
private fun serialize(parameters: CommonizerParameters, mergedTree: CirRootNode, target: CommonizerTarget, targetIndex: Int) {
serializeSingleTarget(mergedTree, targetIndex, parameters.statsCollector) { metadataModule ->
val libraryName = metadataModule.name
val serializedMetadata = with(metadataModule.write(KLIB_FRAGMENT_WRITE_STRATEGY)) {
SerializedMetadata(header, fragments, fragmentNames)
}
val manifestData = parameters.manifestProvider[target].getManifest(libraryName)
parameters.resultsConsumer.consume(target, ModuleResult.Commonized(libraryName, serializedMetadata, manifestData))
}
parameters.resultsConsumer.targetConsumed(target)
}
private fun serializeMissingModules(parameters: CommonizerParameters, requestedTarget: CommonizerTarget) {
if (requestedTarget in parameters.targetProviders.targets) {
parameters.targetProviders[requestedTarget]?.modulesProvider?.loadModuleInfos().orEmpty()
.filter { it.name !in parameters.getCommonModuleNames() }
.forEach { missingModule -> parameters.resultsConsumer.consume(target, ModuleResult.Missing(missingModule.originalLocation)) }
}
if (targetIndex == mergedTree.indexOfCommon || target is LeafCommonizerTarget) {
CirTreeSerializer.serializeSingleTarget(mergedTree, targetIndex, parameters.statsCollector) { metadataModule ->
val libraryName = metadataModule.name
val serializedMetadata = with(metadataModule.write(KLIB_FRAGMENT_WRITE_STRATEGY)) {
SerializedMetadata(header, fragments, fragmentNames)
}
val manifestData = parameters.manifestProvider[target].getManifest(libraryName)
parameters.resultsConsumer.consume(target, ModuleResult.Commonized(libraryName, serializedMetadata, manifestData))
}
parameters.resultsConsumer.targetConsumed(target)
.forEach { missingModule -> parameters.resultsConsumer.consume(requestedTarget, Missing(missingModule.originalLocation)) }
}
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.commonizer.*
import org.jetbrains.kotlin.commonizer.repository.Repository
import org.jetbrains.kotlin.commonizer.stats.StatsCollector
import org.jetbrains.kotlin.commonizer.utils.ProgressLogger
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
internal class LibraryCommonizer internal constructor(
private val outputTarget: SharedCommonizerTarget,
@@ -26,26 +27,27 @@ internal class LibraryCommonizer internal constructor(
progressLogger.logTotal()
}
private fun loadLibraries(): TargetDependent<NativeLibrariesToCommonize> {
val librariesByTargets = outputTarget.allLeaves().associateWith { target ->
NativeLibrariesToCommonize(repository.getLibraries(target).toList())
private fun loadLibraries(): TargetDependent<NativeLibrariesToCommonize?> {
val libraries = EagerTargetDependent(outputTarget.allLeaves()) { target ->
repository.getLibraries(target).toList().ifNotEmpty(::NativeLibrariesToCommonize)
}
librariesByTargets.forEach { (target, librariesToCommonize) ->
if (librariesToCommonize.libraries.isEmpty()) {
progressLogger.warning("No platform libraries found for target ${target.prettyName}. This target will be excluded from commonization.")
}
libraries.forEachWithTarget { target, librariesOrNull ->
if (librariesOrNull == null)
progressLogger.warning(
"No libraries found for target ${target.prettyName}. This target will be excluded from commonization."
)
}
progressLogger.log("Resolved libraries to be commonized")
return TargetDependent(librariesByTargets)
return libraries
}
private fun commonizeAndSaveResults(allLibraries: TargetDependent<NativeLibrariesToCommonize>) {
private fun commonizeAndSaveResults(libraries: TargetDependent<NativeLibrariesToCommonize?>) {
val parameters = CommonizerParameters(
outputTarget = outputTarget,
targetProviders = TargetDependent(outputTarget.allLeaves()) { target -> createTargetProvider(target, allLibraries[target]) }
.filterNonNull(),
manifestProvider = createManifestProvider(allLibraries),
targetProviders = libraries.map { target, targetLibraries -> createTargetProvider(target, targetLibraries) },
manifestProvider = createManifestProvider(libraries),
dependenciesProvider = createDependenciesProvider(),
resultsConsumer = resultsConsumer,
statsCollector = statsCollector,
@@ -54,8 +56,8 @@ internal class LibraryCommonizer internal constructor(
runCommonization(parameters)
}
private fun createTargetProvider(target: CommonizerTarget, libraries: NativeLibrariesToCommonize): TargetProvider? {
if (libraries.libraries.isEmpty()) return null
private fun createTargetProvider(target: CommonizerTarget, libraries: NativeLibrariesToCommonize?): TargetProvider? {
if (libraries == null) return null
return TargetProvider(
target = target,
modulesProvider = DefaultModulesProvider.create(libraries)
@@ -69,13 +71,13 @@ internal class LibraryCommonizer internal constructor(
}
private fun createManifestProvider(
libraries: TargetDependent<NativeLibrariesToCommonize>
libraries: TargetDependent<NativeLibrariesToCommonize?>
): TargetDependent<NativeManifestDataProvider> {
return TargetDependent(outputTarget.withAllAncestors()) { target ->
when (target) {
is LeafCommonizerTarget -> libraries[target]
is LeafCommonizerTarget -> libraries[target] ?: error("Can't provide manifest for missing target $target")
is SharedCommonizerTarget -> CommonNativeManifestDataProvider(
target.allLeaves().map { leafTarget -> libraries[leafTarget] }
target.allLeaves().mapNotNull { leafTarget -> libraries.getOrNull(leafTarget) }
)
}
}
@@ -8,9 +8,6 @@
package org.jetbrains.kotlin.commonizer.konan
import gnu.trove.THashMap
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.library.KotlinLibrary
interface NativeManifestDataProvider {
@@ -22,6 +22,8 @@ interface CirNode<T : CirDeclaration, R : CirDeclaration> {
companion object {
inline val CirNode<*, *>.indices: IntRange get() = 0..targetDeclarations.size
inline val CirNode<*, *>.targetIndices: List<Int> get() = indices - indexOfCommon
inline val CirNode<*, *>.indexOfCommon: Int
get() = targetDeclarations.size
@@ -19,9 +19,6 @@ class CirRootNode(
) : CirNode<CirRoot, CirRoot> {
val modules: MutableMap<CirName, CirModuleNode> = THashMap()
fun getTarget(targetIndex: Int): CommonizerTarget =
(if (targetIndex == indexOfCommon) commonDeclaration() else targetDeclarations[targetIndex])!!.target
override fun <T, R> accept(visitor: CirNodeVisitor<T, R>, data: T): R =
visitor.visitRootNode(this, data)
@@ -23,7 +23,7 @@ internal class RootMerger(
val commonModuleNames = parameters.getCommonModuleNames()
val missingModuleInfosByTargets = mutableMapOf<CommonizerTarget, Collection<ModulesProvider.ModuleInfo>>()
parameters.targetProviders.forEachIndexed { targetIndex, targetProvider ->
parameters.targetProviders.filterNotNull().forEachIndexed { targetIndex, targetProvider ->
val allModuleInfos = targetProvider.modulesProvider.loadModuleInfos()
val (commonModuleInfos, missingModuleInfos) = allModuleInfos.partition { it.name in commonModuleNames }
@@ -293,7 +293,6 @@ private class CirTreeSerializationVisitor(
internal data class CirTreeSerializationContext(
val targetIndex: Int,
val target: CommonizerTarget,
val isCommon: Boolean,
val typeParameterIndexOffset: Int,
val currentPath: Path
@@ -332,7 +331,6 @@ internal data class CirTreeSerializationContext(
return CirTreeSerializationContext(
targetIndex = targetIndex,
target = target,
isCommon = isCommon,
typeParameterIndexOffset = 0,
currentPath = Path.Module(moduleName)
@@ -344,7 +342,6 @@ internal data class CirTreeSerializationContext(
return CirTreeSerializationContext(
targetIndex = targetIndex,
target = target,
isCommon = isCommon,
typeParameterIndexOffset = 0,
currentPath = Path.Package(packageName)
@@ -369,7 +366,6 @@ internal data class CirTreeSerializationContext(
return CirTreeSerializationContext(
targetIndex = targetIndex,
target = target,
isCommon = isCommon,
typeParameterIndexOffset = typeParameterIndexOffset + outerClassTypeParametersCount,
currentPath = newPath
@@ -394,7 +390,6 @@ internal data class CirTreeSerializationContext(
return CirTreeSerializationContext(
targetIndex = targetIndex,
target = target,
isCommon = isCommon,
typeParameterIndexOffset = typeParameterIndexOffset + ownerClassTypeParametersCount,
currentPath = newPath
@@ -417,7 +412,6 @@ internal data class CirTreeSerializationContext(
fun rootContext(rootNode: CirRootNode, targetIndex: Int): CirTreeSerializationContext =
CirTreeSerializationContext(
targetIndex = targetIndex,
target = rootNode.getTarget(targetIndex),
isCommon = rootNode.indexOfCommon == targetIndex,
typeParameterIndexOffset = 0,
currentPath = Path.Empty
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.repository
import org.jetbrains.kotlin.commonizer.*
import org.jetbrains.kotlin.commonizer.NativeLibraryLoader
import org.jetbrains.kotlin.commonizer.konan.NativeLibrary
internal class CommonizerDependencyRepository(
private val dependencies: Set<CommonizerDependency>,
private val libraryLoader: NativeLibraryLoader
) : Repository {
private val nonTargetedDependencyRepository = FilesRepository(
libraryFiles = dependencies.filterIsInstance<NonTargetedCommonizerDependency>().map { it.file }.toSet(),
libraryLoader = libraryLoader
)
private val targetedDependencies: Map<CommonizerTarget, Lazy<Set<NativeLibrary>>> by lazy {
dependencies
.filterIsInstance<TargetedCommonizerDependency>()
.groupBy { it.target }
.mapValues { (_, dependencies) -> lazy { dependencies.map { libraryLoader(it.file) }.toSet() } }
}
override fun getLibraries(target: CommonizerTarget): Set<NativeLibrary> {
return targetedDependencies[target]?.value.orEmpty() + nonTargetedDependencyRepository.getLibraries(target)
}
}
@@ -17,7 +17,7 @@ internal class FilesRepository(
private val libraryLoader: NativeLibraryLoader
) : Repository {
private val librariesByTarget: Map<Set<KonanTarget>, Set<NativeLibrary>> by lazy {
private val librariesByKonanTargets: Map<Set<KonanTarget>, Set<NativeLibrary>> by lazy {
libraryFiles
.map(libraryLoader::invoke)
.groupBy { library -> library.manifestData.nativeTargets.map(::konanTargetOrThrow).toSet() }
@@ -25,10 +25,11 @@ internal class FilesRepository(
}
override fun getLibraries(target: CommonizerTarget): Set<NativeLibrary> {
return librariesByTarget[target.konanTargets].orEmpty()
return librariesByKonanTargets[target.konanTargets].orEmpty()
}
private fun konanTargetOrThrow(value: String): KonanTarget {
return KonanTarget.predefinedTargets[value] ?: error("Unexpected KonanTarget $value")
}
}
private fun konanTargetOrThrow(value: String): KonanTarget {
return KonanTarget.predefinedTargets[value] ?: error("Unexpected KonanTarget $value")
}
@@ -6,14 +6,16 @@
package org.jetbrains.kotlin.commonizer.repository
import org.jetbrains.kotlin.commonizer.*
import org.jetbrains.kotlin.commonizer.NativeLibraryLoader
import org.jetbrains.kotlin.commonizer.konan.NativeLibrary
import org.jetbrains.kotlin.konan.target.KonanTarget
internal class KonanDistributionRepository(
konanDistribution: KonanDistribution,
targets: Set<LeafCommonizerTarget>,
targets: Set<KonanTarget>,
libraryLoader: NativeLibraryLoader,
) : Repository {
private val librariesByTarget: Map<LeafCommonizerTarget, Lazy<Set<NativeLibrary>>> =
private val librariesByTarget: Map<KonanTarget, Lazy<Set<NativeLibrary>>> =
targets.associateWith { target ->
lazy {
konanDistribution.platformLibsDir
@@ -27,9 +29,7 @@ internal class KonanDistributionRepository(
}
override fun getLibraries(target: CommonizerTarget): Set<NativeLibrary> {
return when (target) {
is LeafCommonizerTarget -> librariesByTarget[target]?.value ?: error("Missing target libraries for: $target")
is SharedCommonizerTarget -> emptySet()
}
val singleTarget = target.konanTargets.singleOrNull() ?: return emptySet()
return librariesByTarget[singleTarget]?.value ?: error("Missing target libraries for $target")
}
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.commonizer.repository
import org.jetbrains.kotlin.commonizer.CommonizerTarget
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
import org.jetbrains.kotlin.commonizer.konan.NativeLibrary
internal interface Repository {
@@ -25,9 +24,3 @@ private class CompositeRepository(val repositories: Iterable<Repository>) : Repo
return repositories.map { it.getLibraries(target) }.flatten().toSet()
}
}
internal object EmptyRepository : Repository {
override fun getLibraries(target: CommonizerTarget): Set<NativeLibrary> {
return emptySet()
}
}
@@ -18,7 +18,6 @@ internal class StdlibRepository(
}
override fun getLibraries(target: CommonizerTarget): Set<NativeLibrary> {
return if (target is SharedCommonizerTarget) setOf(stdlib)
else emptySet()
return if (target is SharedCommonizerTarget) setOf(stdlib) else emptySet()
}
}