[Commonizer] Implement :native:kotlin-klib-commonizer:api with support for library commonization
- Implement new Gradle module ':native:kotlin-klib-commonizer' - Implement new NativeKlibCommonize task - Implement CommonizerTarget.identityString
This commit is contained in:
committed by
Space
parent
6d019d9544
commit
4500b6ce74
@@ -16,11 +16,13 @@ configurations {
|
||||
dependencies {
|
||||
embedded(project(":kotlinx-metadata-klib")) { isTransitive = false }
|
||||
embedded(project(":kotlinx-metadata")) { isTransitive = false }
|
||||
embedded(project(":native:kotlin-klib-commonizer-api")) { isTransitive = false }
|
||||
|
||||
// N.B. The order of "kotlinx-metadata*" dependencies makes sense for runtime classpath
|
||||
// of the "runCommonizer" task. Please, don't mix them up.
|
||||
compileOnly(project(":kotlinx-metadata-klib")) { isTransitive = false }
|
||||
compileOnly(project(":kotlinx-metadata")) { isTransitive = false }
|
||||
compileOnly(project(":native:kotlin-klib-commonizer-api")) { isTransitive = false }
|
||||
compileOnly(project(":compiler:cli-common"))
|
||||
compileOnly(project(":compiler:ir.serialization.common"))
|
||||
compileOnly(project(":compiler:frontend"))
|
||||
@@ -38,6 +40,7 @@ dependencies {
|
||||
testImplementation(projectTests(":compiler:tests-common"))
|
||||
testImplementation(project(":kotlinx-metadata-klib")) { isTransitive = false }
|
||||
testImplementation(project(":kotlinx-metadata")) { isTransitive = false }
|
||||
testImplementation(project(":native:kotlin-klib-commonizer-api"))
|
||||
}
|
||||
|
||||
val runCommonizer by tasks.registering(JavaExec::class) {
|
||||
|
||||
+5
-10
@@ -5,16 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.TargetedNativeManifestDataProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsCollector
|
||||
|
||||
class CommonizerParameters(
|
||||
val resultsConsumer: ResultsConsumer,
|
||||
val manifestDataProvider: TargetedNativeManifestDataProvider,
|
||||
val statsCollector: StatsCollector? = null,
|
||||
val progressLogger: ((String) -> Unit)? = null
|
||||
) {
|
||||
// use linked hash map to preserve order
|
||||
private val _targetProviders = LinkedHashMap<LeafTarget, TargetProvider>()
|
||||
private val _targetProviders = LinkedHashMap<LeafCommonizerTarget, TargetProvider>()
|
||||
val targetProviders: List<TargetProvider> get() = _targetProviders.values.toList()
|
||||
val sharedTarget: SharedTarget get() = SharedTarget(_targetProviders.keys)
|
||||
val sharedTarget: SharedCommonizerTarget get() = SharedCommonizerTarget(_targetProviders.keys)
|
||||
|
||||
// common module dependencies (ex: Kotlin stdlib)
|
||||
var dependencyModulesProvider: ModulesProvider? = null
|
||||
@@ -30,14 +33,6 @@ 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 getCommonModuleNames(): Set<String> {
|
||||
if (_targetProviders.size < 2) return emptySet() // too few targets
|
||||
|
||||
|
||||
@@ -1,36 +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.konan.target.KonanTarget
|
||||
|
||||
// N.B. TargetPlatform/SimplePlatform are non exhaustive enough to address both target platforms such as
|
||||
// JVM, JS and concrete Kotlin/Native targets, e.g. macos_x64, ios_x64, linux_x64.
|
||||
sealed class CommonizerTarget {
|
||||
abstract val name: String
|
||||
abstract val prettyName: String
|
||||
|
||||
fun prettyCommonizedName(sharedTarget: SharedTarget): String = when {
|
||||
this == sharedTarget -> prettyName
|
||||
this in sharedTarget.targets -> sharedTarget.targets.joinToString(prefix = "[", postfix = "]") {
|
||||
if (it == this) "${it.name}(*)" else it.name
|
||||
}
|
||||
else -> error("Target $prettyName is not in ${sharedTarget.prettyName}")
|
||||
}
|
||||
}
|
||||
|
||||
data class LeafTarget(override val name: String, val konanTarget: KonanTarget? = null) : CommonizerTarget() {
|
||||
override val prettyName get() = "[$name]"
|
||||
}
|
||||
|
||||
data class SharedTarget(val targets: Set<CommonizerTarget>) : CommonizerTarget() {
|
||||
init {
|
||||
require(targets.isNotEmpty())
|
||||
}
|
||||
|
||||
override val name get() = targets.joinToString(prefix = "[", postfix = "]") { it.name }
|
||||
override val prettyName get() = name
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.konan.library.*
|
||||
import java.io.File
|
||||
|
||||
internal data class KonanDistribution(val root: File)
|
||||
|
||||
internal val KonanDistribution.stdlib: File
|
||||
get() = root.resolve(konanCommonLibraryPath(KONAN_STDLIB_NAME))
|
||||
|
||||
internal val KonanDistribution.klibDir: File
|
||||
get() = root.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||
|
||||
internal val KonanDistribution.platformLibsDir: File
|
||||
get() = klibDir.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR)
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.backend.common.serialization.metadata.KlibMetadataVersion
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.metadataVersion
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeLibrary
|
||||
import org.jetbrains.kotlin.library.ToolingSingleFileKlibResolveStrategy
|
||||
import org.jetbrains.kotlin.library.resolveSingleFileKlib
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
import java.io.File
|
||||
|
||||
internal fun interface NativeLibraryLoader {
|
||||
operator fun invoke(file: File): NativeLibrary
|
||||
}
|
||||
|
||||
internal class DefaultNativeLibraryLoader(
|
||||
private val logger: Logger
|
||||
) : NativeLibraryLoader {
|
||||
override fun invoke(file: File): NativeLibrary {
|
||||
val library = resolveSingleFileKlib(
|
||||
libraryFile = org.jetbrains.kotlin.konan.file.File(file.path),
|
||||
logger = logger,
|
||||
strategy = ToolingSingleFileKlibResolveStrategy
|
||||
)
|
||||
|
||||
if (library.versions.metadataVersion == null)
|
||||
logger.fatal("Library does not have metadata version specified in manifest: $file")
|
||||
|
||||
val metadataVersion = library.metadataVersion
|
||||
if (metadataVersion?.isCompatible() != true)
|
||||
logger.fatal(
|
||||
"""
|
||||
Library has incompatible metadata version ${metadataVersion ?: "\"unknown\""}: $file
|
||||
Please make sure that all libraries passed to commonizer compatible metadata version ${KlibMetadataVersion.INSTANCE}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
return NativeLibrary(library)
|
||||
}
|
||||
}
|
||||
+56
-4
@@ -5,9 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeSensitiveManifestData
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import java.io.File
|
||||
|
||||
internal fun buildResultsConsumer(init: ResultsConsumerBuilder.() -> Unit): ResultsConsumer {
|
||||
return ResultsConsumerBuilder().apply(init).build()
|
||||
}
|
||||
|
||||
interface ResultsConsumer {
|
||||
enum class Status { NOTHING_TO_DO, DONE }
|
||||
|
||||
@@ -18,23 +23,70 @@ interface ResultsConsumer {
|
||||
override val libraryName: String get() = originalLocation.name
|
||||
}
|
||||
|
||||
class Commonized(override val libraryName: String, val metadata: SerializedMetadata) : ModuleResult()
|
||||
class Commonized(
|
||||
override val libraryName: String, val metadata: SerializedMetadata, val manifest: NativeSensitiveManifestData
|
||||
) : ModuleResult()
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume a single [ModuleResult] for the specified [CommonizerTarget].
|
||||
*/
|
||||
fun consume(target: CommonizerTarget, moduleResult: ModuleResult)
|
||||
fun consume(target: CommonizerTarget, moduleResult: ModuleResult) = Unit
|
||||
|
||||
/**
|
||||
* Mark the specified [CommonizerTarget] as fully consumed.
|
||||
* It's forbidden to make subsequent [consume] calls for fully consumed targets.
|
||||
*/
|
||||
fun targetConsumed(target: CommonizerTarget)
|
||||
fun targetConsumed(target: CommonizerTarget) = Unit
|
||||
|
||||
/**
|
||||
* Notify that all results have been consumed.
|
||||
* It's forbidden to make any subsequent [consume] and [targetConsumed] calls after this call.
|
||||
*/
|
||||
fun allConsumed(status: Status)
|
||||
fun allConsumed(status: Status) = Unit
|
||||
}
|
||||
|
||||
internal class ResultsConsumerBuilder {
|
||||
private var resultsConsumer: ResultsConsumer? = null
|
||||
|
||||
infix fun add(consumer: ResultsConsumer) {
|
||||
val resultsConsumer = this.resultsConsumer
|
||||
if (resultsConsumer == null) {
|
||||
this.resultsConsumer = consumer
|
||||
return
|
||||
}
|
||||
this.resultsConsumer = resultsConsumer + consumer
|
||||
}
|
||||
|
||||
fun build(): ResultsConsumer {
|
||||
return resultsConsumer ?: object : ResultsConsumer {}
|
||||
}
|
||||
}
|
||||
|
||||
operator fun ResultsConsumer.plus(other: ResultsConsumer?): ResultsConsumer {
|
||||
if (other == null) return this
|
||||
if (this is CompositeResultsConsumer) {
|
||||
return CompositeResultsConsumer(consumers + other)
|
||||
}
|
||||
return CompositeResultsConsumer(listOf(this, other))
|
||||
}
|
||||
|
||||
private class CompositeResultsConsumer(val consumers: List<ResultsConsumer>) : ResultsConsumer {
|
||||
override fun consume(target: CommonizerTarget, moduleResult: ResultsConsumer.ModuleResult) {
|
||||
consumers.forEach { consumer ->
|
||||
consumer.consume(target, moduleResult)
|
||||
}
|
||||
}
|
||||
|
||||
override fun targetConsumed(target: CommonizerTarget) {
|
||||
consumers.forEach { consumer ->
|
||||
consumer.targetConsumed(target)
|
||||
}
|
||||
}
|
||||
|
||||
override fun allConsumed(status: ResultsConsumer.Status) {
|
||||
consumers.forEach { consumer ->
|
||||
consumer.allConsumed(status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import java.io.File
|
||||
|
||||
class TargetProvider(
|
||||
val target: LeafTarget,
|
||||
val target: LeafCommonizerTarget,
|
||||
val modulesProvider: ModulesProvider,
|
||||
val dependencyModulesProvider: ModulesProvider?
|
||||
)
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* 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.cli
|
||||
|
||||
internal object DependencyLibrariesOptionType : LibrariesSetOptionType(
|
||||
mandatory = true,
|
||||
alias = "dependency-libraries",
|
||||
description = "';' separated list of klib file paths that can be used as dependency"
|
||||
)
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* 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.cli
|
||||
|
||||
internal object InputLibrariesOptionType : LibrariesSetOptionType(
|
||||
mandatory = true,
|
||||
alias = "input-libraries",
|
||||
description = "';' separated list of klib file paths that will get commonized"
|
||||
)
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.cli
|
||||
|
||||
import java.io.File
|
||||
|
||||
internal abstract class LibrariesSetOptionType(
|
||||
mandatory: Boolean,
|
||||
alias: String,
|
||||
description: String
|
||||
) : OptionType<List<File>>(
|
||||
mandatory = mandatory,
|
||||
alias = alias,
|
||||
description = description
|
||||
) {
|
||||
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<List<File>> {
|
||||
if (rawValue.isBlank()) {
|
||||
return Option(this, emptyList())
|
||||
}
|
||||
return Option(this, rawValue.split(";").map(::File))
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.cli
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.parseCommonizerTarget
|
||||
|
||||
internal object OutputCommonizerTargetOptionType : OptionType<SharedCommonizerTarget>(
|
||||
alias = "output-commonizer-target",
|
||||
description = "Shared commonizer target representing the commonized output hierarchy",
|
||||
mandatory = true
|
||||
) {
|
||||
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<SharedCommonizerTarget> {
|
||||
return try {
|
||||
Option(this, parseCommonizerTarget(rawValue) as SharedCommonizerTarget)
|
||||
} catch (t: Throwable) {
|
||||
onError("Failed parsing output-commonizer-target ($rawValue): ${t.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.cli
|
||||
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
|
||||
fun Logger.toProgressLogger(): Logger {
|
||||
return ProgressLogger(this)
|
||||
}
|
||||
|
||||
private class ProgressLogger(private val logger: Logger) : Logger by logger {
|
||||
override fun log(message: String) {
|
||||
logger.log("* $message")
|
||||
}
|
||||
|
||||
override fun warning(message: String) {
|
||||
logger.log("* $message")
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cli
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeDistributionCommonizer.StatsType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsType
|
||||
|
||||
internal object StatsTypeOptionType : OptionType<StatsType>("log-stats", DESCRIPTION, mandatory = false) {
|
||||
override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option<StatsType> {
|
||||
|
||||
@@ -40,7 +40,21 @@ internal enum class TaskType(
|
||||
NativeDistributionOptionType
|
||||
),
|
||||
::NativeDistributionListTargets
|
||||
);
|
||||
),
|
||||
|
||||
NATIVE_KLIB_COMMONIZE(
|
||||
"native-klib-commonize",
|
||||
"Commonize any platform-specific libraries",
|
||||
listOf(
|
||||
NativeDistributionOptionType,
|
||||
OutputOptionType,
|
||||
InputLibrariesOptionType,
|
||||
DependencyLibrariesOptionType,
|
||||
OutputCommonizerTargetOptionType,
|
||||
),
|
||||
::NativeKlibCommonize
|
||||
)
|
||||
;
|
||||
|
||||
companion object {
|
||||
fun getByAlias(alias: String) = values().firstOrNull { it.alias == alias }
|
||||
|
||||
+81
-20
@@ -5,8 +5,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cli
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.CopyUnconsumedModulesAsIsConsumer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.CopyStdlibResultsConsumer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeDistributionCommonizer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeDistributionCommonizer.StatsType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.ModuleSerializer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.repository.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.repository.EmptyRepository
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.repository.FilesRepository
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.repository.KonanDistributionRepository
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.repository.Repository
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.stats.FileStatsOutput
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsCollector
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsType
|
||||
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.target.KonanTarget
|
||||
@@ -35,11 +47,52 @@ internal class NativeDistributionListTargets(options: Collection<Option<*>>) : T
|
||||
}
|
||||
}
|
||||
|
||||
internal class NativeKlibCommonize(options: Collection<Option<*>>) : Task(options) {
|
||||
override val category: Category = Category.COMMONIZATION
|
||||
|
||||
override fun execute(logPrefix: String) {
|
||||
val distribution = KonanDistribution(getMandatory<File, NativeDistributionOptionType>())
|
||||
val destination = getMandatory<File, OutputOptionType>()
|
||||
val targetLibraries = getMandatory<List<File>, InputLibrariesOptionType>()
|
||||
val dependencyLibraries = getMandatory<List<File>, DependencyLibrariesOptionType>()
|
||||
val outputCommonizerTarget = getMandatory<SharedCommonizerTarget, OutputCommonizerTargetOptionType>()
|
||||
val statsType = getOptional<StatsType, StatsTypeOptionType> { it == "log-stats" } ?: StatsType.NONE
|
||||
|
||||
val konanTargets = outputCommonizerTarget.konanTargets
|
||||
val logger = CliLoggerAdapter(2)
|
||||
val libraryLoader = DefaultNativeLibraryLoader(logger)
|
||||
val statsCollector = StatsCollector(statsType, outputCommonizerTarget.konanTargets.toList())
|
||||
val repository = FilesRepository(targetLibraries.toSet(), libraryLoader)
|
||||
|
||||
val resultsConsumer = buildResultsConsumer {
|
||||
this add ModuleSerializer(destination, HierarchicalCommonizerOutputLayout)
|
||||
this add CopyUnconsumedModulesAsIsConsumer(
|
||||
repository, destination, konanTargets, NativeDistributionCommonizerOutputLayout, logger.toProgressLogger()
|
||||
)
|
||||
this add LoggingResultsConsumer(outputCommonizerTarget, logger.toProgressLogger())
|
||||
}
|
||||
|
||||
NativeDistributionCommonizer(
|
||||
konanDistribution = distribution,
|
||||
repository = repository,
|
||||
dependencies = KonanDistributionRepository(distribution, outputCommonizerTarget.konanTargets, libraryLoader) +
|
||||
FilesRepository(dependencyLibraries.toSet(), libraryLoader),
|
||||
libraryLoader = libraryLoader,
|
||||
targets = outputCommonizerTarget.konanTargets.toList(),
|
||||
resultsConsumer = resultsConsumer,
|
||||
statsCollector = statsCollector,
|
||||
logger = logger
|
||||
).run()
|
||||
|
||||
statsCollector?.writeTo(FileStatsOutput(destination, statsType.name.toLowerCase()))
|
||||
}
|
||||
}
|
||||
|
||||
internal class NativeDistributionCommonize(options: Collection<Option<*>>) : Task(options) {
|
||||
override val category get() = Category.COMMONIZATION
|
||||
|
||||
override fun execute(logPrefix: String) {
|
||||
val distribution = getMandatory<File, NativeDistributionOptionType>()
|
||||
val distribution = KonanDistribution(getMandatory<File, NativeDistributionOptionType>())
|
||||
val destination = getMandatory<File, OutputOptionType>()
|
||||
val targets = getMandatory<List<KonanTarget>, NativeTargetsOptionType>()
|
||||
|
||||
@@ -47,35 +100,43 @@ internal class NativeDistributionCommonize(options: Collection<Option<*>>) : Tas
|
||||
val copyEndorsedLibs = getOptional<Boolean, BooleanOptionType> { it == "copy-endorsed-libs" } ?: false
|
||||
val statsType = getOptional<StatsType, StatsTypeOptionType> { it == "log-stats" } ?: StatsType.NONE
|
||||
|
||||
val targetNames = targets.joinToString { "[${it.name}]" }
|
||||
val descriptionSuffix = estimateLibrariesCount(distribution, targets)?.let { " ($it items)" } ?: ""
|
||||
val description = "${logPrefix}Preparing commonized Kotlin/Native libraries for targets $targetNames$descriptionSuffix"
|
||||
val logger = CliLoggerAdapter(2)
|
||||
val libraryLoader = DefaultNativeLibraryLoader(logger)
|
||||
val repository = KonanDistributionRepository(distribution, targets.toSet(), libraryLoader)
|
||||
val statsCollector = StatsCollector(statsType, targets.toList())
|
||||
|
||||
val resultsConsumer = buildResultsConsumer {
|
||||
this add ModuleSerializer(destination, NativeDistributionCommonizerOutputLayout)
|
||||
this add CopyUnconsumedModulesAsIsConsumer(
|
||||
repository, destination, targets.toSet(), NativeDistributionCommonizerOutputLayout, logger.toProgressLogger()
|
||||
)
|
||||
if (copyStdlib) this add CopyStdlibResultsConsumer(distribution, destination, logger.toProgressLogger())
|
||||
if (copyEndorsedLibs) this add CopyEndorsedLibrairesResultsConsumer(distribution, destination, logger.toProgressLogger())
|
||||
this add LoggingResultsConsumer(SharedCommonizerTarget(targets), logger.toProgressLogger())
|
||||
}
|
||||
|
||||
val targetNames = targets.joinToString { "[${it.name}]" }
|
||||
val descriptionSuffix = estimateLibrariesCount(repository, targets).let { " ($it items)" }
|
||||
val description = "${logPrefix}Preparing commonized Kotlin/Native libraries for targets $targetNames$descriptionSuffix"
|
||||
println(description)
|
||||
|
||||
NativeDistributionCommonizer(
|
||||
repository = distribution,
|
||||
repository = repository,
|
||||
konanDistribution = distribution,
|
||||
dependencies = EmptyRepository,
|
||||
libraryLoader = libraryLoader,
|
||||
targets = targets,
|
||||
destination = destination,
|
||||
copyStdlib = copyStdlib,
|
||||
copyEndorsedLibs = copyEndorsedLibs,
|
||||
statsType = statsType,
|
||||
logger = CliLoggerAdapter(2)
|
||||
resultsConsumer = resultsConsumer,
|
||||
statsCollector = statsCollector,
|
||||
logger = logger
|
||||
).run()
|
||||
|
||||
println("$description: Done")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun estimateLibrariesCount(distribution: File, targets: List<KonanTarget>): Int? {
|
||||
val targetNames = targets.map { it.name }
|
||||
return distribution.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||
.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR)
|
||||
.listFiles()
|
||||
?.filter { it.name in targetNames }
|
||||
?.mapNotNull { it.listFiles() }
|
||||
?.flatMap { it.toList() }
|
||||
?.size
|
||||
private fun estimateLibrariesCount(repository: Repository, targets: List<KonanTarget>): Int {
|
||||
return targets.flatMap { repository.getLibraries(LeafCommonizerTarget(it)) }.count()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -5,24 +5,24 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirRoot
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirRootFactory
|
||||
|
||||
class RootCommonizer : AbstractStandardCommonizer<CirRoot, CirRoot>() {
|
||||
private val leafTargets = mutableSetOf<LeafTarget>()
|
||||
private val leafTargets = mutableSetOf<LeafCommonizerTarget>()
|
||||
|
||||
override fun commonizationResult() = CirRootFactory.create(
|
||||
target = SharedTarget(leafTargets)
|
||||
target = SharedCommonizerTarget(leafTargets)
|
||||
)
|
||||
|
||||
override fun initialize(first: CirRoot) {
|
||||
leafTargets += first.target as LeafTarget
|
||||
leafTargets += first.target as LeafCommonizerTarget
|
||||
}
|
||||
|
||||
override fun doCommonizeWith(next: CirRoot): Boolean {
|
||||
leafTargets += next.target as LeafTarget
|
||||
leafTargets += next.target as LeafCommonizerTarget
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,11 +67,11 @@ private fun serializeTarget(mergeResult: CirTreeMergeResult, targetIndex: Int, p
|
||||
val serializedMetadata = with(metadataModule.write(KLIB_FRAGMENT_WRITE_STRATEGY)) {
|
||||
SerializedMetadata(header, fragments, fragmentNames)
|
||||
}
|
||||
|
||||
parameters.resultsConsumer.consume(target, ModuleResult.Commonized(libraryName, serializedMetadata))
|
||||
val manifestData = parameters.manifestDataProvider.getManifest(target, libraryName)
|
||||
parameters.resultsConsumer.consume(target, ModuleResult.Commonized(libraryName, serializedMetadata, manifestData))
|
||||
}
|
||||
|
||||
if (target is LeafTarget) {
|
||||
if (target is LeafCommonizerTarget) {
|
||||
mergeResult.missingModuleInfos.getValue(target).forEach {
|
||||
parameters.resultsConsumer.consume(target, ModuleResult.Missing(it.originalLocation))
|
||||
}
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.descriptors.commonizer.konan
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.KonanDistribution
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.klibDir
|
||||
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_COMMON_LIBS_DIR
|
||||
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
import java.io.File
|
||||
|
||||
internal fun CopyStdlibResultsConsumer(
|
||||
konanDistribution: KonanDistribution,
|
||||
destination: File,
|
||||
logger: Logger
|
||||
): ResultsConsumer {
|
||||
return CopyLibrariesFromKonanDistributionResultsConsumer(
|
||||
konanDistribution,
|
||||
destination,
|
||||
invokeWhenCopied = { logger.log("Copied standard library") },
|
||||
copyFileIf = { file -> file.endsWith(KONAN_STDLIB_NAME) }
|
||||
)
|
||||
}
|
||||
|
||||
internal fun CopyEndorsedLibrairesResultsConsumer(
|
||||
konanDistribution: KonanDistribution,
|
||||
destination: File,
|
||||
logger: Logger
|
||||
): ResultsConsumer {
|
||||
return CopyLibrariesFromKonanDistributionResultsConsumer(
|
||||
konanDistribution,
|
||||
destination,
|
||||
invokeWhenCopied = { logger.log("Copied endorsed libraries") },
|
||||
copyFileIf = { file -> !file.endsWith(KONAN_STDLIB_NAME) }
|
||||
)
|
||||
}
|
||||
|
||||
private class CopyLibrariesFromKonanDistributionResultsConsumer(
|
||||
private val konanDistribution: KonanDistribution,
|
||||
private val destination: File,
|
||||
private val invokeWhenCopied: () -> Unit = {},
|
||||
private val copyFileIf: (File) -> Boolean = { true }
|
||||
) : ResultsConsumer {
|
||||
override fun allConsumed(status: ResultsConsumer.Status) {
|
||||
konanDistribution.klibDir
|
||||
.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
|
||||
.listFiles().orEmpty()
|
||||
.filter { it.isDirectory }
|
||||
.filterNot(copyFileIf)
|
||||
.forEach { libraryOrigin ->
|
||||
val libraryDestination = destination.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR).resolve(libraryOrigin.name)
|
||||
libraryOrigin.copyRecursively(libraryDestination)
|
||||
}
|
||||
invokeWhenCopied()
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.repository.Repository
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
import java.io.File
|
||||
|
||||
internal class CopyUnconsumedModulesAsIsConsumer(
|
||||
private val repository: Repository,
|
||||
private val destination: File,
|
||||
private val targets: Set<KonanTarget>,
|
||||
private val outputLayout: CommonizerOutputLayout,
|
||||
private val logger: Logger? = null
|
||||
) : ResultsConsumer {
|
||||
|
||||
private val consumedTargets = mutableSetOf<KonanTarget>()
|
||||
|
||||
override fun targetConsumed(target: CommonizerTarget) {
|
||||
if (target is LeafCommonizerTarget) {
|
||||
consumedTargets.add(target.konanTarget)
|
||||
}
|
||||
}
|
||||
|
||||
override fun allConsumed(status: ResultsConsumer.Status) {
|
||||
when (status) {
|
||||
ResultsConsumer.Status.NOTHING_TO_DO -> targets.forEach(::copyTargetAsIs)
|
||||
ResultsConsumer.Status.DONE -> targets.minus(consumedTargets).forEach(::copyTargetAsIs)
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyTargetAsIs(target: KonanTarget) {
|
||||
val commonizerTarget = CommonizerTarget(target)
|
||||
val libraries = repository.getLibraries(commonizerTarget)
|
||||
val librariesDestination = outputLayout.getTargetDirectory(destination, commonizerTarget)
|
||||
librariesDestination.mkdirs() // always create an empty directory even if there is nothing to copy
|
||||
libraries.map { it.library.libraryFile.absolutePath }.map(::File).forEach { libraryFile ->
|
||||
libraryFile.copyRecursively(destination.resolve(libraryFile.name))
|
||||
}
|
||||
|
||||
logger?.log("Copied ${libraries.size} libraries for ${commonizerTarget.prettyName}")
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.CommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.prettyName
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
|
||||
internal class LoggingResultsConsumer(
|
||||
private val outputCommonizerTarget: SharedCommonizerTarget, private val logger: Logger
|
||||
) : ResultsConsumer {
|
||||
override fun targetConsumed(target: CommonizerTarget) {
|
||||
logger.log("Written libraries for ${outputCommonizerTarget.prettyName(target)}")
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.*
|
||||
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 org.jetbrains.kotlin.util.Logger
|
||||
import java.io.File
|
||||
|
||||
internal class ModuleSerializer(
|
||||
private val destination: File,
|
||||
private val outputLayout: CommonizerOutputLayout,
|
||||
) : ResultsConsumer {
|
||||
override fun consume(target: CommonizerTarget, moduleResult: ResultsConsumer.ModuleResult) {
|
||||
val librariesDestination = outputLayout.getTargetDirectory(destination, target)
|
||||
when (moduleResult) {
|
||||
is ResultsConsumer.ModuleResult.Commonized -> {
|
||||
val libraryName = moduleResult.libraryName
|
||||
val libraryDestination = librariesDestination.resolve(libraryName)
|
||||
writeLibrary(moduleResult.metadata, moduleResult.manifest, libraryDestination)
|
||||
}
|
||||
is ResultsConsumer.ModuleResult.Missing -> {
|
||||
val libraryName = moduleResult.libraryName
|
||||
val missingModuleLocation = moduleResult.originalLocation
|
||||
missingModuleLocation.copyRecursively(librariesDestination.resolve(libraryName))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeLibrary(
|
||||
metadata: SerializedMetadata,
|
||||
manifestData: NativeSensitiveManifestData,
|
||||
libraryDestination: File
|
||||
) {
|
||||
val layout = org.jetbrains.kotlin.konan.file.File(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()
|
||||
}
|
||||
+36
-105
@@ -5,160 +5,91 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.konan
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.metadataVersion
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeDistributionCommonizer.StatsType.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.stats.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cli.toProgressLogger
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeDistributionCommonizer.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.repository.Repository
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsCollector
|
||||
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.ToolingSingleFileKlibResolveStrategy
|
||||
import org.jetbrains.kotlin.library.resolveSingleFileKlib
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
import java.io.File
|
||||
import org.jetbrains.kotlin.konan.file.File as KFile
|
||||
|
||||
class NativeDistributionCommonizer(
|
||||
private val repository: File,
|
||||
internal class NativeDistributionCommonizer internal constructor(
|
||||
private val konanDistribution: KonanDistribution,
|
||||
private val repository: Repository,
|
||||
private val dependencies: Repository,
|
||||
private val libraryLoader: NativeLibraryLoader,
|
||||
private val targets: List<KonanTarget>,
|
||||
private val destination: File,
|
||||
private val copyStdlib: Boolean,
|
||||
private val copyEndorsedLibs: Boolean,
|
||||
private val statsType: StatsType,
|
||||
private val resultsConsumer: ResultsConsumer,
|
||||
private val statsCollector: StatsCollector?,
|
||||
private val logger: Logger
|
||||
) {
|
||||
enum class StatsType { RAW, AGGREGATED, NONE }
|
||||
|
||||
private val clockMark = ResettableClockMark()
|
||||
|
||||
fun run() {
|
||||
checkPreconditions()
|
||||
clockMark.reset()
|
||||
|
||||
// 1. load libraries
|
||||
val allLibraries = loadLibraries()
|
||||
|
||||
// 2. run commonization & write new libraries
|
||||
commonizeAndSaveResults(allLibraries)
|
||||
|
||||
logTotal()
|
||||
}
|
||||
|
||||
private fun checkPreconditions() {
|
||||
if (!repository.isDirectory)
|
||||
logger.fatal("Repository does not exist: $repository")
|
||||
|
||||
when (targets.size) {
|
||||
0 -> logger.fatal("No targets specified")
|
||||
1 -> logger.fatal("Too few targets specified: $targets")
|
||||
}
|
||||
|
||||
when {
|
||||
!destination.exists() -> destination.mkdirs()
|
||||
!destination.isDirectory -> logger.fatal("Output already exists: $destination")
|
||||
destination.walkTopDown().any { it != destination } -> logger.fatal("Output is not empty: $destination")
|
||||
}
|
||||
}
|
||||
|
||||
private fun logProgress(message: String) = logger.log("* $message in ${clockMark.elapsedSinceLast()}")
|
||||
|
||||
private fun logTotal() = logger.log("TOTAL: ${clockMark.elapsedSinceStart()}")
|
||||
|
||||
private fun loadLibraries(): AllNativeLibraries {
|
||||
val stdlibPath = repository.resolve(konanCommonLibraryPath(KONAN_STDLIB_NAME))
|
||||
val stdlib = NativeLibrary(loadLibrary(stdlibPath))
|
||||
val stdlib = libraryLoader(konanDistribution.stdlib)
|
||||
|
||||
val librariesByTargets = targets.associate { target ->
|
||||
val leafTarget = LeafTarget(target.name, target)
|
||||
|
||||
val platformLibs = leafTarget.platformLibrariesSource
|
||||
.takeIf { it.isDirectory }
|
||||
?.listFiles()
|
||||
?.takeIf { it.isNotEmpty() }
|
||||
?.map { NativeLibrary(loadLibrary(it)) }
|
||||
.orEmpty()
|
||||
|
||||
if (platformLibs.isEmpty())
|
||||
logger.warning("No platform libraries found for target ${leafTarget.prettyName}. This target will be excluded from commonization.")
|
||||
|
||||
leafTarget to NativeLibrariesToCommonize(platformLibs)
|
||||
val librariesByTargets = targets.map(::LeafCommonizerTarget).associateWith { target ->
|
||||
NativeLibrariesToCommonize(repository.getLibraries(target).toList())
|
||||
}
|
||||
|
||||
librariesByTargets.forEach { (target, librariesToCommonize) ->
|
||||
if (librariesToCommonize.libraries.isEmpty()) {
|
||||
logger.warning("No platform libraries found for target $target. This target will be excluded from commonization.")
|
||||
}
|
||||
}
|
||||
logProgress("Read lazy (uninitialized) libraries")
|
||||
|
||||
return AllNativeLibraries(stdlib, librariesByTargets)
|
||||
}
|
||||
|
||||
private fun loadLibrary(location: File): KotlinLibrary {
|
||||
if (!location.isDirectory)
|
||||
logger.fatal("Library not found: $location")
|
||||
|
||||
val library = resolveSingleFileKlib(
|
||||
libraryFile = KFile(location.path),
|
||||
logger = logger,
|
||||
strategy = ToolingSingleFileKlibResolveStrategy
|
||||
)
|
||||
|
||||
if (library.versions.metadataVersion == null)
|
||||
logger.fatal("Library does not have metadata version specified in manifest: $location")
|
||||
|
||||
val metadataVersion = library.metadataVersion
|
||||
if (metadataVersion?.isCompatible() != true)
|
||||
logger.fatal(
|
||||
"""
|
||||
Library has incompatible metadata version ${metadataVersion ?: "\"unknown\""}: $location
|
||||
Please make sure that all libraries passed to commonizer compatible metadata version ${KlibMetadataVersion.INSTANCE}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
return library
|
||||
}
|
||||
|
||||
private fun commonizeAndSaveResults(allLibraries: AllNativeLibraries) {
|
||||
val statsCollector = when (statsType) {
|
||||
RAW -> RawStatsCollector(targets)
|
||||
AGGREGATED -> AggregatedStatsCollector(targets)
|
||||
NONE -> null
|
||||
}
|
||||
val manifestProvider = TargetedNativeManifestDataProvider(allLibraries)
|
||||
|
||||
val parameters = CommonizerParameters(statsCollector, ::logProgress).apply {
|
||||
val parameters = CommonizerParameters(resultsConsumer, manifestProvider, statsCollector, ::logProgress).apply {
|
||||
val storageManager = LockBasedStorageManager("Commonized modules")
|
||||
|
||||
resultsConsumer = NativeDistributionResultsConsumer(
|
||||
repository = repository,
|
||||
originalLibraries = allLibraries,
|
||||
destination = destination,
|
||||
copyStdlib = copyStdlib,
|
||||
copyEndorsedLibs = copyEndorsedLibs,
|
||||
logProgress = ::logProgress
|
||||
)
|
||||
dependencyModulesProvider = NativeDistributionModulesProvider.forStandardLibrary(storageManager, allLibraries.stdlib)
|
||||
|
||||
allLibraries.librariesByTargets.forEach { (target, librariesToCommonize) ->
|
||||
if (librariesToCommonize.libraries.isEmpty()) return@forEach
|
||||
|
||||
val modulesProvider = NativeDistributionModulesProvider.platformLibraries(storageManager, librariesToCommonize)
|
||||
val dependencyModuleProvider = NativeDistributionModulesProvider.platformLibraries(
|
||||
storageManager, NativeLibrariesToCommonize(dependencies.getLibraries(target).toList()),
|
||||
)
|
||||
|
||||
addTarget(
|
||||
TargetProvider(
|
||||
target = target,
|
||||
modulesProvider = modulesProvider,
|
||||
dependencyModulesProvider = null // stdlib is already set as common dependency
|
||||
dependencyModulesProvider = dependencyModuleProvider
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
runCommonization(parameters)
|
||||
|
||||
statsCollector?.writeTo(FileStatsOutput(destination, statsType.name.toLowerCase()))
|
||||
}
|
||||
|
||||
private val LeafTarget.platformLibrariesSource: File
|
||||
get() = repository.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
|
||||
.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR)
|
||||
.resolve(name)
|
||||
private fun checkPreconditions() {
|
||||
when (targets.size) {
|
||||
0 -> logger.fatal("No targets specified")
|
||||
1 -> logger.fatal("Too few targets specified: $targets")
|
||||
}
|
||||
}
|
||||
|
||||
private fun logProgress(message: String) = logger.toProgressLogger().log("$message in ${clockMark.elapsedSinceLast()}")
|
||||
|
||||
private fun logTotal() = logger.log("TOTAL: ${clockMark.elapsedSinceStart()}")
|
||||
}
|
||||
|
||||
-2
@@ -34,8 +34,6 @@ internal abstract class NativeDistributionModulesProvider(libraries: Collection<
|
||||
protected val moduleInfoMap: Map<String, NativeModuleInfo>
|
||||
|
||||
init {
|
||||
check(libraries.isNotEmpty()) { "No libraries supplied" }
|
||||
|
||||
val libraryMap = mutableMapOf<String, NativeLibrary>()
|
||||
val moduleInfoMap = mutableMapOf<String, NativeModuleInfo>()
|
||||
|
||||
|
||||
-172
@@ -1,172 +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.descriptors.commonizer.konan
|
||||
|
||||
import com.intellij.util.containers.FactoryMap
|
||||
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 allLeafTargets = originalLibraries.librariesByTargets.keys
|
||||
|
||||
private val allLeafCommonizedTargets = originalLibraries.librariesByTargets.filterValues { it.libraries.isNotEmpty() }.keys
|
||||
private val sharedTarget = SharedTarget(allLeafCommonizedTargets)
|
||||
|
||||
private val consumedTargets = LinkedHashSet<CommonizerTarget>()
|
||||
|
||||
private val cachedManifestProviders = FactoryMap.create<CommonizerTarget, NativeManifestDataProvider> { target ->
|
||||
when (target) {
|
||||
is LeafTarget -> originalLibraries.librariesByTargets.getValue(target)
|
||||
is SharedTarget -> CommonNativeManifestDataProvider(originalLibraries.librariesByTargets.values)
|
||||
}
|
||||
}
|
||||
|
||||
private val cachedLibrariesDestination = FactoryMap.create<CommonizerTarget, File> { target ->
|
||||
val librariesDestination = when (target) {
|
||||
is LeafTarget -> destination.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR).resolve(target.name)
|
||||
is SharedTarget -> destination.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
|
||||
}
|
||||
|
||||
librariesDestination.mkdirs() // always create an empty directory even if there is nothing to copy
|
||||
librariesDestination
|
||||
}
|
||||
|
||||
override fun consume(target: CommonizerTarget, moduleResult: ModuleResult) {
|
||||
check(target in allLeafCommonizedTargets || target == sharedTarget)
|
||||
consumedTargets += target
|
||||
|
||||
serializeModule(target, moduleResult)
|
||||
}
|
||||
|
||||
override fun targetConsumed(target: CommonizerTarget) {
|
||||
check(target in consumedTargets)
|
||||
|
||||
logProgress("Written libraries for ${target.prettyCommonizedName(sharedTarget)}")
|
||||
}
|
||||
|
||||
override fun allConsumed(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 = cachedLibrariesDestination.getValue(leafTarget)
|
||||
|
||||
val librariesSource = leafTarget.platformLibrariesSource
|
||||
if (librariesSource.isDirectory) librariesSource.copyRecursively(librariesDestination)
|
||||
|
||||
logProgress("Copied $librariesCount libraries for ${leafTarget.prettyName}")
|
||||
}
|
||||
|
||||
private fun serializeModule(target: CommonizerTarget, moduleResult: ModuleResult) {
|
||||
val librariesDestination = cachedLibrariesDestination.getValue(target)
|
||||
|
||||
when (moduleResult) {
|
||||
is ModuleResult.Commonized -> {
|
||||
val libraryName = moduleResult.libraryName
|
||||
|
||||
val manifestData = cachedManifestProviders.getValue(target).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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
+21
-2
@@ -5,14 +5,33 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.konan
|
||||
|
||||
import com.intellij.util.containers.FactoryMap
|
||||
import gnu.trove.THashMap
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedCommonizerTarget
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
|
||||
fun interface TargetedNativeManifestDataProvider {
|
||||
fun getManifest(target: CommonizerTarget, libraryName: String): NativeSensitiveManifestData
|
||||
}
|
||||
|
||||
internal interface NativeManifestDataProvider {
|
||||
fun getManifest(libraryName: String): NativeSensitiveManifestData
|
||||
}
|
||||
|
||||
internal fun TargetedNativeManifestDataProvider(libraries: AllNativeLibraries): TargetedNativeManifestDataProvider {
|
||||
val cachedManifestProviders: Map<CommonizerTarget, NativeManifestDataProvider> = FactoryMap.create { target ->
|
||||
when (target) {
|
||||
is LeafCommonizerTarget -> libraries.librariesByTargets.getValue(target)
|
||||
is SharedCommonizerTarget -> CommonNativeManifestDataProvider(libraries.librariesByTargets.values)
|
||||
}
|
||||
}
|
||||
return TargetedNativeManifestDataProvider { target, libraryName ->
|
||||
cachedManifestProviders.getValue(target).getManifest(libraryName)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A separate Kotlin/Native library.
|
||||
*/
|
||||
@@ -37,7 +56,7 @@ internal class NativeLibrariesToCommonize(val libraries: List<NativeLibrary>) :
|
||||
|
||||
internal class AllNativeLibraries(
|
||||
val stdlib: NativeLibrary,
|
||||
val librariesByTargets: Map<LeafTarget, NativeLibrariesToCommonize>
|
||||
val librariesByTargets: Map<LeafCommonizerTarget, NativeLibrariesToCommonize>
|
||||
)
|
||||
|
||||
internal class CommonNativeManifestDataProvider(
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.library.impl.BaseWriterImpl
|
||||
* The set of properties in manifest of Kotlin/Native library that should be
|
||||
* preserved in commonized libraries (both for "common" and platform-specific library parts).
|
||||
*/
|
||||
internal data class NativeSensitiveManifestData(
|
||||
data class NativeSensitiveManifestData(
|
||||
val uniqueName: String,
|
||||
val versions: KotlinLibraryVersioning,
|
||||
val dependencies: List<String>,
|
||||
|
||||
+2
-4
@@ -6,10 +6,8 @@
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.ModuleInfo
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizerParameters
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.TargetProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackageName
|
||||
@@ -49,7 +47,7 @@ class CirTreeMerger(
|
||||
) {
|
||||
class CirTreeMergeResult(
|
||||
val root: CirRootNode,
|
||||
val missingModuleInfos: Map<LeafTarget, Collection<ModuleInfo>>
|
||||
val missingModuleInfos: Map<LeafCommonizerTarget, Collection<ModuleInfo>>
|
||||
)
|
||||
|
||||
private val size = parameters.targetProviders.size
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
import gnu.trove.THashMap
|
||||
import gnu.trove.THashSet
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackageName
|
||||
@@ -25,7 +25,7 @@ class CirKnownClassifiers(
|
||||
) {
|
||||
// a shortcut for fast access
|
||||
val commonDependencies: CirProvidedClassifiers =
|
||||
dependencies.filterKeys { it is SharedTarget }.values.singleOrNull() ?: CirProvidedClassifiers.EMPTY
|
||||
dependencies.filterKeys { it is SharedCommonizerTarget }.values.singleOrNull() ?: CirProvidedClassifiers.EMPTY
|
||||
}
|
||||
|
||||
interface CirCommonizedClassifiers {
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.repository
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.NativeLibraryLoader
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeLibrary
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import java.io.File
|
||||
|
||||
internal class FilesRepository(
|
||||
private val libraryFiles: Set<File>,
|
||||
private val libraryLoader: NativeLibraryLoader
|
||||
) : Repository {
|
||||
|
||||
private val librariesByTarget: Map<CommonizerTarget, Set<NativeLibrary>> by lazy {
|
||||
libraryFiles
|
||||
.map(libraryLoader::invoke)
|
||||
.groupBy { library -> CommonizerTarget(library.manifestData.nativeTargets.map(::konanTargetOrThrow)) }
|
||||
.mapValues { (_, list) -> list.toSet() }
|
||||
}
|
||||
|
||||
override fun getLibraries(target: LeafCommonizerTarget): Set<NativeLibrary> {
|
||||
return librariesByTarget[target].orEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
private fun konanTargetOrThrow(value: String): KonanTarget {
|
||||
return KonanTarget.predefinedTargets[value] ?: error("Unexpected KonanTarget $value")
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.repository
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.KonanDistribution
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.NativeLibraryLoader
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeLibrary
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.platformLibsDir
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
internal class KonanDistributionRepository(
|
||||
konanDistribution: KonanDistribution,
|
||||
targets: Set<KonanTarget>,
|
||||
libraryLoader: NativeLibraryLoader,
|
||||
) : Repository {
|
||||
|
||||
private val librariesByTarget: Map<LeafCommonizerTarget, Lazy<Set<NativeLibrary>>> =
|
||||
targets.map(::LeafCommonizerTarget).associateWith { target ->
|
||||
lazy {
|
||||
konanDistribution.platformLibsDir
|
||||
.resolve(target.name)
|
||||
.takeIf { it.isDirectory }
|
||||
?.listFiles()
|
||||
.orEmpty().toList()
|
||||
.map { libraryLoader(it) }
|
||||
.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLibraries(target: LeafCommonizerTarget): Set<NativeLibrary> {
|
||||
return librariesByTarget[target]?.value ?: error("Missing target $target")
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.repository
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeLibrary
|
||||
|
||||
internal interface Repository {
|
||||
fun getLibraries(target: LeafCommonizerTarget): Set<NativeLibrary>
|
||||
}
|
||||
|
||||
internal operator fun Repository.plus(other: Repository): Repository {
|
||||
if (this is CompositeRepository) {
|
||||
return CompositeRepository(this.repositories + other)
|
||||
}
|
||||
return CompositeRepository(listOf(this, other))
|
||||
}
|
||||
|
||||
private class CompositeRepository(val repositories: Iterable<Repository>) : Repository {
|
||||
override fun getLibraries(target: LeafCommonizerTarget): Set<NativeLibrary> {
|
||||
return repositories.map { it.getLibraries(target) }.flatten().toSet()
|
||||
}
|
||||
}
|
||||
|
||||
internal object EmptyRepository : Repository {
|
||||
override fun getLibraries(target: LeafCommonizerTarget): Set<NativeLibrary> {
|
||||
return emptySet()
|
||||
}
|
||||
}
|
||||
+14
@@ -5,6 +5,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.stats
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
fun StatsCollector(type: StatsType, targets: List<KonanTarget>): StatsCollector? {
|
||||
return when (type) {
|
||||
StatsType.RAW -> RawStatsCollector(targets)
|
||||
StatsType.AGGREGATED -> AggregatedStatsCollector(targets)
|
||||
StatsType.NONE -> null
|
||||
}
|
||||
}
|
||||
|
||||
enum class StatsType {
|
||||
RAW, AGGREGATED, NONE;
|
||||
}
|
||||
|
||||
interface StatsCollector {
|
||||
data class StatsKey(
|
||||
val id: String,
|
||||
|
||||
+30
-29
@@ -23,6 +23,7 @@ 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.konan.TargetedNativeManifestDataProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ClassCollector
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.FunctionCollector
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.collectMembers
|
||||
@@ -75,7 +76,7 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
|
||||
runCommonization(analyzedModules.toCommonizerParameters(results))
|
||||
assertEquals(Status.DONE, results.status)
|
||||
|
||||
val sharedTarget: SharedTarget = analyzedModules.sharedTarget
|
||||
val sharedTarget: SharedCommonizerTarget = analyzedModules.sharedTarget
|
||||
assertEquals(sharedTarget, results.sharedTarget)
|
||||
|
||||
val sharedModuleAsExpected: SerializedMetadata = analyzedModules.commonizedModules.getValue(sharedTarget)
|
||||
@@ -84,7 +85,7 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
|
||||
|
||||
assertModulesAreEqual(sharedModuleAsExpected, sharedModuleByCommonizer, sharedTarget)
|
||||
|
||||
val leafTargets: Set<LeafTarget> = analyzedModules.leafTargets
|
||||
val leafTargets: Set<LeafCommonizerTarget> = analyzedModules.leafTargets
|
||||
assertEquals(leafTargets, results.leafTargets)
|
||||
|
||||
for (leafTarget in leafTargets) {
|
||||
@@ -116,18 +117,18 @@ private data class SourceModuleRoot(
|
||||
}
|
||||
|
||||
private class SourceModuleRoots(
|
||||
val originalRoots: Map<LeafTarget, SourceModuleRoot>,
|
||||
val originalRoots: Map<LeafCommonizerTarget, SourceModuleRoot>,
|
||||
val commonizedRoots: Map<CommonizerTarget, SourceModuleRoot>,
|
||||
val dependencyRoots: Map<CommonizerTarget, SourceModuleRoot>
|
||||
) {
|
||||
val leafTargets: Set<LeafTarget> = originalRoots.keys
|
||||
val sharedTarget: SharedTarget
|
||||
val leafTargets: Set<LeafCommonizerTarget> = originalRoots.keys
|
||||
val sharedTarget: SharedCommonizerTarget
|
||||
|
||||
init {
|
||||
check(leafTargets.size >= 2)
|
||||
check(leafTargets.none { it.name == SHARED_TARGET_NAME })
|
||||
|
||||
val sharedTargets = commonizedRoots.keys.filterIsInstance<SharedTarget>()
|
||||
val sharedTargets = commonizedRoots.keys.filterIsInstance<SharedCommonizerTarget>()
|
||||
check(sharedTargets.size == 1)
|
||||
|
||||
sharedTarget = sharedTargets.single()
|
||||
@@ -140,10 +141,10 @@ private class SourceModuleRoots(
|
||||
|
||||
companion object {
|
||||
fun load(dataDir: File): SourceModuleRoots = try {
|
||||
val originalRoots = listRoots(dataDir, ORIGINAL_ROOTS_DIR).mapKeys { LeafTarget(it.key) }
|
||||
val originalRoots = listRoots(dataDir, ORIGINAL_ROOTS_DIR).mapKeys { LeafCommonizerTarget(it.key) }
|
||||
|
||||
val leafTargets = originalRoots.keys
|
||||
val sharedTarget = SharedTarget(leafTargets)
|
||||
val sharedTarget = SharedCommonizerTarget(leafTargets)
|
||||
|
||||
fun getTarget(targetName: String): CommonizerTarget =
|
||||
if (targetName == SHARED_TARGET_NAME) sharedTarget else leafTargets.first { it.name == targetName }
|
||||
@@ -185,41 +186,41 @@ private class AnalyzedModules(
|
||||
val commonizedModules: Map<CommonizerTarget, SerializedMetadata>,
|
||||
val dependencyModules: Map<CommonizerTarget, List<ModuleDescriptor>>
|
||||
) {
|
||||
val leafTargets: Set<LeafTarget>
|
||||
val sharedTarget: SharedTarget
|
||||
val leafTargets: Set<LeafCommonizerTarget>
|
||||
val sharedTarget: SharedCommonizerTarget
|
||||
|
||||
init {
|
||||
originalModules.keys.let { targets ->
|
||||
check(targets.isNotEmpty())
|
||||
|
||||
leafTargets = targets.filterIsInstance<LeafTarget>().toSet()
|
||||
leafTargets = targets.filterIsInstance<LeafCommonizerTarget>().toSet()
|
||||
check(targets.size == leafTargets.size)
|
||||
}
|
||||
|
||||
sharedTarget = SharedTarget(leafTargets)
|
||||
sharedTarget = SharedCommonizerTarget(leafTargets)
|
||||
val allTargets = leafTargets + sharedTarget
|
||||
|
||||
check(commonizedModules.keys == allTargets)
|
||||
check(allTargets.containsAll(dependencyModules.keys))
|
||||
}
|
||||
|
||||
fun toCommonizerParameters(resultsConsumer: ResultsConsumer) =
|
||||
CommonizerParameters().also { parameters ->
|
||||
parameters.resultsConsumer = resultsConsumer
|
||||
parameters.dependencyModulesProvider = dependencyModules[sharedTarget]?.let(MockModulesProvider::create)
|
||||
fun toCommonizerParameters(
|
||||
resultsConsumer: ResultsConsumer, manifestDataProvider: TargetedNativeManifestDataProvider = MockNativeManifestDataProvider()
|
||||
) = CommonizerParameters(resultsConsumer, manifestDataProvider).also { parameters ->
|
||||
parameters.dependencyModulesProvider = dependencyModules[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),
|
||||
dependencyModulesProvider = dependencyModules[leafTarget]?.let(MockModulesProvider::create)
|
||||
)
|
||||
parameters.addTarget(
|
||||
TargetProvider(
|
||||
target = leafTarget,
|
||||
modulesProvider = MockModulesProvider.create(originalModule),
|
||||
dependencyModulesProvider = dependencyModules[leafTarget]?.let(MockModulesProvider::create)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun create(
|
||||
@@ -242,7 +243,7 @@ private class AnalyzedModules(
|
||||
}
|
||||
|
||||
private fun createDependencyModules(
|
||||
sharedTarget: SharedTarget,
|
||||
sharedTarget: SharedCommonizerTarget,
|
||||
dependencyRoots: Map<out CommonizerTarget, SourceModuleRoot>,
|
||||
parentDisposable: Disposable
|
||||
): Pair<Map<CommonizerTarget, List<ModuleDescriptor>>, AnalyzedModuleDependencies> {
|
||||
@@ -263,7 +264,7 @@ private class AnalyzedModules(
|
||||
}
|
||||
|
||||
private fun createModules(
|
||||
sharedTarget: SharedTarget,
|
||||
sharedTarget: SharedCommonizerTarget,
|
||||
moduleRoots: Map<out CommonizerTarget, SourceModuleRoot>,
|
||||
dependencies: AnalyzedModuleDependencies,
|
||||
parentDisposable: Disposable,
|
||||
@@ -290,7 +291,7 @@ private class AnalyzedModules(
|
||||
}
|
||||
|
||||
private fun createModule(
|
||||
sharedTarget: SharedTarget,
|
||||
sharedTarget: SharedCommonizerTarget,
|
||||
currentTarget: CommonizerTarget,
|
||||
moduleRoot: SourceModuleRoot,
|
||||
dependencies: AnalyzedModuleDependencies,
|
||||
@@ -338,7 +339,7 @@ private class AnalyzedModules(
|
||||
}
|
||||
|
||||
private class DependenciesContainerImpl(
|
||||
sharedTarget: SharedTarget,
|
||||
sharedTarget: SharedCommonizerTarget,
|
||||
currentTarget: CommonizerTarget,
|
||||
dependencies: AnalyzedModuleDependencies
|
||||
) : CommonDependenciesContainer {
|
||||
|
||||
+14
-12
@@ -7,8 +7,11 @@ 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.konan.CommonNativeManifestDataProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.TargetedNativeManifestDataProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.MockResultsConsumer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.MockModulesProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.MockNativeManifestDataProvider
|
||||
import org.junit.Test
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.test.assertEquals
|
||||
@@ -62,20 +65,19 @@ class CommonizerFacadeTest {
|
||||
)
|
||||
|
||||
companion object {
|
||||
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),
|
||||
dependencyModulesProvider = null
|
||||
)
|
||||
private fun Map<String, List<String>>.toCommonizerParameters(
|
||||
resultsConsumer: ResultsConsumer, manifestDataProvider: TargetedNativeManifestDataProvider = MockNativeManifestDataProvider()
|
||||
) = CommonizerParameters(resultsConsumer, manifestDataProvider).also { parameters ->
|
||||
forEach { (targetName, moduleNames) ->
|
||||
parameters.addTarget(
|
||||
TargetProvider(
|
||||
target = LeafCommonizerTarget(targetName),
|
||||
modulesProvider = MockModulesProvider.create(moduleNames),
|
||||
dependencyModulesProvider = null
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun doTestNothingToCommonize(originalModules: Map<String, List<String>>) {
|
||||
val results = MockResultsConsumer()
|
||||
|
||||
-70
@@ -1,70 +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.descriptors.commonizer
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class CommonizerTargetTest {
|
||||
|
||||
@Test
|
||||
fun leafTargetNames() {
|
||||
listOf(
|
||||
Triple("foo", "[foo]", FOO),
|
||||
Triple("bar", "[bar]", BAR),
|
||||
Triple("baz_123", "[baz_123]", BAZ),
|
||||
).forEach { (name, prettyName, target: LeafTarget) ->
|
||||
assertEquals(name, target.name)
|
||||
assertEquals(prettyName, target.prettyName)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sharedTargetNames() {
|
||||
listOf(
|
||||
"[foo]" to SharedTarget(FOO),
|
||||
"[foo, bar]" to SharedTarget(FOO, BAR),
|
||||
"[foo, bar, baz_123]" to SharedTarget(FOO, BAR, BAZ),
|
||||
"[foo, bar, baz_123, [foo, bar]]" to SharedTarget(FOO, BAR, BAZ, SharedTarget(FOO, BAR))
|
||||
).forEach { (prettyName, target: SharedTarget) ->
|
||||
assertEquals(prettyName, target.prettyName)
|
||||
assertEquals(prettyName, target.name)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun prettyCommonizedName() {
|
||||
val sharedTarget = SharedTarget(FOO, BAR, BAZ)
|
||||
listOf(
|
||||
"[foo(*), bar, baz_123]" to FOO,
|
||||
"[foo, bar(*), baz_123]" to BAR,
|
||||
"[foo, bar, baz_123(*)]" to BAZ,
|
||||
"[foo, bar, baz_123]" to sharedTarget
|
||||
).forEach { (prettyCommonizerName, target: CommonizerTarget) ->
|
||||
assertEquals(prettyCommonizerName, target.prettyCommonizedName(sharedTarget))
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun prettyCommonizedNameFailure() {
|
||||
FOO.prettyCommonizedName(SharedTarget(BAR, BAZ))
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
fun sharedTargetNoInnerTargets() {
|
||||
SharedTarget(emptySet())
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val FOO = LeafTarget("foo")
|
||||
val BAR = LeafTarget("bar", KonanTarget.IOS_X64)
|
||||
val BAZ = LeafTarget("baz_123", KonanTarget.MACOS_X64)
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
fun SharedTarget(vararg targets: CommonizerTarget) = SharedTarget(linkedSetOf(*targets))
|
||||
}
|
||||
}
|
||||
+44
-72
@@ -6,8 +6,8 @@
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
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.descriptors.commonizer.LeafCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirRoot
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirRootFactory
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
@@ -17,114 +17,86 @@ class RootCommonizerTest : AbstractCommonizerTest<CirRoot, CirRoot>() {
|
||||
|
||||
@Test
|
||||
fun allAreNative() = doTestSuccess(
|
||||
expected = SharedTarget(
|
||||
expected = SharedCommonizerTarget(
|
||||
setOf(
|
||||
LeafTarget("ios_x64", KonanTarget.IOS_X64),
|
||||
LeafTarget("ios_arm64", KonanTarget.IOS_ARM64),
|
||||
LeafTarget("ios_arm32", KonanTarget.IOS_ARM32)
|
||||
LeafCommonizerTarget(KonanTarget.IOS_X64),
|
||||
LeafCommonizerTarget(KonanTarget.IOS_ARM64),
|
||||
LeafCommonizerTarget(KonanTarget.IOS_ARM32)
|
||||
)
|
||||
).toMock(),
|
||||
LeafTarget("ios_x64", KonanTarget.IOS_X64).toMock(),
|
||||
LeafTarget("ios_arm64", KonanTarget.IOS_ARM64).toMock(),
|
||||
LeafTarget("ios_arm32", KonanTarget.IOS_ARM32).toMock()
|
||||
LeafCommonizerTarget(KonanTarget.IOS_X64).toMock(),
|
||||
LeafCommonizerTarget(KonanTarget.IOS_ARM64).toMock(),
|
||||
LeafCommonizerTarget(KonanTarget.IOS_ARM32).toMock()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun jvmAndNative1() = doTestSuccess(
|
||||
expected = SharedTarget(
|
||||
expected = SharedCommonizerTarget(
|
||||
setOf(
|
||||
LeafTarget("jvm1"),
|
||||
LeafTarget("ios_x64", KonanTarget.IOS_X64),
|
||||
LeafTarget("jvm2")
|
||||
LeafCommonizerTarget("jvm1"),
|
||||
LeafCommonizerTarget(KonanTarget.IOS_X64),
|
||||
LeafCommonizerTarget("jvm2")
|
||||
)
|
||||
).toMock(),
|
||||
LeafTarget("jvm1").toMock(),
|
||||
LeafTarget("ios_x64", KonanTarget.IOS_X64).toMock(),
|
||||
LeafTarget("jvm2").toMock()
|
||||
LeafCommonizerTarget("jvm1").toMock(),
|
||||
LeafCommonizerTarget(KonanTarget.IOS_X64).toMock(),
|
||||
LeafCommonizerTarget("jvm2").toMock()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun jvmAndNative2() = doTestSuccess(
|
||||
expected = SharedTarget(
|
||||
expected = SharedCommonizerTarget(
|
||||
setOf(
|
||||
LeafTarget("ios_x64", KonanTarget.IOS_X64),
|
||||
LeafTarget("jvm"),
|
||||
LeafTarget("ios_arm64", KonanTarget.IOS_ARM64)
|
||||
LeafCommonizerTarget(KonanTarget.IOS_X64),
|
||||
LeafCommonizerTarget("jvm"),
|
||||
LeafCommonizerTarget(KonanTarget.IOS_ARM64)
|
||||
)
|
||||
).toMock(),
|
||||
LeafTarget("ios_x64", KonanTarget.IOS_X64).toMock(),
|
||||
LeafTarget("jvm").toMock(),
|
||||
LeafTarget("ios_arm64", KonanTarget.IOS_ARM64).toMock()
|
||||
LeafCommonizerTarget(KonanTarget.IOS_X64).toMock(),
|
||||
LeafCommonizerTarget("jvm").toMock(),
|
||||
LeafCommonizerTarget(KonanTarget.IOS_ARM64).toMock()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun noNative1() = doTestSuccess(
|
||||
expected = SharedTarget(
|
||||
expected = SharedCommonizerTarget(
|
||||
setOf(
|
||||
LeafTarget("default1"),
|
||||
LeafTarget("default2"),
|
||||
LeafTarget("default3")
|
||||
LeafCommonizerTarget("default1"),
|
||||
LeafCommonizerTarget("default2"),
|
||||
LeafCommonizerTarget("default3")
|
||||
)
|
||||
).toMock(),
|
||||
LeafTarget("default1").toMock(),
|
||||
LeafTarget("default2").toMock(),
|
||||
LeafTarget("default3").toMock()
|
||||
LeafCommonizerTarget("default1").toMock(),
|
||||
LeafCommonizerTarget("default2").toMock(),
|
||||
LeafCommonizerTarget("default3").toMock()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun noNative2() = doTestSuccess(
|
||||
expected = SharedTarget(
|
||||
expected = SharedCommonizerTarget(
|
||||
setOf(
|
||||
LeafTarget("jvm1"),
|
||||
LeafTarget("default"),
|
||||
LeafTarget("jvm2")
|
||||
LeafCommonizerTarget("jvm1"),
|
||||
LeafCommonizerTarget("default"),
|
||||
LeafCommonizerTarget("jvm2")
|
||||
)
|
||||
).toMock(),
|
||||
LeafTarget("jvm1").toMock(),
|
||||
LeafTarget("default").toMock(),
|
||||
LeafTarget("jvm2").toMock()
|
||||
LeafCommonizerTarget("jvm1").toMock(),
|
||||
LeafCommonizerTarget("default").toMock(),
|
||||
LeafCommonizerTarget("jvm2").toMock()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun noNative3() = doTestSuccess(
|
||||
expected = SharedTarget(
|
||||
expected = SharedCommonizerTarget(
|
||||
setOf(
|
||||
LeafTarget("jvm1"),
|
||||
LeafTarget("jvm2"),
|
||||
LeafTarget("jvm3")
|
||||
LeafCommonizerTarget("jvm1"),
|
||||
LeafCommonizerTarget("jvm2"),
|
||||
LeafCommonizerTarget("jvm3")
|
||||
)
|
||||
).toMock(),
|
||||
LeafTarget("jvm1").toMock(),
|
||||
LeafTarget("jvm2").toMock(),
|
||||
LeafTarget("jvm3").toMock()
|
||||
)
|
||||
|
||||
@Test(expected = ObjectsNotEqual::class)
|
||||
fun misconfiguration1() = doTestSuccess(
|
||||
expected = SharedTarget(
|
||||
setOf(
|
||||
LeafTarget("ios_x64", KonanTarget.IOS_X64),
|
||||
LeafTarget("ios_arm64", KonanTarget.IOS_ARM64),
|
||||
LeafTarget("ios_arm32", KonanTarget.IOS_ARM32)
|
||||
)
|
||||
).toMock(),
|
||||
LeafTarget("ios_x64").toMock(), // KonanTarget is missing here!
|
||||
LeafTarget("ios_arm64", KonanTarget.IOS_ARM64).toMock(),
|
||||
LeafTarget("ios_arm32", KonanTarget.IOS_ARM32).toMock()
|
||||
)
|
||||
|
||||
@Test(expected = ObjectsNotEqual::class)
|
||||
fun misconfiguration2() = doTestSuccess(
|
||||
expected = SharedTarget(
|
||||
setOf(
|
||||
LeafTarget("jvm1"),
|
||||
LeafTarget("jvm2"),
|
||||
LeafTarget("jvm3")
|
||||
)
|
||||
).toMock(),
|
||||
LeafTarget("jvm1", KonanTarget.IOS_X64).toMock(), // mistakenly specified KonanTarget!
|
||||
LeafTarget("jvm2").toMock(),
|
||||
LeafTarget("jvm3").toMock()
|
||||
LeafCommonizerTarget("jvm1").toMock(),
|
||||
LeafCommonizerTarget("jvm2").toMock(),
|
||||
LeafCommonizerTarget("jvm3").toMock()
|
||||
)
|
||||
|
||||
override fun createCommonizer() = RootCommonizer()
|
||||
|
||||
+3
-3
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.SharedCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory
|
||||
@@ -537,7 +537,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
|
||||
fun areEqual(classifiers: CirKnownClassifiers, a: CirType, b: CirType): Boolean =
|
||||
TypeCommonizer(classifiers).run { commonizeWith(a) && commonizeWith(b) }
|
||||
|
||||
private val FAKE_SHARED_TARGET = SharedTarget(setOf(LeafTarget("a"), LeafTarget("b")))
|
||||
private val FAKE_SHARED_TARGET = SharedCommonizerTarget(setOf(LeafCommonizerTarget("a"), LeafCommonizerTarget("b")))
|
||||
|
||||
private fun CirKnownClassifiers.classNode(classId: CirEntityId, computation: () -> CirClassNode) =
|
||||
commonized.classNode(classId) ?: computation()
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.utils
|
||||
|
||||
import kotlinx.metadata.klib.KlibModuleMetadata
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.identityString
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.utils.MetadataDeclarationsComparator
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.utils.MetadataDeclarationsComparator.Mismatch
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.utils.MetadataDeclarationsComparator.Result
|
||||
@@ -38,7 +39,7 @@ fun assertModulesAreEqual(reference: SerializedMetadata, generated: SerializedMe
|
||||
val digitCount = mismatches.size.toString().length
|
||||
|
||||
val failureMessage = buildString {
|
||||
appendLine("${mismatches.size} mismatches found while comparing reference module ${referenceModule.name} (A) and generated module ${generatedModule.name} (B) for target ${target.prettyName}:")
|
||||
appendLine("${mismatches.size} mismatches found while comparing reference module ${referenceModule.name} (A) and generated module ${generatedModule.name} (B) for target ${target.identityString}:")
|
||||
mismatches.forEachIndexed { index, mismatch ->
|
||||
appendLine((index + 1).toString().padStart(digitCount, ' ') + ". " + mismatch)
|
||||
}
|
||||
|
||||
@@ -16,9 +16,12 @@ import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.ModuleInfo
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeSensitiveManifestData
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.TargetedNativeManifestDataProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.AbstractTypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.library.KotlinLibraryVersioning
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.parentOrNull
|
||||
@@ -204,8 +207,8 @@ internal class MockResultsConsumer : ResultsConsumer {
|
||||
val modulesByTargets: Map<CommonizerTarget, Collection<ModuleResult>>
|
||||
get() = _modulesByTargets.mapValues { it.value.values }
|
||||
|
||||
val sharedTarget: SharedTarget by lazy { modulesByTargets.keys.filterIsInstance<SharedTarget>().single() }
|
||||
val leafTargets: Set<LeafTarget> by lazy { modulesByTargets.keys.filterIsInstance<LeafTarget>().toSet() }
|
||||
val sharedTarget: SharedCommonizerTarget by lazy { modulesByTargets.keys.filterIsInstance<SharedCommonizerTarget>().single() }
|
||||
val leafTargets: Set<LeafCommonizerTarget> by lazy { modulesByTargets.keys.filterIsInstance<LeafCommonizerTarget>().toSet() }
|
||||
|
||||
private val finishedTargets = mutableSetOf<CommonizerTarget>()
|
||||
|
||||
@@ -232,3 +235,25 @@ internal class MockResultsConsumer : ResultsConsumer {
|
||||
this.status = status
|
||||
}
|
||||
}
|
||||
|
||||
fun MockNativeManifestDataProvider(
|
||||
uniqueName: String = "mock",
|
||||
versions: KotlinLibraryVersioning = KotlinLibraryVersioning(null, null, null, null, null),
|
||||
dependencies: List<String> = emptyList(),
|
||||
isInterop: Boolean = true,
|
||||
packageFqName: String? = "mock",
|
||||
exportForwardDeclarations: List<String> = emptyList(),
|
||||
nativeTargets: Collection<String> = emptyList(),
|
||||
shortName: String? = "mock"
|
||||
): TargetedNativeManifestDataProvider = TargetedNativeManifestDataProvider { target, libraryName ->
|
||||
NativeSensitiveManifestData(
|
||||
uniqueName = uniqueName,
|
||||
versions = versions,
|
||||
dependencies = dependencies,
|
||||
isInterop = isInterop,
|
||||
packageFqName = packageFqName,
|
||||
exportForwardDeclarations = exportForwardDeclarations,
|
||||
nativeTargets = nativeTargets,
|
||||
shortName = shortName
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user