[KLIB tool] Move all CLI-related logic to the Command class

^KT-62340
This commit is contained in:
Dmitriy Dolovov
2024-02-16 14:47:55 +01:00
committed by Space Team
parent d4585ff3ce
commit 921a787815
@@ -39,96 +39,113 @@ import java.io.File
import kotlin.system.exitProcess
import org.jetbrains.kotlin.konan.file.File as KFile
private fun printUsage() {
println(
"""
Usage: klib <command> <library> [<option>]
where the commands are:
info General information about the library
install [DEPRECATED] Local KLIB repositories to be dropped soon. See https://youtrack.jetbrains.com/issue/KT-61098
Install the library to the local repository.
remove [DEPRECATED] Local KLIB repositories to be dropped soon. See https://youtrack.jetbrains.com/issue/KT-61098
Remove the library from the local repository.
dump-abi Dump the ABI snapshot of the library. Each line in the snapshot corresponds exactly to one
declaration. Whenever an ABI-incompatible change happens to a declaration, this should
be visible in the corresponding line of the snapshot.
dump-ir Dump the intermediate representation (IR) of all declarations in the library. The output of this
command is intended to be used for debugging purposes only.
dump-ir-signatures Dump IR signatures of all non-private declarations in the library and all non-private declarations
consumed by this library (as two separate lists). This command relies purely on the data in IR.
dump-metadata-signatures Dump IR signatures of all non-private declarations in the library. Note, that this command renders
the signatures based on the library metadata. This is different from "dump-ir-signatures",
which renders signatures based on the IR. On practice, in most cases there is no difference
between output of these two commands. However, if IR transforming compiler plugins
(such as Compose) were used during compilation of the library, there would be different
signatures for patched declarations.
signatures [DEPRECATED] Renamed to "dump-metadata-signatures". Please, use new command name.
dump-metadata Dump the metadata of all declarations in the library. The output of this command is intended
to be used for debugging purposes only.
contents [DEPRECATED] Reworked and renamed to "dump-metadata". Please, use new command name.
and the options are:
-repository <path> [DEPRECATED] Local KLIB repositories to be dropped soon. See https://youtrack.jetbrains.com/issue/KT-61098
Work with the specified repository.
-signature-version {${KotlinIrSignatureVersion.CURRENTLY_SUPPORTED_VERSIONS.joinToString("|") { it.number.toString() }}}
Render IR signatures of a specific version. By default, the most up-to-date signature version
that is supported in the library is used.
-print-signatures {true|false}
Print IR signature for every declaration. Applicable only to "dump-metadata" and "dump-ir" commands.
""".trimIndent()
)
}
private fun parseOptions(args: Array<String>): Map<String, List<String>> {
val options = mutableMapOf<String, MutableList<String>>()
for (index in args.indices step 2) {
val key = args[index]
if (key[0] != '-') {
logError("Expected a flag with initial dash: $key")
}
if (index + 1 == args.size) {
logError("Expected an value after $key")
}
val value = listOf(args[index + 1])
options[key]?.addAll(value) ?: options.put(key, value.toMutableList())
}
return options
}
internal class Command(args: Array<String>) {
val commandName: String
val libraryNameOrPath: String
val repository: String?
val printSignatures: Boolean
val signatureVersion: KotlinIrSignatureVersion?
init {
if (args.size < 2) {
printUsage()
exitProcess(0)
}
commandName = args[0]
libraryNameOrPath = args[1]
val extraOptions: Map<ExtraOption, List<String>> = parseOptions(args.drop(2).toTypedArray<String>())
.entries
.mapNotNull { (option, values) ->
val knownOption = ExtraOption.parseOrNull(option)
if (knownOption == null) {
logWarning("Unrecognized command-line option: $option")
return@mapNotNull null
}
knownOption to values
}.toMap()
repository = extraOptions[ExtraOption.REPOSITORY]?.last()
printSignatures = extraOptions[ExtraOption.PRINT_SIGNATURES]?.last()?.toBoolean() == true
signatureVersion = extraOptions[ExtraOption.SIGNATURE_VERSION]?.last()?.let { rawSignatureVersion ->
rawSignatureVersion.toIntOrNull()?.let(::KotlinIrSignatureVersion)
?: logError("Invalid signature version: $rawSignatureVersion")
}
if (signatureVersion != null && signatureVersion !in KotlinIrSignatureVersion.CURRENTLY_SUPPORTED_VERSIONS)
logError("Unsupported signature version: ${signatureVersion.number}")
}
val verb = args[0]
val library = args[1]
private fun parseOptions(args: Array<String>): Map<String, List<String>> {
val options = mutableMapOf<String, MutableList<String>>()
for (index in args.indices step 2) {
val key = args[index]
if (key[0] != '-') {
logError("Expected a flag with initial dash: $key")
}
if (index + 1 == args.size) {
logError("Expected an value after $key")
}
val value = listOf(args[index + 1])
options[key]?.addAll(value) ?: options.put(key, value.toMutableList())
}
return options
}
val knownOptions: Map<KnownOption, List<String>> = parseOptions(args.drop(2).toTypedArray<String>())
.entries
.mapNotNull { (option, values) ->
val knownOption = KnownOption.parseOrNull(option)
if (knownOption == null) {
logWarning("Unrecognized command-line option: $option")
return@mapNotNull null
}
knownOption to values
}.toMap()
private fun printUsage() {
println(
"""
Usage: klib <command> <library> [<option>]
where the commands are:
info General information about the library
install [DEPRECATED] Local KLIB repositories to be dropped soon. See https://youtrack.jetbrains.com/issue/KT-61098
Install the library to the local repository.
remove [DEPRECATED] Local KLIB repositories to be dropped soon. See https://youtrack.jetbrains.com/issue/KT-61098
Remove the library from the local repository.
dump-abi Dump the ABI snapshot of the library. Each line in the snapshot corresponds exactly to one
declaration. Whenever an ABI-incompatible change happens to a declaration, this should
be visible in the corresponding line of the snapshot.
dump-ir Dump the intermediate representation (IR) of all declarations in the library. The output of this
command is intended to be used for debugging purposes only.
dump-ir-signatures Dump IR signatures of all non-private declarations in the library and all non-private declarations
consumed by this library (as two separate lists). This command relies purely on the data in IR.
dump-metadata-signatures Dump IR signatures of all non-private declarations in the library. Note, that this command renders
the signatures based on the library metadata. This is different from "dump-ir-signatures",
which renders signatures based on the IR. On practice, in most cases there is no difference
between output of these two commands. However, if IR transforming compiler plugins
(such as Compose) were used during compilation of the library, there would be different
signatures for patched declarations.
signatures [DEPRECATED] Renamed to "dump-metadata-signatures". Please, use new command name.
dump-metadata Dump the metadata of all declarations in the library. The output of this command is intended
to be used for debugging purposes only.
contents [DEPRECATED] Reworked and renamed to "dump-metadata". Please, use new command name.
and the options are:
-repository <path> [DEPRECATED] Local KLIB repositories to be dropped soon. See https://youtrack.jetbrains.com/issue/KT-61098
Work with the specified repository.
-signature-version {${KotlinIrSignatureVersion.CURRENTLY_SUPPORTED_VERSIONS.joinToString("|") { it.number.toString() }}}
Render IR signatures of a specific version. By default, the most up-to-date signature version
that is supported in the library is used.
-print-signatures {true|false}
Print IR signature for every declaration. Applicable only to "dump-metadata" and "dump-ir" commands.
""".trimIndent()
)
}
}
private fun Command.parseSignatureVersion(): KotlinIrSignatureVersion? {
val rawSignatureVersion = knownOptions[KnownOption.SIGNATURE_VERSION]?.last() ?: return null
val signatureVersion = rawSignatureVersion.toIntOrNull()?.let(::KotlinIrSignatureVersion)
?: logError("Invalid signature version: $rawSignatureVersion")
private enum class ExtraOption(val option: String) {
REPOSITORY("-repository"),
PRINT_SIGNATURES("-print-signatures"),
SIGNATURE_VERSION("-signature-version");
if (signatureVersion !in KotlinIrSignatureVersion.CURRENTLY_SUPPORTED_VERSIONS)
logError("Unsupported signature version: ${signatureVersion.number}")
return signatureVersion
companion object {
fun parseOrNull(option: String): ExtraOption? = entries.firstOrNull { it.option == option }
}
}
internal object KlibToolLogger : Logger, IrMessageLogger {
@@ -427,37 +444,21 @@ private fun libraryInCurrentDir(name: String) = resolverByName(emptyList(), logg
private fun libraryInRepoOrCurrentDir(repository: KFile, name: String) =
resolverByName(listOf(repository.absolutePath), logger = KlibToolLogger).resolve(name)
private enum class KnownOption(val option: String) {
REPOSITORY("-repository"),
PRINT_SIGNATURES("-print-signatures"),
SIGNATURE_VERSION("-signature-version");
companion object {
fun parseOrNull(option: String): KnownOption? = entries.firstOrNull { it.option == option }
}
}
fun main(args: Array<String>) {
val command = Command(args)
val library = Library(command.libraryNameOrPath, command.repository)
val repository = command.knownOptions[KnownOption.REPOSITORY]?.last()
val printSignatures = command.knownOptions[KnownOption.PRINT_SIGNATURES]?.last()?.toBoolean() == true
val signatureVersion = command.parseSignatureVersion()
val library = Library(command.library, repository)
when (command.verb) {
"dump-abi" -> library.dumpAbi(System.out, signatureVersion)
"dump-ir" -> library.dumpIr(System.out, printSignatures, signatureVersion)
"dump-ir-signatures" -> library.dumpIrSignatures(System.out, signatureVersion)
"dump-metadata" -> library.dumpMetadata(System.out, printSignatures, signatureVersion, testMode = false)
"dump-metadata-signatures" -> library.dumpMetadataSignatures(System.out, signatureVersion)
"contents" -> library.contents(System.out, printSignatures, signatureVersion)
"signatures" -> library.signatures(System.out, signatureVersion)
when (command.commandName) {
"dump-abi" -> library.dumpAbi(System.out, command.signatureVersion)
"dump-ir" -> library.dumpIr(System.out, command.printSignatures, command.signatureVersion)
"dump-ir-signatures" -> library.dumpIrSignatures(System.out, command.signatureVersion)
"dump-metadata" -> library.dumpMetadata(System.out, command.printSignatures, command.signatureVersion, testMode = false)
"dump-metadata-signatures" -> library.dumpMetadataSignatures(System.out, command.signatureVersion)
"contents" -> library.contents(System.out, command.printSignatures, command.signatureVersion)
"signatures" -> library.signatures(System.out, command.signatureVersion)
"info" -> library.info()
"install" -> library.install()
"remove" -> library.remove()
else -> logError("Unknown command: ${command.verb}")
else -> logError("Unknown command: ${command.commandName}")
}
}