[Commonizer] Provide union of forwardDeclarations as common dependencies

^KT-52050 Verification Pending

The issue described in KT-52050 happened, because forwardDeclarations
were not carried into next commonization steps. For commonization
it is fair to choose the union of all modules forwardDeclarations
as common dependency (instead of a union), since we can assume that
all those forward declarations will be provided.
This commit is contained in:
sebastian.sellmair
2022-04-20 13:45:40 +02:00
committed by Space
parent 99d995a313
commit 204bc4ca95
10 changed files with 67 additions and 44 deletions
@@ -103,6 +103,23 @@ class CommonizeNativeDistributionTest {
)
}
@Test
fun `commonize - linux macos - linux macos mingw`() {
val unixTarget = CommonizerTarget(LINUX_X64, MACOS_X64)
val nativeTarget = CommonizerTarget(MINGW_X64, LINUX_X64, MACOS_X64)
CliCommonizer(this::class.java.classLoader).commonizeNativeDistribution(
konanHome = konanHome,
outputTargets = setOf(unixTarget, nativeTarget),
outputDirectory = temporaryOutputDirectory.root,
logLevel = CommonizerLogLevel.Info
)
assertTrue(
resolveCommonizedDirectory(temporaryOutputDirectory.root, nativeTarget).isDirectory,
"Expected directory for $nativeTarget"
)
}
@Test
fun `commonize - no outputTargets specified`() {
CliCommonizer(this::class.java.classLoader).commonizeNativeDistribution(
@@ -27,20 +27,19 @@ data class CommonizerParameters(
)
internal fun CommonizerParameters.dependencyClassifiers(target: CommonizerTarget): CirProvidedClassifiers {
val targetModulesProvider = targetProviders.getOrNull(target)?.modulesProvider
val dependenciesModulesProvider = dependenciesProvider[target]
val providedByTarget = if (targetModulesProvider != null)
CirProvidedClassifiersByModules.loadExportedForwardDeclarations(targetModulesProvider) else null
val exportedForwardDeclarations = target.withAllLeaves()
.mapNotNull { targetOrLeaf -> targetProviders.getOrNull(targetOrLeaf)?.modulesProvider }
.plus(listOfNotNull(dependenciesModulesProvider))
.let { modulesProviders -> CirProvidedClassifiersByModules.loadExportedForwardDeclarations(modulesProviders) }
val providedByDependencies = if (dependenciesModulesProvider != null)
CirProvidedClassifiers.of(
CirProvidedClassifiersByModules.load(dependenciesModulesProvider),
CirProvidedClassifiersByModules.loadExportedForwardDeclarations(dependenciesModulesProvider)
) else null
CirProvidedClassifiersByModules.load(dependenciesModulesProvider)
else null
return CirProvidedClassifiers.of(
*listOfNotNull(CirFictitiousFunctionClassifiers, providedByTarget, providedByDependencies).toTypedArray()
*listOfNotNull(CirFictitiousFunctionClassifiers, exportedForwardDeclarations, providedByDependencies).toTypedArray()
)
}
@@ -16,7 +16,6 @@ class TargetProvider(
interface ModulesProvider {
open class ModuleInfo(
val name: String,
val originalLocation: File,
val cInteropAttributes: CInteropModuleAttributes?
)
@@ -58,7 +58,6 @@ internal fun commonizeTarget(
targetDependencies = availableTrees.mapValue(CirTreeRoot::dependencies),
commonizedNodes = CirCommonizedClassifierNodes.default(),
commonDependencies = parameters.dependencyClassifiers(output)
)
val mergedTree = mergeCirTree(parameters.storageManager, classifiers, availableTrees, parameters.settings)
@@ -14,10 +14,9 @@ import java.io.File
internal class DefaultModulesProvider(libraries: Collection<NativeLibrary>) : ModulesProvider {
internal class NativeModuleInfo(
name: String,
originalLocation: File,
val dependencies: Set<String>,
cInteropAttributes: ModulesProvider.CInteropModuleAttributes?
) : ModuleInfo(name, originalLocation, cInteropAttributes)
) : ModuleInfo(name, cInteropAttributes)
private val libraryMap: Map<String, NativeLibrary>
private val moduleInfoMap: Map<String, NativeModuleInfo>
@@ -30,7 +29,6 @@ internal class DefaultModulesProvider(libraries: Collection<NativeLibrary>) : Mo
val manifestData = library.manifestData
val name = manifestData.uniqueName
val location = File(library.library.libraryFile.path)
val dependencies = manifestData.dependencies.toSet()
val cInteropAttributes = if (manifestData.isInterop) {
@@ -39,7 +37,7 @@ internal class DefaultModulesProvider(libraries: Collection<NativeLibrary>) : Mo
} else null
libraryMap.put(name, library)?.let { error("Duplicated libraries: $name") }
moduleInfoMap[name] = NativeModuleInfo(name, location, dependencies, cInteropAttributes)
moduleInfoMap[name] = NativeModuleInfo(name, dependencies, cInteropAttributes)
}
this.libraryMap = libraryMap
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
/** A set of classes and type aliases provided by libraries (either the libraries to commonize, or their dependency libraries)/ */
interface CirProvidedClassifiers {
sealed interface CirProvidedClassifiers {
fun hasClassifier(classifierId: CirEntityId): Boolean
fun classifier(classifierId: CirEntityId): CirProvided.Classifier?
@@ -24,24 +24,6 @@ interface CirProvidedClassifiers {
override fun findTypeAliasesWithUnderlyingType(underlyingClassifier: CirEntityId) = emptyList<CirEntityId>()
}
private class CompositeClassifiers(val delegates: List<CirProvidedClassifiers>) : CirProvidedClassifiers {
override fun hasClassifier(classifierId: CirEntityId) = delegates.any { it.hasClassifier(classifierId) }
override fun classifier(classifierId: CirEntityId): CirProvided.Classifier? {
var fallbackReturn: CirProvided.Classifier? = null
for (delegate in delegates) {
delegate.classifier(classifierId)?.let { classifier ->
if (classifier !== FALLBACK_FORWARD_DECLARATION_CLASS) return classifier
else fallbackReturn = classifier
}
}
return fallbackReturn
}
override fun findTypeAliasesWithUnderlyingType(underlyingClassifier: CirEntityId): List<CirEntityId> {
return delegates.flatMap { it.findTypeAliasesWithUnderlyingType(underlyingClassifier) }
}
}
companion object {
internal val FALLBACK_FORWARD_DECLARATION_CLASS =
CirProvided.RegularClass(emptyList(), emptyList(), Visibilities.Public, ClassKind.CLASS)
@@ -68,3 +50,30 @@ interface CirProvidedClassifiers {
}
}
internal operator fun CirProvidedClassifiers.plus(other: CirProvidedClassifiers): CirProvidedClassifiers {
return when {
this is CompositeClassifiers && other is CompositeClassifiers -> CompositeClassifiers(this.delegates + other.delegates)
this is CompositeClassifiers -> CompositeClassifiers(this.delegates + other)
other is CompositeClassifiers -> CompositeClassifiers(listOf(this) + other.delegates)
else -> CompositeClassifiers(listOf(this, other))
}
}
private class CompositeClassifiers(val delegates: List<CirProvidedClassifiers>) : CirProvidedClassifiers {
override fun hasClassifier(classifierId: CirEntityId) = delegates.any { it.hasClassifier(classifierId) }
override fun classifier(classifierId: CirEntityId): CirProvided.Classifier? {
var fallbackReturn: CirProvided.Classifier? = null
for (delegate in delegates) {
delegate.classifier(classifierId)?.let { classifier ->
if (classifier !== CirProvidedClassifiers.FALLBACK_FORWARD_DECLARATION_CLASS) return classifier
else fallbackReturn = classifier
}
}
return fallbackReturn
}
override fun findTypeAliasesWithUnderlyingType(underlyingClassifier: CirEntityId): List<CirEntityId> {
return delegates.flatMap { it.findTypeAliasesWithUnderlyingType(underlyingClassifier) }
}
}
@@ -68,10 +68,15 @@ internal class CirProvidedClassifiersByModules internal constructor(
return CirProvidedClassifiersByModules(false, classifiers)
}
fun loadExportedForwardDeclarations(modulesProvider: ModulesProvider): CirProvidedClassifiers {
/**
* Will load *all* forward declarations provided by all modules into a flat [CirProvidedClassifiers].
* Note: This builds a union *not an intersection* of forward declarations.
*/
fun loadExportedForwardDeclarations(modulesProviders: List<ModulesProvider>): CirProvidedClassifiers {
val classifiers = THashMap<CirEntityId, CirProvided.Classifier>()
modulesProvider.moduleInfos.mapNotNull { moduleInfo -> moduleInfo.cInteropAttributes }
modulesProviders.flatMap { moduleProvider -> moduleProvider.moduleInfos }
.mapNotNull { moduleInfo -> moduleInfo.cInteropAttributes }
.forEach { attrs -> readExportedForwardDeclarations(attrs, classifiers::set) }
if (classifiers.isEmpty) return CirProvidedClassifiers.EMPTY
@@ -5,26 +5,23 @@
package org.jetbrains.kotlin.commonizer.mergedtree
import org.jetbrains.kotlin.commonizer.cir.CirClassRecursionMarker
import org.jetbrains.kotlin.commonizer.cir.CirDeclaration
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirTypeAliasRecursionMarker
import org.jetbrains.kotlin.commonizer.core.*
import org.jetbrains.kotlin.commonizer.CommonizerSettings
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.storage.NullableLazyValue
import org.jetbrains.kotlin.storage.StorageManager
internal fun buildRootNode(
storageManager: StorageManager,
dependencies: CirProvidedClassifiers,
commonDependencies: CirProvidedClassifiers,
size: Int
): CirRootNode = buildNode(
storageManager = storageManager,
size = size,
nodeRelationship = null,
commonizerProducer = ::RootCommonizer,
nodeProducer = { targetDeclarations, commonDeclaration -> CirRootNode(dependencies, targetDeclarations, commonDeclaration) }
nodeProducer = { targetDeclarations, commonDeclaration -> CirRootNode(commonDependencies, targetDeclarations, commonDeclaration) }
)
internal fun buildModuleNode(
@@ -103,7 +103,7 @@ fun InlineSourceBuilder.createCirTreeRootFromSourceCode(@Language("kotlin") sour
fun InlineSourceBuilder.createCirProvidedClassifiers(module: InlineSourceBuilder.Module): CirProvidedClassifiers {
val modulesProvider = object : ModulesProvider {
override val moduleInfos: Collection<ModulesProvider.ModuleInfo> = listOf(
ModulesProvider.ModuleInfo(name = "CirProvidedForTest", originalLocation = File("."), cInteropAttributes = null)
ModulesProvider.ModuleInfo(name = "CirProvidedForTest", cInteropAttributes = null)
)
override fun loadModuleMetadata(name: String): SerializedMetadata {
@@ -122,4 +122,4 @@ fun InlineSourceBuilder.createCirProvidedClassifiers(builder: InlineSourceBuilde
@InlineSourceBuilder.ModuleBuilderDsl
fun InlineSourceBuilder.createCirProvidedClassifiersFromSourceCode(@Language("kotlin") sourceCode: String): CirProvidedClassifiers {
return createCirProvidedClassifiers(createModule { source(sourceCode) })
}
}
@@ -98,7 +98,7 @@ internal class MockModulesProvider private constructor(
return SERIALIZER.serializeModule(module)
}
private fun fakeModuleInfo(name: String) = ModuleInfo(name, File("/tmp/commonizer/mocks/$name"), null)
private fun fakeModuleInfo(name: String) = ModuleInfo(name, null)
companion object {
@JvmName("createByModuleNames")