[Commonizer] Dump every target to disk immediately when it's ready
This commit is contained in:
+8
-1
@@ -13,7 +13,6 @@ class CommonizerParameters(
|
||||
) {
|
||||
// use linked hash map to preserve order
|
||||
private val _targetProviders = LinkedHashMap<LeafTarget, TargetProvider>()
|
||||
|
||||
val targetProviders: List<TargetProvider> get() = _targetProviders.values.toList()
|
||||
val sharedTarget: SharedTarget get() = SharedTarget(_targetProviders.keys)
|
||||
|
||||
@@ -31,5 +30,13 @@ class CommonizerParameters(
|
||||
return this
|
||||
}
|
||||
|
||||
private var _resultsConsumer: ResultsConsumer? = null
|
||||
var resultsConsumer: ResultsConsumer
|
||||
get() = _resultsConsumer ?: error("Results consumer has not been set")
|
||||
set(value) {
|
||||
check(_resultsConsumer == null)
|
||||
_resultsConsumer = value
|
||||
}
|
||||
|
||||
fun hasAnythingToCommonize(): Boolean = _targetProviders.size >= 2
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.descriptors.commonizer
|
||||
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import java.io.File
|
||||
|
||||
sealed class CommonizerResult {
|
||||
object NothingToDo : CommonizerResult()
|
||||
|
||||
class Done(
|
||||
val modulesByTargets: Map<CommonizerTarget, Collection<ModuleResult>>
|
||||
) : CommonizerResult() {
|
||||
val sharedTarget: SharedTarget by lazy { modulesByTargets.keys.filterIsInstance<SharedTarget>().single() }
|
||||
val leafTargets: Set<LeafTarget> by lazy { modulesByTargets.keys.filterIsInstance<LeafTarget>().toSet() }
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ModuleResult {
|
||||
abstract val libraryName: String
|
||||
|
||||
class Missing(val originalLocation: File) : ModuleResult() {
|
||||
override val libraryName: String get() = originalLocation.name
|
||||
}
|
||||
|
||||
class Commonized(override val libraryName: String, val metadata: SerializedMetadata) : ModuleResult()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.descriptors.commonizer
|
||||
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import java.io.File
|
||||
|
||||
interface ResultsConsumer {
|
||||
enum class Status { NOTHING_TO_DO, DONE }
|
||||
|
||||
sealed class ModuleResult {
|
||||
abstract val libraryName: String
|
||||
|
||||
class Missing(val originalLocation: File) : ModuleResult() {
|
||||
override val libraryName: String get() = originalLocation.name
|
||||
}
|
||||
|
||||
class Commonized(override val libraryName: String, val metadata: SerializedMetadata) : ModuleResult()
|
||||
}
|
||||
|
||||
fun consumeResults(target: CommonizerTarget, moduleResults: Collection<ModuleResult>)
|
||||
|
||||
fun successfullyFinished(status: Status)
|
||||
}
|
||||
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.descriptors.commonizer
|
||||
|
||||
import kotlinx.metadata.klib.ChunkedKlibModuleFragmentWriteStrategy
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer.ModuleResult
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer.Status
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizationVisitor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.dimension
|
||||
@@ -15,9 +17,12 @@ import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
fun runCommonization(parameters: CommonizerParameters): CommonizerResult {
|
||||
if (!parameters.hasAnythingToCommonize())
|
||||
return CommonizerResult.NothingToDo
|
||||
fun runCommonization(parameters: CommonizerParameters) {
|
||||
val resultsConsumer = parameters.resultsConsumer
|
||||
if (!parameters.hasAnythingToCommonize()) {
|
||||
resultsConsumer.successfullyFinished(Status.NOTHING_TO_DO)
|
||||
return
|
||||
}
|
||||
|
||||
val storageManager = LockBasedStorageManager("Declarations commonization")
|
||||
|
||||
@@ -25,7 +30,6 @@ fun runCommonization(parameters: CommonizerParameters): CommonizerResult {
|
||||
val mergedTree = mergeResult.root
|
||||
|
||||
// build resulting declarations:
|
||||
val modulesByTargets = LinkedHashMap<CommonizerTarget, Collection<ModuleResult>>() // use linked hash map to preserve order
|
||||
val klibFragmentWriteStrategy = ChunkedKlibModuleFragmentWriteStrategy()
|
||||
|
||||
for (targetIndex in 0 until mergedTree.dimension) {
|
||||
@@ -39,16 +43,15 @@ fun runCommonization(parameters: CommonizerParameters): CommonizerResult {
|
||||
|
||||
ModuleResult.Commonized(libraryName, serializedMetadata)
|
||||
}
|
||||
parameters.progressLogger?.invoke("Built metadata for ${target.prettyCommonizedName(parameters.sharedTarget)}")
|
||||
|
||||
val missingModules: List<ModuleResult.Missing> = if (target is LeafTarget)
|
||||
mergeResult.missingModuleInfos.getValue(target).map { ModuleResult.Missing(it.originalLocation) }
|
||||
else emptyList()
|
||||
|
||||
modulesByTargets[target] = commonizedModules + missingModules
|
||||
resultsConsumer.consumeResults(target, commonizedModules + missingModules)
|
||||
}
|
||||
|
||||
return CommonizerResult.Done(modulesByTargets)
|
||||
resultsConsumer.successfullyFinished(Status.DONE)
|
||||
}
|
||||
|
||||
private fun mergeAndCommonize(storageManager: StorageManager, parameters: CommonizerParameters): CirTreeMergeResult {
|
||||
|
||||
+14
-151
@@ -14,12 +14,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.utils.ResettableClockMark
|
||||
import org.jetbrains.kotlin.konan.library.*
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import org.jetbrains.kotlin.library.ToolingSingleFileKlibResolveStrategy
|
||||
import org.jetbrains.kotlin.library.impl.BaseWriterImpl
|
||||
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
|
||||
import org.jetbrains.kotlin.library.impl.KotlinLibraryLayoutForWriter
|
||||
import org.jetbrains.kotlin.library.impl.KotlinLibraryWriterImpl
|
||||
import org.jetbrains.kotlin.library.resolveSingleFileKlib
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
@@ -35,9 +30,7 @@ class NativeDistributionCommonizer(
|
||||
private val statsType: StatsType,
|
||||
private val logger: Logger
|
||||
) {
|
||||
enum class StatsType {
|
||||
RAW, AGGREGATED, NONE
|
||||
}
|
||||
enum class StatsType { RAW, AGGREGATED, NONE }
|
||||
|
||||
private val clockMark = ResettableClockMark()
|
||||
|
||||
@@ -48,11 +41,8 @@ class NativeDistributionCommonizer(
|
||||
// 1. load libraries
|
||||
val allLibraries = loadLibraries()
|
||||
|
||||
// 2. run commonization
|
||||
val result = commonize(allLibraries)
|
||||
|
||||
// 3. write new libraries
|
||||
saveModules(allLibraries, result)
|
||||
// 2. run commonization & write new libraries
|
||||
commonizeAndSaveResults(allLibraries)
|
||||
|
||||
logTotal()
|
||||
}
|
||||
@@ -127,7 +117,7 @@ class NativeDistributionCommonizer(
|
||||
return library
|
||||
}
|
||||
|
||||
private fun commonize(allLibraries: AllNativeLibraries): CommonizerResult {
|
||||
private fun commonizeAndSaveResults(allLibraries: AllNativeLibraries) {
|
||||
val statsCollector = when (statsType) {
|
||||
RAW -> RawStatsCollector(targets)
|
||||
AGGREGATED -> AggregatedStatsCollector(targets)
|
||||
@@ -137,6 +127,14 @@ class NativeDistributionCommonizer(
|
||||
val parameters = CommonizerParameters(statsCollector, ::logProgress).apply {
|
||||
val storageManager = LockBasedStorageManager("Commonized modules")
|
||||
|
||||
resultsConsumer = NativeDistributionResultsConsumer(
|
||||
repository = repository,
|
||||
originalLibraries = allLibraries,
|
||||
destination = destination,
|
||||
copyStdlib = copyStdlib,
|
||||
copyEndorsedLibs = copyEndorsedLibs,
|
||||
logProgress = ::logProgress
|
||||
)
|
||||
dependeeModulesProvider = NativeDistributionStdlibProvider(storageManager, allLibraries.stdlib)
|
||||
|
||||
allLibraries.librariesByTargets.forEach { (target, librariesToCommonize) ->
|
||||
@@ -154,148 +152,13 @@ class NativeDistributionCommonizer(
|
||||
}
|
||||
}
|
||||
|
||||
val result = runCommonization(parameters)
|
||||
runCommonization(parameters)
|
||||
|
||||
statsCollector?.writeTo(FileStatsOutput(destination, statsType.name.toLowerCase()))
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun saveModules(originalLibraries: AllNativeLibraries, result: CommonizerResult) {
|
||||
// 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
|
||||
copyCommonStandardLibraries()
|
||||
|
||||
when (result) {
|
||||
is CommonizerResult.NothingToDo -> {
|
||||
// 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 the target where they are to the new destination.
|
||||
originalLibraries.librariesByTargets.forEach { (target, librariesToCommonize) ->
|
||||
copyTargetAsIs(target, librariesToCommonize.libraries.size)
|
||||
}
|
||||
}
|
||||
|
||||
is CommonizerResult.Done -> {
|
||||
// 'targetsToCopy' are some targets with empty set of platform libraries
|
||||
val targetsToCopy = originalLibraries.librariesByTargets.keys - result.leafTargets
|
||||
if (targetsToCopy.isNotEmpty()) {
|
||||
targetsToCopy.forEach { target ->
|
||||
val librariesToCommonize = originalLibraries.librariesByTargets.getValue(target)
|
||||
copyTargetAsIs(target, librariesToCommonize.libraries.size)
|
||||
}
|
||||
}
|
||||
|
||||
val targetsToSerialize = result.leafTargets + result.sharedTarget
|
||||
targetsToSerialize.forEach { target ->
|
||||
val moduleResults: Collection<ModuleResult> = result.modulesByTargets.getValue(target)
|
||||
val prettyTargetName = target.prettyCommonizedName(result.sharedTarget)
|
||||
|
||||
val manifestProvider = when (target) {
|
||||
is LeafTarget -> originalLibraries.librariesByTargets.getValue(target)
|
||||
is SharedTarget -> CommonNativeManifestDataProvider(originalLibraries.librariesByTargets.values)
|
||||
}
|
||||
|
||||
serializeTarget(target, prettyTargetName, moduleResults, manifestProvider)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyCommonStandardLibraries() {
|
||||
if (copyStdlib || copyEndorsedLibs) {
|
||||
repository.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||
.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
|
||||
.listFiles()
|
||||
?.filter { it.isDirectory }
|
||||
?.let {
|
||||
if (copyStdlib) {
|
||||
if (copyEndorsedLibs) it else it.filter { dir -> dir.endsWith(KONAN_STDLIB_NAME) }
|
||||
} else
|
||||
it.filter { dir -> !dir.endsWith(KONAN_STDLIB_NAME) }
|
||||
}?.forEach { libraryOrigin ->
|
||||
val libraryDestination = destination.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR).resolve(libraryOrigin.name)
|
||||
libraryOrigin.copyRecursively(libraryDestination)
|
||||
}
|
||||
|
||||
val what = listOfNotNull(
|
||||
"standard library".takeIf { copyStdlib },
|
||||
"endorsed libraries".takeIf { copyEndorsedLibs }
|
||||
).joinToString(separator = " and ")
|
||||
|
||||
logProgress("Copied $what")
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyTargetAsIs(leafTarget: LeafTarget, librariesCount: Int) {
|
||||
val librariesDestination = leafTarget.librariesDestination
|
||||
librariesDestination.mkdirs() // always create an empty directory even if there is nothing to copy
|
||||
|
||||
val librariesSource = leafTarget.platformLibrariesSource
|
||||
if (librariesSource.isDirectory) librariesSource.copyRecursively(librariesDestination)
|
||||
|
||||
logProgress("Copied $librariesCount libraries for [${leafTarget.name}]")
|
||||
}
|
||||
|
||||
private fun serializeTarget(
|
||||
target: CommonizerTarget,
|
||||
prettyTargetName: String,
|
||||
moduleResults: Collection<ModuleResult>,
|
||||
manifestProvider: NativeManifestDataProvider
|
||||
) {
|
||||
val librariesDestination = target.librariesDestination
|
||||
librariesDestination.mkdirs() // always create an empty directory even if there is nothing to copy
|
||||
|
||||
for (moduleResult in moduleResults) {
|
||||
when (moduleResult) {
|
||||
is ModuleResult.Commonized -> {
|
||||
val libraryName = moduleResult.libraryName
|
||||
|
||||
val manifestData = manifestProvider.getManifest(libraryName)
|
||||
val libraryDestination = librariesDestination.resolve(libraryName)
|
||||
|
||||
writeLibrary(moduleResult.metadata, manifestData, libraryDestination)
|
||||
}
|
||||
is ModuleResult.Missing -> {
|
||||
val libraryName = moduleResult.libraryName
|
||||
val missingModuleLocation = moduleResult.originalLocation
|
||||
|
||||
missingModuleLocation.copyRecursively(librariesDestination.resolve(libraryName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logProgress("Written libraries for $prettyTargetName")
|
||||
}
|
||||
|
||||
private fun writeLibrary(
|
||||
metadata: SerializedMetadata,
|
||||
manifestData: NativeSensitiveManifestData,
|
||||
destination: File
|
||||
) {
|
||||
val kDestination = KFile(destination.path)
|
||||
val layout = KotlinLibraryLayoutForWriter(kDestination, kDestination)
|
||||
val library = KotlinLibraryWriterImpl(
|
||||
moduleName = manifestData.uniqueName,
|
||||
versions = manifestData.versions,
|
||||
builtInsPlatform = BuiltInsPlatform.NATIVE,
|
||||
nativeTargets = emptyList(), // will be overwritten with NativeSensitiveManifestData.applyTo() below
|
||||
nopack = true,
|
||||
shortName = manifestData.shortName,
|
||||
layout = layout
|
||||
)
|
||||
library.addMetadata(metadata)
|
||||
manifestData.applyTo(library.base as BaseWriterImpl)
|
||||
library.commit()
|
||||
}
|
||||
|
||||
private val LeafTarget.platformLibrariesSource: File
|
||||
get() = repository.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||
.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR)
|
||||
.resolve(name)
|
||||
|
||||
private val CommonizerTarget.librariesDestination: File
|
||||
get() = when (this) {
|
||||
is LeafTarget -> destination.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR).resolve(name)
|
||||
is SharedTarget -> destination.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
|
||||
}
|
||||
}
|
||||
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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.descriptors.commonizer.konan
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer.ModuleResult
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer.Status
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedTarget
|
||||
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_COMMON_LIBS_DIR
|
||||
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_KLIB_DIR
|
||||
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR
|
||||
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import org.jetbrains.kotlin.library.impl.BaseWriterImpl
|
||||
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
|
||||
import org.jetbrains.kotlin.library.impl.KotlinLibraryLayoutForWriter
|
||||
import org.jetbrains.kotlin.library.impl.KotlinLibraryWriterImpl
|
||||
import java.io.File
|
||||
import org.jetbrains.kotlin.konan.file.File as KFile
|
||||
|
||||
internal class NativeDistributionResultsConsumer(
|
||||
private val repository: File,
|
||||
private val originalLibraries: AllNativeLibraries,
|
||||
private val destination: File,
|
||||
private val copyStdlib: Boolean,
|
||||
private val copyEndorsedLibs: Boolean,
|
||||
private val logProgress: (String) -> Unit
|
||||
) : ResultsConsumer {
|
||||
private val consumedTargets = LinkedHashSet<CommonizerTarget>()
|
||||
private val allLeafTargets = originalLibraries.librariesByTargets.keys
|
||||
private val sharedTarget = SharedTarget(allLeafTargets)
|
||||
|
||||
override fun consumeResults(target: CommonizerTarget, moduleResults: Collection<ModuleResult>) {
|
||||
val added = consumedTargets.add(target)
|
||||
check(added)
|
||||
|
||||
serializeTarget(target, moduleResults)
|
||||
}
|
||||
|
||||
override fun successfullyFinished(status: Status) {
|
||||
// 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
|
||||
copyCommonStandardLibraries()
|
||||
|
||||
when (status) {
|
||||
Status.NOTHING_TO_DO -> {
|
||||
// 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 raise a special status value 'NOTHING_TO_DO'.
|
||||
// So, let's just copy platform libraries from the target where they are to the new destination.
|
||||
allLeafTargets.forEach(::copyTargetAsIs)
|
||||
}
|
||||
Status.DONE -> {
|
||||
// 'targetsToCopy' are some leaf targets with empty set of platform libraries
|
||||
val targetsToCopy = allLeafTargets - consumedTargets.filterIsInstance<LeafTarget>()
|
||||
targetsToCopy.forEach(::copyTargetAsIs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyCommonStandardLibraries() {
|
||||
if (copyStdlib || copyEndorsedLibs) {
|
||||
repository.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||
.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
|
||||
.listFiles()
|
||||
?.filter { it.isDirectory }
|
||||
?.let {
|
||||
if (copyStdlib) {
|
||||
if (copyEndorsedLibs) it else it.filter { dir -> dir.endsWith(KONAN_STDLIB_NAME) }
|
||||
} else
|
||||
it.filter { dir -> !dir.endsWith(KONAN_STDLIB_NAME) }
|
||||
}?.forEach { libraryOrigin ->
|
||||
val libraryDestination = destination.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR).resolve(libraryOrigin.name)
|
||||
libraryOrigin.copyRecursively(libraryDestination)
|
||||
}
|
||||
|
||||
val what = listOfNotNull(
|
||||
"standard library".takeIf { copyStdlib },
|
||||
"endorsed libraries".takeIf { copyEndorsedLibs }
|
||||
).joinToString(separator = " and ")
|
||||
|
||||
logProgress("Copied $what")
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyTargetAsIs(leafTarget: LeafTarget) {
|
||||
val librariesCount = originalLibraries.librariesByTargets.getValue(leafTarget).libraries.size
|
||||
|
||||
val librariesDestination = leafTarget.librariesDestination
|
||||
librariesDestination.mkdirs() // always create an empty directory even if there is nothing to copy
|
||||
|
||||
val librariesSource = leafTarget.platformLibrariesSource
|
||||
if (librariesSource.isDirectory) librariesSource.copyRecursively(librariesDestination)
|
||||
|
||||
logProgress("Copied $librariesCount libraries for ${leafTarget.prettyName}")
|
||||
}
|
||||
|
||||
private fun serializeTarget(target: CommonizerTarget, moduleResults: Collection<ModuleResult>) {
|
||||
val librariesDestination = target.librariesDestination
|
||||
librariesDestination.mkdirs() // always create an empty directory even if there is nothing to copy
|
||||
|
||||
val manifestProvider = when (target) {
|
||||
is LeafTarget -> originalLibraries.librariesByTargets.getValue(target)
|
||||
is SharedTarget -> CommonNativeManifestDataProvider(originalLibraries.librariesByTargets.values)
|
||||
}
|
||||
|
||||
for (moduleResult in moduleResults) {
|
||||
when (moduleResult) {
|
||||
is ModuleResult.Commonized -> {
|
||||
val libraryName = moduleResult.libraryName
|
||||
|
||||
val manifestData = manifestProvider.getManifest(libraryName)
|
||||
val libraryDestination = librariesDestination.resolve(libraryName)
|
||||
|
||||
writeLibrary(moduleResult.metadata, manifestData, libraryDestination)
|
||||
}
|
||||
is ModuleResult.Missing -> {
|
||||
val libraryName = moduleResult.libraryName
|
||||
val missingModuleLocation = moduleResult.originalLocation
|
||||
|
||||
missingModuleLocation.copyRecursively(librariesDestination.resolve(libraryName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logProgress("Written libraries for ${target.prettyCommonizedName(sharedTarget)}")
|
||||
}
|
||||
|
||||
private fun writeLibrary(
|
||||
metadata: SerializedMetadata,
|
||||
manifestData: NativeSensitiveManifestData,
|
||||
libraryDestination: File
|
||||
) {
|
||||
val layout = KFile(libraryDestination.path).let { KotlinLibraryLayoutForWriter(it, it) }
|
||||
val library = KotlinLibraryWriterImpl(
|
||||
moduleName = manifestData.uniqueName,
|
||||
versions = manifestData.versions,
|
||||
builtInsPlatform = BuiltInsPlatform.NATIVE,
|
||||
nativeTargets = emptyList(), // will be overwritten with NativeSensitiveManifestData.applyTo() below
|
||||
nopack = true,
|
||||
shortName = manifestData.shortName,
|
||||
layout = layout
|
||||
)
|
||||
library.addMetadata(metadata)
|
||||
manifestData.applyTo(library.base as BaseWriterImpl)
|
||||
library.commit()
|
||||
}
|
||||
|
||||
private val LeafTarget.platformLibrariesSource: File
|
||||
get() = repository.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||
.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR)
|
||||
.resolve(name)
|
||||
|
||||
private val CommonizerTarget.librariesDestination: File
|
||||
get() = when (this) {
|
||||
is LeafTarget -> destination.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR).resolve(name)
|
||||
is SharedTarget -> destination.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
|
||||
}
|
||||
}
|
||||
+22
-21
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer.ModuleResult
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer.Status
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SourceModuleRoot.Companion.SHARED_TARGET_NAME
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ClassCollector
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.FunctionCollector
|
||||
@@ -72,25 +74,26 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
|
||||
val sourceModuleRoots: SourceModuleRoots = SourceModuleRoots.load(getTestDataDir())
|
||||
val analyzedModules: AnalyzedModules = AnalyzedModules.create(sourceModuleRoots, testRootDisposable)
|
||||
|
||||
val result: CommonizerResult = runCommonization(analyzedModules.toCommonizationParameters())
|
||||
assertCommonizationPerformed(result)
|
||||
val results = MockResultsConsumer()
|
||||
runCommonization(analyzedModules.toCommonizerParameters(results))
|
||||
assertEquals(Status.DONE, results.status)
|
||||
|
||||
val sharedTarget: SharedTarget = analyzedModules.sharedTarget
|
||||
assertEquals(sharedTarget, result.sharedTarget)
|
||||
assertEquals(sharedTarget, results.sharedTarget)
|
||||
|
||||
val sharedModuleAsExpected: SerializedMetadata = analyzedModules.commonizedModules.getValue(sharedTarget)
|
||||
val sharedModuleByCommonizer: SerializedMetadata =
|
||||
(result.modulesByTargets.getValue(sharedTarget).single() as ModuleResult.Commonized).metadata
|
||||
(results.modulesByTargets.getValue(sharedTarget).single() as ModuleResult.Commonized).metadata
|
||||
|
||||
assertModulesAreEqual(sharedModuleAsExpected, sharedModuleByCommonizer, sharedTarget)
|
||||
|
||||
val leafTargets: Set<LeafTarget> = analyzedModules.leafTargets
|
||||
assertEquals(leafTargets, result.leafTargets)
|
||||
assertEquals(leafTargets, results.leafTargets)
|
||||
|
||||
for (leafTarget in leafTargets) {
|
||||
val leafTargetModuleAsExpected: SerializedMetadata = analyzedModules.commonizedModules.getValue(leafTarget)
|
||||
val leafTargetModuleByCommonizer: SerializedMetadata =
|
||||
(result.modulesByTargets.getValue(leafTarget).single() as ModuleResult.Commonized).metadata
|
||||
(results.modulesByTargets.getValue(leafTarget).single() as ModuleResult.Commonized).metadata
|
||||
|
||||
assertModulesAreEqual(leafTargetModuleAsExpected, leafTargetModuleByCommonizer, leafTarget)
|
||||
}
|
||||
@@ -203,26 +206,24 @@ private class AnalyzedModules(
|
||||
check(allTargets.containsAll(dependeeModules.keys))
|
||||
}
|
||||
|
||||
fun toCommonizationParameters(): CommonizerParameters {
|
||||
val parameters = CommonizerParameters()
|
||||
fun toCommonizerParameters(resultsConsumer: ResultsConsumer) =
|
||||
CommonizerParameters().also { parameters ->
|
||||
parameters.resultsConsumer = resultsConsumer
|
||||
parameters.dependeeModulesProvider = dependeeModules[sharedTarget]?.let(MockModulesProvider::create)
|
||||
|
||||
leafTargets.forEach { leafTarget ->
|
||||
val originalModule = originalModules.getValue(leafTarget)
|
||||
leafTargets.forEach { leafTarget ->
|
||||
val originalModule = originalModules.getValue(leafTarget)
|
||||
|
||||
parameters.addTarget(
|
||||
TargetProvider(
|
||||
target = leafTarget,
|
||||
modulesProvider = MockModulesProvider.create(originalModule),
|
||||
dependeeModulesProvider = dependeeModules[leafTarget]?.let(MockModulesProvider::create)
|
||||
parameters.addTarget(
|
||||
TargetProvider(
|
||||
target = leafTarget,
|
||||
modulesProvider = MockModulesProvider.create(originalModule),
|
||||
dependeeModulesProvider = dependeeModules[leafTarget]?.let(MockModulesProvider::create)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
parameters.dependeeModulesProvider = dependeeModules[sharedTarget]?.let(MockModulesProvider::create)
|
||||
|
||||
return parameters
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun create(
|
||||
sourceModuleRoots: SourceModuleRoots,
|
||||
|
||||
+26
-17
@@ -5,11 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer.ModuleResult
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer.Status
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.MockResultsConsumer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.MockModulesProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.assertCommonizationPerformed
|
||||
import org.junit.Test
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
@ExperimentalContracts
|
||||
class CommonizerFacadeTest {
|
||||
@@ -59,26 +62,32 @@ class CommonizerFacadeTest {
|
||||
)
|
||||
|
||||
companion object {
|
||||
private fun Map<String, List<String>>.toCommonizationParameters() = CommonizerParameters().also {
|
||||
forEach { (targetName, moduleNames) ->
|
||||
it.addTarget(
|
||||
TargetProvider(
|
||||
target = LeafTarget(targetName),
|
||||
modulesProvider = MockModulesProvider.create(moduleNames),
|
||||
dependeeModulesProvider = null
|
||||
private fun Map<String, List<String>>.toCommonizerParameters(resultsConsumer: ResultsConsumer) =
|
||||
CommonizerParameters().also { parameters ->
|
||||
parameters.resultsConsumer = resultsConsumer
|
||||
|
||||
forEach { (targetName, moduleNames) ->
|
||||
parameters.addTarget(
|
||||
TargetProvider(
|
||||
target = LeafTarget(targetName),
|
||||
modulesProvider = MockModulesProvider.create(moduleNames),
|
||||
dependeeModulesProvider = null
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun doTestNothingToCommonize(originalModules: Map<String, List<String>>) {
|
||||
val result = runCommonization(originalModules.toCommonizationParameters())
|
||||
assertEquals(CommonizerResult.NothingToDo, result)
|
||||
val results = MockResultsConsumer()
|
||||
runCommonization(originalModules.toCommonizerParameters(results))
|
||||
assertEquals(results.status, Status.NOTHING_TO_DO)
|
||||
assertTrue(results.modulesByTargets.isEmpty())
|
||||
}
|
||||
|
||||
private fun doTestSuccessfulCommonization(originalModules: Map<String, List<String>>) {
|
||||
val result = runCommonization(originalModules.toCommonizationParameters())
|
||||
assertCommonizationPerformed(result)
|
||||
val results = MockResultsConsumer()
|
||||
runCommonization(originalModules.toCommonizerParameters(results))
|
||||
assertEquals(results.status, Status.DONE)
|
||||
|
||||
val expectedCommonModuleNames = mutableSetOf<String>()
|
||||
originalModules.values.forEachIndexed { index, moduleNames ->
|
||||
@@ -90,17 +99,17 @@ class CommonizerFacadeTest {
|
||||
assertModulesMatch(
|
||||
expectedCommonizedModuleNames = expectedCommonModuleNames,
|
||||
expectedMissingModuleNames = emptySet(),
|
||||
actualModuleResults = result.modulesByTargets.getValue(result.sharedTarget)
|
||||
actualModuleResults = results.modulesByTargets.getValue(results.sharedTarget)
|
||||
)
|
||||
|
||||
result.leafTargets.forEach { target ->
|
||||
results.leafTargets.forEach { target ->
|
||||
val allModuleNames = originalModules.getValue(target.name).toSet()
|
||||
val expectedMissingModuleNames = allModuleNames - expectedCommonModuleNames
|
||||
|
||||
assertModulesMatch(
|
||||
expectedCommonizedModuleNames = expectedCommonModuleNames,
|
||||
expectedMissingModuleNames = expectedMissingModuleNames,
|
||||
actualModuleResults = result.modulesByTargets.getValue(target)
|
||||
actualModuleResults = results.modulesByTargets.getValue(target)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
-12
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.utils
|
||||
|
||||
import kotlinx.metadata.klib.KlibModuleMetadata
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizerResult
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.utils.MetadataDeclarationsComparator
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.utils.MetadataDeclarationsComparator.Mismatch
|
||||
@@ -15,7 +14,6 @@ import org.jetbrains.kotlin.descriptors.commonizer.metadata.utils.SerializedMeta
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import java.io.File
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.test.fail
|
||||
|
||||
fun assertIsDirectory(file: File) {
|
||||
@@ -23,16 +21,6 @@ fun assertIsDirectory(file: File) {
|
||||
fail("Not a directory: $file")
|
||||
}
|
||||
|
||||
@ExperimentalContracts
|
||||
fun assertCommonizationPerformed(result: CommonizerResult) {
|
||||
contract {
|
||||
returns() implies (result is CommonizerResult.Done)
|
||||
}
|
||||
|
||||
if (result !is CommonizerResult.Done)
|
||||
fail("$result is not instance of ${CommonizerResult.Done::class}")
|
||||
}
|
||||
|
||||
@ExperimentalContracts
|
||||
fun assertModulesAreEqual(reference: SerializedMetadata, generated: SerializedMetadata, target: CommonizerTarget) {
|
||||
val referenceModule = with(reference) { KlibModuleMetadata.read(SerializedMetadataLibraryProvider(module, fragments, fragmentNames)) }
|
||||
|
||||
@@ -7,7 +7,8 @@ package org.jetbrains.kotlin.descriptors.commonizer.utils
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer.ModuleResult
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.ModuleInfo
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
|
||||
@@ -175,3 +176,23 @@ internal class MockModulesProvider private constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class MockResultsConsumer : ResultsConsumer {
|
||||
private val _modulesByTargets = LinkedHashMap<CommonizerTarget, Collection<ModuleResult>>() // use linked hash map to preserve order
|
||||
val modulesByTargets: Map<CommonizerTarget, Collection<ModuleResult>>
|
||||
get() = _modulesByTargets
|
||||
|
||||
val sharedTarget: SharedTarget by lazy { modulesByTargets.keys.filterIsInstance<SharedTarget>().single() }
|
||||
val leafTargets: Set<LeafTarget> by lazy { modulesByTargets.keys.filterIsInstance<LeafTarget>().toSet() }
|
||||
|
||||
lateinit var status: ResultsConsumer.Status
|
||||
|
||||
override fun consumeResults(target: CommonizerTarget, moduleResults: Collection<ModuleResult>) {
|
||||
val oldValue = _modulesByTargets.put(target, moduleResults)
|
||||
check(oldValue == null)
|
||||
}
|
||||
|
||||
override fun successfullyFinished(status: ResultsConsumer.Status) {
|
||||
this.status = status
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user