[Commonizer] Move source code to the folder that corresponds package name

This commit is contained in:
Dmitriy Dolovov
2021-03-17 11:36:04 +03:00
parent fc4f66b702
commit 5a35018a88
163 changed files with 0 additions and 0 deletions
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer
import java.io.File
import java.net.URLClassLoader
public fun CliCommonizer(classpath: Iterable<File>): CliCommonizer {
return CliCommonizer(URLClassLoader(classpath.map { it.absoluteFile.toURI().toURL() }.toTypedArray()))
}
public fun CliCommonizer(classLoader: ClassLoader): CliCommonizer {
return CliCommonizer(CommonizerClassLoaderExecutor(classLoader))
}
public class CliCommonizer(private val executor: Executor) : Commonizer {
public fun interface Executor {
public operator fun invoke(arguments: List<String>)
}
override fun commonizeLibraries(
konanHome: File,
inputLibraries: Set<File>,
dependencyLibraries: Set<File>,
outputCommonizerTarget: SharedCommonizerTarget,
outputDirectory: File
) {
if (inputLibraries.isEmpty()) return
val arguments = mutableListOf<String>().apply {
add("native-klib-commonize")
add("-distribution-path"); add(konanHome.absolutePath)
add("-input-libraries"); add(inputLibraries.joinToString(";") { it.absolutePath })
add("-output-commonizer-target"); add(outputCommonizerTarget.identityString)
add("-output-path"); add(outputDirectory.absolutePath)
if (dependencyLibraries.isNotEmpty()) {
add("-dependency-libraries"); add(dependencyLibraries.joinToString(";") { it.absolutePath })
}
}
executor(arguments)
}
}
private class CommonizerClassLoaderExecutor(private val commonizerClassLoader: ClassLoader) : CliCommonizer.Executor {
companion object {
private const val commonizerMainClass = "org.jetbrains.kotlin.commonizer.cli.CommonizerCLI"
private const val commonizerMainFunction = "main"
}
@Throws(Throwable::class)
override fun invoke(arguments: List<String>) {
val commonizerMainClass = commonizerClassLoader.loadClass(commonizerMainClass)
val commonizerMainMethod = commonizerMainClass.methods.singleOrNull { it.name == commonizerMainFunction }
?: throw IllegalArgumentException(
"Missing or conflicting $commonizerMainFunction function in " +
"Class ${commonizerMainClass.name} from ClassLoader $commonizerClassLoader"
)
commonizerMainMethod.invoke(null, arguments.toTypedArray())
}
}
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer
import java.io.File
import java.io.Serializable
import kotlin.jvm.Throws
public interface Commonizer : Serializable {
@Throws(Throwable::class)
public fun commonizeLibraries(
konanHome: File,
inputLibraries: Set<File>,
dependencyLibraries: Set<File>,
outputCommonizerTarget: SharedCommonizerTarget,
outputDirectory: File
)
}
@@ -0,0 +1,106 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.commonizer
import org.jetbrains.kotlin.konan.target.KonanTarget
import java.io.Serializable
// 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.
public sealed class CommonizerTarget : Serializable {
final override fun toString(): String = prettyName
}
public data class LeafCommonizerTarget public constructor(val name: String) : CommonizerTarget() {
public constructor(konanTarget: KonanTarget) : this(konanTarget.name)
public val konanTargetOrNull: KonanTarget? = KonanTarget.predefinedTargets[name]
public val konanTarget: KonanTarget get() = konanTargetOrNull ?: error("Unknown KonanTarget: $name")
}
public data class SharedCommonizerTarget(val targets: Set<CommonizerTarget>) : CommonizerTarget() {
public constructor(vararg targets: CommonizerTarget) : this(targets.toSet())
public constructor(vararg targets: KonanTarget) : this(targets.toSet())
public constructor(targets: Iterable<KonanTarget>) : this(targets.map(::LeafCommonizerTarget).toSet())
public companion object {
public fun ifNotEmpty(targets: Set<CommonizerTarget>): SharedCommonizerTarget? {
return if (targets.isNotEmpty()) SharedCommonizerTarget(targets) else null
}
}
init {
require(targets.isNotEmpty()) { "Empty 'SharedCommonizerTarget': Expected at least one target" }
}
}
public fun CommonizerTarget(konanTargets: Iterable<KonanTarget>): CommonizerTarget {
val konanTargetsSet = konanTargets.toSet()
require(konanTargetsSet.isNotEmpty()) { "Empty set of of konanTargets" }
val leafTargets = konanTargetsSet.map(::LeafCommonizerTarget)
return leafTargets.singleOrNull() ?: SharedCommonizerTarget(leafTargets.toSet())
}
public fun CommonizerTarget(konanTarget: KonanTarget): LeafCommonizerTarget {
return LeafCommonizerTarget(konanTarget)
}
public fun CommonizerTarget(konanTarget: KonanTarget, vararg konanTargets: KonanTarget): SharedCommonizerTarget {
val targets = ArrayList<KonanTarget>(konanTargets.size + 1).apply {
add(konanTarget)
addAll(konanTargets)
}
return SharedCommonizerTarget(targets.map(::LeafCommonizerTarget).toSet())
}
public val CommonizerTarget.identityString: String
get() = when (this) {
is LeafCommonizerTarget -> name
is SharedCommonizerTarget -> identityString
}
private val SharedCommonizerTarget.identityString: String
get() {
val segments = targets.map(CommonizerTarget::identityString).sorted()
return segments.joinToString(
separator = ", ", prefix = "(", postfix = ")"
)
}
public val CommonizerTarget.prettyName: String
get() = when (this) {
is LeafCommonizerTarget -> "[$name]"
is SharedCommonizerTarget -> prettyName(null)
}
public fun SharedCommonizerTarget.prettyName(highlightedChild: CommonizerTarget?): String {
return targets
.sortedWith(compareBy<CommonizerTarget> { it.level }.thenBy { it.identityString }).joinToString(", ", "[", "]") { child ->
when (child) {
is LeafCommonizerTarget -> child.name
is SharedCommonizerTarget -> child.prettyName(highlightedChild)
} + if (child == highlightedChild) "(*)" else ""
}
}
public val CommonizerTarget.konanTargets: Set<KonanTarget>
get() {
return when (this) {
is LeafCommonizerTarget -> setOf(konanTarget)
is SharedCommonizerTarget -> targets.flatMap { it.konanTargets }.toSet()
}
}
public val CommonizerTarget.level: Int
get() {
return when (this) {
is LeafCommonizerTarget -> return 0
is SharedCommonizerTarget -> targets.maxOf { it.level } + 1
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_COMMON_LIBS_DIR
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR
import java.io.File
public fun interface CommonizerOutputLayout {
public fun getTargetDirectory(root: File, target: CommonizerTarget): File
}
public object NativeDistributionCommonizerOutputLayout : CommonizerOutputLayout {
override fun getTargetDirectory(root: File, target: CommonizerTarget): File {
return when (target) {
is LeafCommonizerTarget -> root.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR).resolve(target.name)
is SharedCommonizerTarget -> root.resolve(KONAN_DISTRIBUTION_COMMON_LIBS_DIR)
}
}
}
public object HierarchicalCommonizerOutputLayout : CommonizerOutputLayout {
override fun getTargetDirectory(root: File, target: CommonizerTarget): File {
return root.resolve(target.identityString)
}
}
@@ -0,0 +1,196 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer
import org.jetbrains.kotlin.commonizer.IdentityStringSyntaxNode.LeafTargetSyntaxNode
import org.jetbrains.kotlin.commonizer.IdentityStringSyntaxNode.SharedTargetSyntaxNode
import org.jetbrains.kotlin.commonizer.IdentityStringToken.*
public fun parseCommonizerTarget(identityString: String): CommonizerTarget {
try {
val tokens = tokenizeIdentityString(identityString)
val syntaxTree = parser(tokens) ?: error("Failed building syntax tree. $identityString")
check(syntaxTree.remaining.isEmpty()) { "Failed building syntax tree. Unexpected remaining tokens ${syntaxTree.remaining}" }
return buildCommonizerTarget(syntaxTree.value)
} catch (e: Throwable) {
throw IllegalArgumentException("Failed parsing CommonizerTarget from \"$identityString\"", e)
}
}
//region Tokens
private fun tokenizeIdentityString(identityString: String): List<IdentityStringToken> {
var remainingString = identityString
val tokenizer = sharedTargetStartTokenizer + sharedTargetEndTokenizer + separatorTokenizer + wordTokenizer
return mutableListOf<IdentityStringToken>().apply {
while (remainingString.isNotEmpty()) {
val generatedToken = tokenizer.nextToken(remainingString)
?: error("Unexpected token at $remainingString")
remainingString = generatedToken.remaining
add(generatedToken.token)
}
}.toList()
}
private sealed class IdentityStringToken {
data class Word(val value: String) : IdentityStringToken()
object Separator : IdentityStringToken()
object SharedTargetStart : IdentityStringToken()
object SharedTargetEnd : IdentityStringToken()
final override fun toString(): String {
return when (this) {
is Word -> value
is Separator -> ", "
is SharedTargetStart -> "["
is SharedTargetEnd -> "]"
}
}
}
private data class GeneratedToken(val token: IdentityStringToken, val remaining: String)
private interface IdentityStringTokenizer {
fun nextToken(value: String): GeneratedToken?
}
private operator fun IdentityStringTokenizer.plus(other: IdentityStringTokenizer): IdentityStringTokenizer {
return CompositeIdentityStringTokenizer(this, other)
}
private data class CompositeIdentityStringTokenizer(
val first: IdentityStringTokenizer,
val second: IdentityStringTokenizer
) : IdentityStringTokenizer {
override fun nextToken(value: String): GeneratedToken? {
return first.nextToken(value) ?: second.nextToken(value)
}
}
private data class RegexIdentityStringTokenizer(
val regex: Regex,
val token: (String) -> IdentityStringToken
) : IdentityStringTokenizer {
override fun nextToken(value: String): GeneratedToken? {
val firstMatchResult = regex.findAll(value, 0).firstOrNull() ?: return null
val range = firstMatchResult.range
if (range.first != 0) return null
return GeneratedToken(token(firstMatchResult.value), value.drop(firstMatchResult.value.length))
}
}
private val sharedTargetStartTokenizer =
RegexIdentityStringTokenizer(Regex.fromLiteral("(")) { SharedTargetStart }
private val sharedTargetEndTokenizer =
RegexIdentityStringTokenizer(Regex.fromLiteral(")")) { SharedTargetEnd }
private val separatorTokenizer =
RegexIdentityStringTokenizer(Regex("""\s*,\s*""")) { Separator }
private val wordTokenizer =
RegexIdentityStringTokenizer(Regex("\\w+"), IdentityStringToken::Word)
//endregion
//region Syntax Tree
private val parser = anyOf(SharedTargetParser, LeafTargetParser)
private data class ParserOutput<out T : Any>(val value: T, val remaining: List<IdentityStringToken>)
private interface Parser<out T : Any> {
operator fun invoke(tokens: List<IdentityStringToken>): ParserOutput<T>?
}
private fun <T : Any> anyOf(vararg parser: Parser<T>): Parser<T> {
return AnyOfParser(parser.toList())
}
private data class AnyOfParser<T : Any>(val parsers: List<Parser<T>>) : Parser<T> {
override fun invoke(tokens: List<IdentityStringToken>): ParserOutput<T>? {
return parsers.mapNotNull { parser -> parser(tokens) }.firstOrNull()
}
}
private fun <T : Any> Parser<T>.oneOrMore(): Parser<List<T>> {
return OneOrMoreParser(this)
}
private data class OneOrMoreParser<T : Any>(val parser: Parser<T>) : Parser<List<T>> {
override fun invoke(tokens: List<IdentityStringToken>): ParserOutput<List<T>>? {
val outputs = mutableListOf<T>()
var remainingTokens = tokens
while (true) {
val output = parser(remainingTokens) ?: break
if (output.remaining == remainingTokens) break
outputs.add(output.value)
remainingTokens = output.remaining
}
if (outputs.isEmpty()) {
return null
}
return ParserOutput(outputs.toList(), remainingTokens)
}
}
private fun <T : Any> Parser<T>.ignore(token: IdentityStringToken): Parser<T> {
return IgnoreTokensParser(this, token)
}
private data class IgnoreTokensParser<T : Any>(val parser: Parser<T>, val ignoredToken: IdentityStringToken) : Parser<T> {
override fun invoke(tokens: List<IdentityStringToken>): ParserOutput<T>? {
return parser(
if (tokens.firstOrNull() == ignoredToken) tokens.drop(1) else tokens
)
}
}
private object LeafTargetParser : Parser<LeafTargetSyntaxNode> {
override fun invoke(tokens: List<IdentityStringToken>): ParserOutput<LeafTargetSyntaxNode>? {
val nextToken = tokens.firstOrNull() as? Word ?: return null
return ParserOutput(LeafTargetSyntaxNode(nextToken), tokens.drop(1))
}
}
private object SharedTargetParser : Parser<SharedTargetSyntaxNode> {
override fun invoke(tokens: List<IdentityStringToken>): ParserOutput<SharedTargetSyntaxNode>? {
if (tokens.firstOrNull() !is SharedTargetStart) return null
val innerParser = anyOf(LeafTargetParser, SharedTargetParser).ignore(Separator).oneOrMore()
val innerParserOutput = innerParser(tokens.drop(1)) ?: return null
val closingToken = innerParserOutput.remaining.firstOrNull()
if (closingToken != SharedTargetEnd) {
error("Missing ']' at ${tokens.joinToString("")}")
}
return ParserOutput(SharedTargetSyntaxNode(innerParserOutput.value), innerParserOutput.remaining.drop(1))
}
}
private sealed class IdentityStringSyntaxNode {
data class LeafTargetSyntaxNode(val token: Word) : IdentityStringSyntaxNode()
data class SharedTargetSyntaxNode(val children: List<IdentityStringSyntaxNode>) : IdentityStringSyntaxNode()
}
//endregion Tree
//region Build CommonizerTarget
private fun buildCommonizerTarget(node: IdentityStringSyntaxNode): CommonizerTarget {
return when (node) {
is LeafTargetSyntaxNode -> LeafCommonizerTarget(node.token.value)
is SharedTargetSyntaxNode -> SharedCommonizerTarget(
node.children.map { child -> buildCommonizerTarget(child) }.toSet()
)
}
}
//endregion