diff --git a/native/commonizer-api/test/org/jetbrains/kotlin/commonizer/CommonizeNativeDistributionTest.kt b/native/commonizer-api/test/org/jetbrains/kotlin/commonizer/CommonizeNativeDistributionTest.kt index 4dbaa5f1035..6d89d7969eb 100644 --- a/native/commonizer-api/test/org/jetbrains/kotlin/commonizer/CommonizeNativeDistributionTest.kt +++ b/native/commonizer-api/test/org/jetbrains/kotlin/commonizer/CommonizeNativeDistributionTest.kt @@ -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( diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt index be0579f4866..20be6470b03 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt @@ -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() ) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetProvider.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetProvider.kt index 681fd71f5b2..82934217cde 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetProvider.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetProvider.kt @@ -16,7 +16,6 @@ class TargetProvider( interface ModulesProvider { open class ModuleInfo( val name: String, - val originalLocation: File, val cInteropAttributes: CInteropModuleAttributes? ) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt index 22021b729f0..d142cabc35b 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt @@ -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) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/DefaultModulesProvider.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/DefaultModulesProvider.kt index 829030bf1c7..5301ef34f01 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/DefaultModulesProvider.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/DefaultModulesProvider.kt @@ -14,10 +14,9 @@ import java.io.File internal class DefaultModulesProvider(libraries: Collection) : ModulesProvider { internal class NativeModuleInfo( name: String, - originalLocation: File, val dependencies: Set, cInteropAttributes: ModulesProvider.CInteropModuleAttributes? - ) : ModuleInfo(name, originalLocation, cInteropAttributes) + ) : ModuleInfo(name, cInteropAttributes) private val libraryMap: Map private val moduleInfoMap: Map @@ -30,7 +29,6 @@ internal class DefaultModulesProvider(libraries: Collection) : 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) : 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 diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirProvidedClassifiers.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirProvidedClassifiers.kt index 378953cc738..6449cf48e51 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirProvidedClassifiers.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirProvidedClassifiers.kt @@ -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() } - private class CompositeClassifiers(val delegates: List) : 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 { - 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 { + 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 { + return delegates.flatMap { it.findTypeAliasesWithUnderlyingType(underlyingClassifier) } + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirProvidedClassifiersByModules.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirProvidedClassifiersByModules.kt index 62121fe06e5..0a098cf5da8 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirProvidedClassifiersByModules.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirProvidedClassifiersByModules.kt @@ -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): CirProvidedClassifiers { val classifiers = THashMap() - 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 diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/nodeBuilders.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/nodeBuilders.kt index 892250d8049..492c4cea9ab 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/nodeBuilders.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/nodeBuilders.kt @@ -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( diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/InlineSourceBuilder.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/InlineSourceBuilder.kt index 37fa93ff7bc..8b0ccee814b 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/InlineSourceBuilder.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/InlineSourceBuilder.kt @@ -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 = 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) }) -} \ No newline at end of file +} diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/mocks.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/mocks.kt index 3c8fdfb81b5..2730e05ecc2 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/mocks.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/mocks.kt @@ -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")