Rework usage of Choice options

This commit is contained in:
Elena Lepilkina
2020-11-25 11:27:03 +03:00
committed by Stanislav Erokhin
parent cb642bca69
commit f88d38314e
5 changed files with 35 additions and 36 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.native.interop.tool
import kotlinx.cli.ArgParser import kotlinx.cli.ArgParser
import kotlinx.cli.ArgType import kotlinx.cli.ArgType
import kotlinx.cli.* import kotlinx.cli.*
import org.jetbrains.kotlin.native.interop.gen.jvm.GenerationMode
const val HEADER_FILTER_ADDITIONAL_SEARCH_PREFIX = "headerFilterAdditionalSearchPrefix" const val HEADER_FILTER_ADDITIONAL_SEARCH_PREFIX = "headerFilterAdditionalSearchPrefix"
const val NODEFAULTLIBS_DEPRECATED = "nodefaultlibs" const val NODEFAULTLIBS_DEPRECATED = "nodefaultlibs"
@@ -46,7 +47,7 @@ open class CommonInteropArguments(val argParser: ArgParser) {
.multiple() .multiple()
val repo by argParser.option(ArgType.String, shortName = "r", description = "repository to resolve dependencies") val repo by argParser.option(ArgType.String, shortName = "r", description = "repository to resolve dependencies")
.multiple() .multiple()
val mode by argParser.option(ArgType.Choice(listOf(MODE_METADATA, MODE_SOURCECODE)), description = "the way interop library is generated") val mode by argParser.option(ArgType.Choice<GenerationMode>(), description = "the way interop library is generated")
.default(DEFAULT_MODE) .default(DEFAULT_MODE)
val nodefaultlibs by argParser.option(ArgType.Boolean, NODEFAULTLIBS, val nodefaultlibs by argParser.option(ArgType.Boolean, NODEFAULTLIBS,
description = "don't link the libraries from dist/klib automatically").default(false) description = "don't link the libraries from dist/klib automatically").default(false)
@@ -65,10 +66,7 @@ open class CommonInteropArguments(val argParser: ArgParser) {
description = "additional kotlinc compiler option").multiple() description = "additional kotlinc compiler option").multiple()
companion object { companion object {
const val MODE_SOURCECODE = "sourcecode" val DEFAULT_MODE = GenerationMode.METADATA
const val MODE_METADATA = "metadata"
const val DEFAULT_MODE = MODE_METADATA
} }
} }
@@ -127,8 +125,13 @@ open class CInteropArguments(argParser: ArgParser =
class JSInteropArguments(argParser: ArgParser = ArgParser("jsinterop", class JSInteropArguments(argParser: ArgParser = ArgParser("jsinterop",
prefixStyle = ArgParser.OptionPrefixStyle.JVM)): CommonInteropArguments(argParser) { prefixStyle = ArgParser.OptionPrefixStyle.JVM)): CommonInteropArguments(argParser) {
val target by argParser.option(ArgType.Choice(listOf("wasm32")), enum class TargetType {
description = "wasm target to compile to").default("wasm32") WASM32;
override fun toString() = name.toLowerCase()
}
val target by argParser.option(ArgType.Choice<TargetType>(),
description = "wasm target to compile to").default(TargetType.WASM32)
} }
internal fun warn(msg: String) { internal fun warn(msg: String) {
@@ -1,13 +1,8 @@
package org.jetbrains.kotlin.native.interop.gen.jvm package org.jetbrains.kotlin.native.interop.gen.jvm
import org.jetbrains.kotlin.native.interop.tool.CommonInteropArguments enum class GenerationMode(val modeName: String) {
SOURCE_CODE("sourcecode"),
METADATA("metadata");
enum class GenerationMode { override fun toString(): String = modeName
SOURCE_CODE, METADATA
}
fun parseGenerationMode(mode: String): GenerationMode? = when(mode) {
CommonInteropArguments.MODE_METADATA -> GenerationMode.METADATA
CommonInteropArguments.MODE_SOURCECODE -> GenerationMode.SOURCE_CODE
else -> null
} }
@@ -50,8 +50,8 @@ data class InternalInteropOptions(val generated: String, val natives: String, va
fun main(args: Array<String>) { fun main(args: Array<String>) {
// Adding flavor option for interop plugin. // Adding flavor option for interop plugin.
class FullCInteropArguments: CInteropArguments() { class FullCInteropArguments: CInteropArguments() {
val flavor by argParser.option(ArgType.Choice(listOf("jvm", "native", "wasm")), description = "Interop target") val flavor by argParser.option(ArgType.Choice<KotlinPlatform>(), description = "Interop target")
.default("jvm") .default(KotlinPlatform.JVM)
val generated by argParser.option(ArgType.String, description = "place generated bindings to the directory") val generated by argParser.option(ArgType.String, description = "place generated bindings to the directory")
.required() .required()
val natives by argParser.option(ArgType.String, description = "where to put the built native files") val natives by argParser.option(ArgType.String, description = "where to put the built native files")
@@ -70,7 +70,8 @@ fun interop(
"jvm", "native" -> { "jvm", "native" -> {
val cinteropArguments = CInteropArguments() val cinteropArguments = CInteropArguments()
cinteropArguments.argParser.parse(args) cinteropArguments.argParser.parse(args)
processCLib(flavor, cinteropArguments, additionalArgs) val platform = KotlinPlatform.values().single { it.name.equals(flavor, ignoreCase = true) }
processCLib(platform, cinteropArguments, additionalArgs)
} }
"wasm" -> processIdlLib(args, additionalArgs) "wasm" -> processIdlLib(args, additionalArgs)
else -> error("Unexpected flavor") else -> error("Unexpected flavor")
@@ -192,11 +193,10 @@ private fun findFilesByGlobs(roots: List<Path>, globs: List<String>): Map<Path,
return relativeToRoot return relativeToRoot
} }
private fun processCLib(flavorName: String, cinteropArguments: CInteropArguments, private fun processCLib(flavor: KotlinPlatform, cinteropArguments: CInteropArguments,
additionalArgs: InternalInteropOptions): Array<String>? { additionalArgs: InternalInteropOptions): Array<String>? {
val ktGenRoot = additionalArgs.generated val ktGenRoot = additionalArgs.generated
val nativeLibsDir = additionalArgs.natives val nativeLibsDir = additionalArgs.natives
val flavor = KotlinPlatform.values().single { it.name.equals(flavorName, ignoreCase = true) }
val defFile = cinteropArguments.def?.let { File(it) } val defFile = cinteropArguments.def?.let { File(it) }
val manifestAddend = additionalArgs.manifest?.let { File(it) } val manifestAddend = additionalArgs.manifest?.let { File(it) }
@@ -210,7 +210,7 @@ private fun processCLib(flavorName: String, cinteropArguments: CInteropArguments
val isLinkerOptsSetByUser = (cinteropArguments.linkerOpts.valueOrigin == ArgParser.ValueOrigin.SET_BY_USER) || val isLinkerOptsSetByUser = (cinteropArguments.linkerOpts.valueOrigin == ArgParser.ValueOrigin.SET_BY_USER) ||
(cinteropArguments.linkerOptions.valueOrigin == ArgParser.ValueOrigin.SET_BY_USER) || (cinteropArguments.linkerOptions.valueOrigin == ArgParser.ValueOrigin.SET_BY_USER) ||
(cinteropArguments.linkerOption.valueOrigin == ArgParser.ValueOrigin.SET_BY_USER) (cinteropArguments.linkerOption.valueOrigin == ArgParser.ValueOrigin.SET_BY_USER)
if (flavorName == "native" && isLinkerOptsSetByUser) { if (flavor == KotlinPlatform.NATIVE && isLinkerOptsSetByUser) {
warn("-linker-option(s)/-linkerOpts option is not supported by cinterop. Please add linker options to .def file or binary compilation instead.") warn("-linker-option(s)/-linkerOpts option is not supported by cinterop. Please add linker options to .def file or binary compilation instead.")
} }
@@ -238,8 +238,7 @@ private fun processCLib(flavorName: String, cinteropArguments: CInteropArguments
val outKtPkg = fqParts.joinToString(".") val outKtPkg = fqParts.joinToString(".")
val mode = run { val mode = run {
val providedMode = parseGenerationMode(cinteropArguments.mode) val providedMode = cinteropArguments.mode
?: error ("Unexpected interop generation mode: ${cinteropArguments.mode}")
if (providedMode == GenerationMode.METADATA && flavor == KotlinPlatform.JVM) { if (providedMode == GenerationMode.METADATA && flavor == KotlinPlatform.JVM) {
warn("Metadata mode isn't supported for Kotlin/JVM! Falling back to sourcecode.") warn("Metadata mode isn't supported for Kotlin/JVM! Falling back to sourcecode.")
@@ -19,9 +19,8 @@ import org.jetbrains.kotlin.konan.target.customerDistribution
import org.jetbrains.kotlin.konan.util.KonanHomeProvider import org.jetbrains.kotlin.konan.util.KonanHomeProvider
import org.jetbrains.kotlin.konan.util.PlatformLibsInfo import org.jetbrains.kotlin.konan.util.PlatformLibsInfo
import org.jetbrains.kotlin.konan.util.visibleName import org.jetbrains.kotlin.konan.util.visibleName
import org.jetbrains.kotlin.native.interop.gen.jvm.GenerationMode
import org.jetbrains.kotlin.native.interop.tool.CommonInteropArguments.Companion.DEFAULT_MODE import org.jetbrains.kotlin.native.interop.tool.CommonInteropArguments.Companion.DEFAULT_MODE
import org.jetbrains.kotlin.native.interop.tool.CommonInteropArguments.Companion.MODE_METADATA
import org.jetbrains.kotlin.native.interop.tool.CommonInteropArguments.Companion.MODE_SOURCECODE
import org.jetbrains.kotlin.native.interop.tool.SHORT_MODULE_NAME import org.jetbrains.kotlin.native.interop.tool.SHORT_MODULE_NAME
import java.io.PrintWriter import java.io.PrintWriter
import java.io.StringWriter import java.io.StringWriter
@@ -64,6 +63,11 @@ private fun Logger.logStackTrace(error: Throwable) {
verbose(stringWriter.toString()) verbose(stringWriter.toString())
} }
private enum class CacheKind(val outputKind: CompilerOutputKind) {
DYNAMIC_CACHE(CompilerOutputKind.DYNAMIC_CACHE),
STATIC_CACHE(CompilerOutputKind.STATIC_CACHE)
}
// TODO: Use Distribution's paths after compiler update. // TODO: Use Distribution's paths after compiler update.
fun generatePlatformLibraries(args: Array<String>) { fun generatePlatformLibraries(args: Array<String>) {
// IMPORTANT! These command line keys are used by the Gradle plugin to configure platform libraries generation, // IMPORTANT! These command line keys are used by the Gradle plugin to configure platform libraries generation,
@@ -90,17 +94,15 @@ fun generatePlatformLibraries(args: Array<String>) {
"Place where stdlib is located. Default value is <dist>/klib/common/stdlib" "Place where stdlib is located. Default value is <dist>/klib/common/stdlib"
) )
val dynamicCacheKind = CompilerOutputKind.DYNAMIC_CACHE.visibleName
val staticCacheKind = CompilerOutputKind.STATIC_CACHE.visibleName
val cacheKind by argParser.option( val cacheKind by argParser.option(
ArgType.Choice(listOf(dynamicCacheKind, staticCacheKind)), "cache-kind", "k", "Type of cache." ArgType.Choice<CacheKind>(toString = { it.outputKind.visibleName }), "cache-kind", "k", "Type of cache."
).default(dynamicCacheKind) ).default(CacheKind.DYNAMIC_CACHE)
val cacheDirectoryPath by argParser.option( val cacheDirectoryPath by argParser.option(
ArgType.String, "cache-directory", "c", "Cache output directory") ArgType.String, "cache-directory", "c", "Cache output directory")
val mode by argParser.option( val mode by argParser.option(
ArgType.Choice(listOf(MODE_METADATA, MODE_SOURCECODE)), ArgType.Choice<GenerationMode>(),
fullName = "mode", fullName = "mode",
shortName = "m", shortName = "m",
description = "The way interop library is generated." description = "The way interop library is generated."
@@ -146,7 +148,7 @@ fun generatePlatformLibraries(args: Array<String>) {
val logger = Logger(if (verbose) Logger.Level.VERBOSE else Logger.Level.NORMAL) val logger = Logger(if (verbose) Logger.Level.VERBOSE else Logger.Level.NORMAL)
val cacheInfo = cacheDirectory?.let { CacheInfo(it, cacheKind, cacheArgs) } val cacheInfo = cacheDirectory?.let { CacheInfo(it, cacheKind.outputKind.visibleName, cacheArgs) }
generatePlatformLibraries( generatePlatformLibraries(
target, mode, target, mode,
@@ -217,7 +219,7 @@ private fun topoSort(defFiles: List<DefFile>): List<DefFile> {
private fun generateLibrary( private fun generateLibrary(
target: KonanTarget, target: KonanTarget,
mode: String, mode: GenerationMode,
def: DefFile, def: DefFile,
directories: DirectoriesInfo, directories: DirectoriesInfo,
tmpDirectory: File, tmpDirectory: File,
@@ -242,7 +244,7 @@ private fun generateLibrary(
"-compiler-option", "-fmodules-cache-path=${tmpDirectory.child("clangModulesCache").absolutePath}", "-compiler-option", "-fmodules-cache-path=${tmpDirectory.child("clangModulesCache").absolutePath}",
"-repo", outputDirectory.absolutePath, "-repo", outputDirectory.absolutePath,
"-no-default-libs", "-no-endorsed-libs", "-Xpurge-user-libs", "-nopack", "-no-default-libs", "-no-endorsed-libs", "-Xpurge-user-libs", "-nopack",
"-mode", mode, "-mode", mode.modeName,
"-$SHORT_MODULE_NAME", def.shortLibraryName, "-$SHORT_MODULE_NAME", def.shortLibraryName,
*def.depends.flatMap { listOf("-l", "$outputDirectory/${it.libraryName}") }.toTypedArray() *def.depends.flatMap { listOf("-l", "$outputDirectory/${it.libraryName}") }.toTypedArray()
) )
@@ -327,7 +329,7 @@ private fun buildStdlibCache(
K2Native.mainNoExit(compilerArgs) K2Native.mainNoExit(compilerArgs)
} }
private fun generatePlatformLibraries(target: KonanTarget, mode: String, private fun generatePlatformLibraries(target: KonanTarget, mode: GenerationMode,
directories: DirectoriesInfo, cacheInfo: CacheInfo?, directories: DirectoriesInfo, cacheInfo: CacheInfo?,
rebuild: Boolean, saveTemps: Boolean, logger: Logger) = with(directories) { rebuild: Boolean, saveTemps: Boolean, logger: Logger) = with(directories) {
if (cacheInfo != null) { if (cacheInfo != null) {
@@ -39,7 +39,7 @@ fun invokeInterop(flavor: String, args: Array<String>): Array<String>? {
val libraries = arguments.library val libraries = arguments.library
val repos = arguments.repo val repos = arguments.repo
val targetRequest = if (arguments is CInteropArguments) arguments.target val targetRequest = if (arguments is CInteropArguments) arguments.target
else (arguments as JSInteropArguments).target else (arguments as JSInteropArguments).target.toString()
val target = PlatformManager(KonanHomeProvider.determineKonanHome()).targetManager(targetRequest).target val target = PlatformManager(KonanHomeProvider.determineKonanHome()).targetManager(targetRequest).target
val cinteropArgsToCompiler = interop(flavor, args, val cinteropArgsToCompiler = interop(flavor, args,