diff --git a/native/commonizer-api/build.gradle.kts b/native/commonizer-api/build.gradle.kts index 5a7de91ccbb..f06e1040e5f 100644 --- a/native/commonizer-api/build.gradle.kts +++ b/native/commonizer-api/build.gradle.kts @@ -43,7 +43,7 @@ sourceSets { * TODO: This version hack on migrating period K/N into repository Kotlin, in new build infrostructure zero maintance claus isn't dropped, * so for old builds we need to keep this version to string representation till total switch on new infrostructure. */ -val konanVersion = object: org.jetbrains.kotlin.konan.CompilerVersion by NativeCompilerDownloader.DEFAULT_KONAN_VERSION { +val konanVersion = object : org.jetbrains.kotlin.konan.CompilerVersion by NativeCompilerDownloader.DEFAULT_KONAN_VERSION { override fun toString(showMeta: Boolean, showBuild: Boolean) = buildString { if (major > 1 || minor > 5 @@ -71,12 +71,15 @@ val konanVersion = object: org.jetbrains.kotlin.konan.CompilerVersion by NativeC } } - override fun toString() = toString(meta != org.jetbrains.kotlin.konan.MetaVersion.RELEASE, - meta != org.jetbrains.kotlin.konan.MetaVersion.RELEASE) + override fun toString() = toString( + meta != org.jetbrains.kotlin.konan.MetaVersion.RELEASE, + meta != org.jetbrains.kotlin.konan.MetaVersion.RELEASE + ) } tasks.register("downloadNativeCompiler") { doFirst { + if (NativeCompilerDownloader(project, konanVersion).compilerDirectory.exists()) return@doFirst NativeCompilerDownloader(project, konanVersion).downloadIfNeeded() } } diff --git a/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/TargetDependent.kt b/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/TargetDependent.kt deleted file mode 100644 index 51a472833af..00000000000 --- a/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/TargetDependent.kt +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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 - -public typealias TargetDependent = Map - diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt index 8951f6e2085..132853c83bf 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt @@ -5,13 +5,12 @@ package org.jetbrains.kotlin.commonizer -import org.jetbrains.kotlin.commonizer.konan.TargetedNativeManifestDataProvider +import org.jetbrains.kotlin.commonizer.konan.NativeManifestDataProvider import org.jetbrains.kotlin.commonizer.stats.StatsCollector class CommonizerParameters( val resultsConsumer: ResultsConsumer, - val manifestDataProvider: TargetedNativeManifestDataProvider, - // common module dependencies (ex: Kotlin stdlib) + val manifestDataProvider: TargetDependent, val commonDependencyModulesProvider: ModulesProvider? = null, val statsCollector: StatsCollector? = null, val progressLogger: ((String) -> Unit)? = null diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetDependent.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetDependent.kt new file mode 100644 index 00000000000..b75e538c485 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetDependent.kt @@ -0,0 +1,49 @@ +/* + * 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. + */ + +@file:Suppress("FunctionName") + +package org.jetbrains.kotlin.commonizer + +sealed interface TargetDependent { + fun getOrNull(target: CommonizerTarget): T? + operator fun get(target: CommonizerTarget): T { + return getOrNull(target) ?: throw NoSuchElementException("Missing element for target ${target.prettyName}") + } +} + +internal fun Map.toTargetDependent(): TargetDependent { + return TargetDependent(toMap()) +} + +internal fun Map.asTargetDependent(): TargetDependent { + return TargetDependent(this) +} + +internal fun TargetDependent.map(mapper: (T) -> R): TargetDependent { + return TargetDependent { target -> this@map.getOrNull(target)?.let(mapper) } +} + +internal fun TargetDependent(map: Map): TargetDependent { + return MapBasedTargetDependent(map) +} + +internal fun TargetDependent(factory: (target: CommonizerTarget) -> T?): TargetDependent { + return FactoryBasedTargetDependent(factory) +} + +private class MapBasedTargetDependent(private val map: Map) : TargetDependent { + override fun getOrNull(target: CommonizerTarget): T? = map[target] +} + +private class FactoryBasedTargetDependent(private val factory: (target: CommonizerTarget) -> T?) : TargetDependent { + private val values = mutableMapOf() + override fun getOrNull(target: CommonizerTarget): T? { + @Suppress("unchecked_cast") + return values.getOrPut(target) { factory(target) ?: Null }.takeIf { it != Null }?.run { this as T } + } + + private object Null +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt index 78fd7bb1c4b..12b4168e23e 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt @@ -62,7 +62,7 @@ private fun serializeTarget(mergeResult: CirTreeMergeResult, targetIndex: Int, p val serializedMetadata = with(metadataModule.write(KLIB_FRAGMENT_WRITE_STRATEGY)) { SerializedMetadata(header, fragments, fragmentNames) } - val manifestData = parameters.manifestDataProvider.getManifest(target, libraryName) + val manifestData = parameters.manifestDataProvider[target].getManifest(libraryName) parameters.resultsConsumer.consume(target, ModuleResult.Commonized(libraryName, serializedMetadata, manifestData)) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/LibraryCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/LibraryCommonizer.kt index baa4dafc53b..c051e2c363a 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/LibraryCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/LibraryCommonizer.kt @@ -37,20 +37,20 @@ internal class LibraryCommonizer internal constructor( } } progressLogger.log("Resolved libraries to be commonized") - return librariesByTargets + return TargetDependent(librariesByTargets) } private fun commonizeAndSaveResults(allLibraries: TargetDependent) { val parameters = CommonizerParameters( resultsConsumer = resultsConsumer, - manifestDataProvider = TargetedNativeManifestDataProvider(allLibraries), + manifestDataProvider = TargetDependentNativeManifestDataProvider(allLibraries), commonDependencyModulesProvider = DefaultModulesProvider.create(dependencies.getLibraries(commonTarget)), statsCollector = statsCollector, progressLogger = progressLogger::log ) - allLibraries.forEach { (target, librariesToCommonize) -> - parameters.addTarget(target, librariesToCommonize) + commonTarget.targets.forEach { target -> + parameters.addTarget(target, allLibraries[target]) } runCommonization(parameters) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/NativeLibrary.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/NativeLibrary.kt index 11d491cb149..595cebd358b 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/NativeLibrary.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/NativeLibrary.kt @@ -3,36 +3,29 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:Suppress("FunctionName") + package org.jetbrains.kotlin.commonizer.konan -import com.intellij.util.containers.FactoryMap import gnu.trove.THashMap -import org.jetbrains.kotlin.commonizer.CommonizerTarget import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget import org.jetbrains.kotlin.commonizer.TargetDependent import org.jetbrains.kotlin.library.KotlinLibrary -fun interface TargetedNativeManifestDataProvider { - fun getManifest(target: CommonizerTarget, libraryName: String): NativeSensitiveManifestData -} - -internal interface NativeManifestDataProvider { +interface NativeManifestDataProvider { fun getManifest(libraryName: String): NativeSensitiveManifestData } -internal fun TargetedNativeManifestDataProvider( +internal fun TargetDependentNativeManifestDataProvider( libraries: TargetDependent -): TargetedNativeManifestDataProvider { - val cachedManifestProviders: Map = FactoryMap.create { target -> +): TargetDependent { + return TargetDependent { target -> when (target) { - is LeafCommonizerTarget -> libraries.getValue(target) - is SharedCommonizerTarget -> CommonNativeManifestDataProvider(libraries.values) + is LeafCommonizerTarget -> libraries[target] + is SharedCommonizerTarget -> CommonNativeManifestDataProvider(target.targets.map { libraries[it] }) } } - return TargetedNativeManifestDataProvider { target, libraryName -> - cachedManifestProviders.getValue(target).getManifest(libraryName) - } } /** diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/AbstractCommonizationFromSourcesTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/AbstractCommonizationFromSourcesTest.kt index 1e2536b13c8..b8eb2d3ded7 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/AbstractCommonizationFromSourcesTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/AbstractCommonizationFromSourcesTest.kt @@ -23,7 +23,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.commonizer.ResultsConsumer.ModuleResult import org.jetbrains.kotlin.commonizer.ResultsConsumer.Status import org.jetbrains.kotlin.commonizer.SourceModuleRoot.Companion.SHARED_TARGET_NAME -import org.jetbrains.kotlin.commonizer.konan.TargetedNativeManifestDataProvider +import org.jetbrains.kotlin.commonizer.konan.NativeManifestDataProvider import org.jetbrains.kotlin.commonizer.utils.* import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl @@ -205,9 +205,11 @@ private class AnalyzedModules( } fun toCommonizerParameters( - resultsConsumer: ResultsConsumer, manifestDataProvider: TargetedNativeManifestDataProvider = MockNativeManifestDataProvider() + resultsConsumer: ResultsConsumer, + manifestDataProvider: TargetDependent = MockNativeManifestDataProvider() ) = CommonizerParameters( - resultsConsumer, manifestDataProvider, commonDependencyModulesProvider = dependencyModules[sharedTarget]?.let(MockModulesProvider::create) + resultsConsumer, manifestDataProvider, + commonDependencyModulesProvider = dependencyModules[sharedTarget]?.let(MockModulesProvider::create) ).also { parameters -> leafTargets.forEach { leafTarget -> diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CommonizerFacadeTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CommonizerFacadeTest.kt index 0c46966792a..bc674ec0cfb 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CommonizerFacadeTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CommonizerFacadeTest.kt @@ -7,8 +7,7 @@ package org.jetbrains.kotlin.commonizer import org.jetbrains.kotlin.commonizer.ResultsConsumer.ModuleResult import org.jetbrains.kotlin.commonizer.ResultsConsumer.Status -import org.jetbrains.kotlin.commonizer.konan.CommonNativeManifestDataProvider -import org.jetbrains.kotlin.commonizer.konan.TargetedNativeManifestDataProvider +import org.jetbrains.kotlin.commonizer.konan.NativeManifestDataProvider import org.jetbrains.kotlin.commonizer.utils.MockResultsConsumer import org.jetbrains.kotlin.commonizer.utils.MockModulesProvider import org.jetbrains.kotlin.commonizer.utils.MockNativeManifestDataProvider @@ -66,7 +65,8 @@ class CommonizerFacadeTest { companion object { private fun Map>.toCommonizerParameters( - resultsConsumer: ResultsConsumer, manifestDataProvider: TargetedNativeManifestDataProvider = MockNativeManifestDataProvider() + resultsConsumer: ResultsConsumer, + manifestDataProvider: TargetDependent = MockNativeManifestDataProvider() ) = CommonizerParameters(resultsConsumer, manifestDataProvider).also { parameters -> forEach { (targetName, moduleNames) -> parameters.addTarget( 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 7943851cb62..b03a524281f 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/mocks.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/utils/mocks.kt @@ -3,6 +3,8 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:Suppress("TestFunctionName") + package org.jetbrains.kotlin.commonizer.utils import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer @@ -13,8 +15,9 @@ import org.jetbrains.kotlin.commonizer.* import org.jetbrains.kotlin.commonizer.ModulesProvider.ModuleInfo import org.jetbrains.kotlin.commonizer.ResultsConsumer.ModuleResult import org.jetbrains.kotlin.commonizer.cir.* +import org.jetbrains.kotlin.commonizer.konan.NativeManifestDataProvider import org.jetbrains.kotlin.commonizer.konan.NativeSensitiveManifestData -import org.jetbrains.kotlin.commonizer.konan.TargetedNativeManifestDataProvider +import org.jetbrains.kotlin.commonizer.konan.TargetDependentNativeManifestDataProvider import org.jetbrains.kotlin.commonizer.mergedtree.* import org.jetbrains.kotlin.library.KotlinLibraryVersioning import org.jetbrains.kotlin.library.SerializedMetadata @@ -173,15 +176,20 @@ fun MockNativeManifestDataProvider( exportForwardDeclarations: List = emptyList(), nativeTargets: Collection = emptyList(), shortName: String? = "mock" -): TargetedNativeManifestDataProvider = TargetedNativeManifestDataProvider { _, _ -> - NativeSensitiveManifestData( - uniqueName = uniqueName, - versions = versions, - dependencies = dependencies, - isInterop = isInterop, - packageFqName = packageFqName, - exportForwardDeclarations = exportForwardDeclarations, - nativeTargets = nativeTargets, - shortName = shortName - ) +): TargetDependent = TargetDependent { + object : NativeManifestDataProvider { + override fun getManifest(libraryName: String): NativeSensitiveManifestData { + return NativeSensitiveManifestData( + uniqueName = uniqueName, + versions = versions, + dependencies = dependencies, + isInterop = isInterop, + packageFqName = packageFqName, + exportForwardDeclarations = exportForwardDeclarations, + nativeTargets = nativeTargets, + shortName = shortName + ) + } + } + }