[interop] Prepare interop driver for a metadata-only mode.
This commit is contained in:
committed by
Sergey Bogolepov
parent
8a8ba03f9e
commit
e8ad4712d3
+67
-9
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jetbrains.kotlin.native.interop.gen
|
package org.jetbrains.kotlin.native.interop.gen
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.native.interop.gen.jvm.GenerationMode
|
||||||
import org.jetbrains.kotlin.native.interop.gen.jvm.InteropConfiguration
|
import org.jetbrains.kotlin.native.interop.gen.jvm.InteropConfiguration
|
||||||
import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform
|
import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform
|
||||||
import org.jetbrains.kotlin.native.interop.indexer.*
|
import org.jetbrains.kotlin.native.interop.indexer.*
|
||||||
@@ -86,18 +87,75 @@ class StubIrContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StubIrDriver(private val context: StubIrContext) {
|
class StubIrDriver(
|
||||||
fun run(outKtFile: File, outCFile: File, entryPoint: String?) {
|
private val context: StubIrContext,
|
||||||
|
private val options: DriverOptions
|
||||||
|
) {
|
||||||
|
data class DriverOptions(
|
||||||
|
val mode: GenerationMode,
|
||||||
|
val entryPoint: String?,
|
||||||
|
val outCFile: File,
|
||||||
|
val outKtFileCreator: () -> File
|
||||||
|
)
|
||||||
|
|
||||||
|
sealed class Result {
|
||||||
|
object SourceCode : Result()
|
||||||
|
|
||||||
|
// Will contain Km* objects.
|
||||||
|
class Metadata(): Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun run(): Result {
|
||||||
|
val (mode, entryPoint, outCFile, outKtFile) = options
|
||||||
|
|
||||||
val builderResult = StubIrBuilder(context).build()
|
val builderResult = StubIrBuilder(context).build()
|
||||||
val bridgeBuilderResult = StubIrBridgeBuilder(context, builderResult).build()
|
val bridgeBuilderResult = StubIrBridgeBuilder(context, builderResult).build()
|
||||||
outKtFile.bufferedWriter().use { ktFile ->
|
|
||||||
File(outCFile.absolutePath).bufferedWriter().use { cFile ->
|
outCFile.bufferedWriter().use {
|
||||||
StubIrTextEmitter(
|
emitCFile(context, it, entryPoint, bridgeBuilderResult.nativeBridges)
|
||||||
context,
|
}
|
||||||
builderResult,
|
|
||||||
bridgeBuilderResult
|
return when (mode) {
|
||||||
).emit(ktFile, cFile, entryPoint)
|
GenerationMode.SOURCE_CODE -> {
|
||||||
|
emitSourceCode(outKtFile(), builderResult, bridgeBuilderResult)
|
||||||
}
|
}
|
||||||
|
GenerationMode.METADATA -> emitMetadata(builderResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun emitSourceCode(
|
||||||
|
outKtFile: File, builderResult: StubIrBuilderResult, bridgeBuilderResult: BridgeBuilderResult
|
||||||
|
): Result.SourceCode {
|
||||||
|
outKtFile.bufferedWriter().use { ktFile ->
|
||||||
|
StubIrTextEmitter(context, builderResult, bridgeBuilderResult).emit(ktFile)
|
||||||
|
}
|
||||||
|
return Result.SourceCode
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun emitMetadata(builderResult: StubIrBuilderResult): Result.Metadata {
|
||||||
|
return Result.Metadata()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun emitCFile(context: StubIrContext, cFile: Appendable, entryPoint: String?, nativeBridges: NativeBridges) {
|
||||||
|
val out = { it: String -> cFile.appendln(it) }
|
||||||
|
|
||||||
|
context.libraryForCStubs.preambleLines.forEach {
|
||||||
|
out(it)
|
||||||
|
}
|
||||||
|
out("")
|
||||||
|
|
||||||
|
out("// NOTE THIS FILE IS AUTO-GENERATED")
|
||||||
|
out("")
|
||||||
|
|
||||||
|
nativeBridges.nativeLines.forEach { out(it) }
|
||||||
|
|
||||||
|
if (entryPoint != null) {
|
||||||
|
out("extern int Konan_main(int argc, char** argv);")
|
||||||
|
out("")
|
||||||
|
out("__attribute__((__used__))")
|
||||||
|
out("int $entryPoint(int argc, char** argv) {")
|
||||||
|
out(" return Konan_main(argc, argv);")
|
||||||
|
out("}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-22
@@ -148,28 +148,7 @@ class StubIrTextEmitter(
|
|||||||
|
|
||||||
out("// NOTE THIS FILE IS AUTO-GENERATED")
|
out("// NOTE THIS FILE IS AUTO-GENERATED")
|
||||||
}
|
}
|
||||||
fun emit(ktFile: Appendable, cFile: Appendable, entryPoint: String?) {
|
fun emit(ktFile: Appendable) {
|
||||||
|
|
||||||
withOutput(cFile) {
|
|
||||||
context.libraryForCStubs.preambleLines.forEach {
|
|
||||||
out(it)
|
|
||||||
}
|
|
||||||
out("")
|
|
||||||
|
|
||||||
out("// NOTE THIS FILE IS AUTO-GENERATED")
|
|
||||||
out("")
|
|
||||||
|
|
||||||
nativeBridges.nativeLines.forEach(out)
|
|
||||||
|
|
||||||
if (entryPoint != null) {
|
|
||||||
out("extern int Konan_main(int argc, char** argv);")
|
|
||||||
out("")
|
|
||||||
out("__attribute__((__used__))")
|
|
||||||
out("int $entryPoint(int argc, char** argv) {")
|
|
||||||
out(" return Konan_main(argc, argv);")
|
|
||||||
out("}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stubs generation may affect imports list so do it before header generation.
|
// Stubs generation may affect imports list so do it before header generation.
|
||||||
val stubLines = generateKotlinFragmentBy {
|
val stubLines = generateKotlinFragmentBy {
|
||||||
|
|||||||
+7
@@ -48,6 +48,8 @@ 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")
|
||||||
|
.default(MODE_SOURCECODE)
|
||||||
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)
|
||||||
val nodefaultlibsDeprecated by argParser.option(ArgType.Boolean, NODEFAULTLIBS_DEPRECATED,
|
val nodefaultlibsDeprecated by argParser.option(ArgType.Boolean, NODEFAULTLIBS_DEPRECATED,
|
||||||
@@ -59,6 +61,11 @@ open class CommonInteropArguments(val argParser: ArgParser) {
|
|||||||
description = "don't link unused libraries even explicitly specified").default(false)
|
description = "don't link unused libraries even explicitly specified").default(false)
|
||||||
val tempDir by argParser.option(ArgType.String, TEMP_DIR,
|
val tempDir by argParser.option(ArgType.String, TEMP_DIR,
|
||||||
description = "save temporary files to the given directory")
|
description = "save temporary files to the given directory")
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val MODE_SOURCECODE = "sourcecode"
|
||||||
|
const val MODE_METADATA = "metadata"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CInteropArguments(argParser: ArgParser =
|
class CInteropArguments(argParser: ArgParser =
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package org.jetbrains.kotlin.native.interop.gen.jvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.native.interop.tool.CommonInteropArguments
|
||||||
|
|
||||||
|
enum class GenerationMode {
|
||||||
|
SOURCE_CODE, METADATA
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseGenerationMode(mode: String): GenerationMode? = when(mode) {
|
||||||
|
CommonInteropArguments.MODE_METADATA -> GenerationMode.METADATA
|
||||||
|
CommonInteropArguments.MODE_SOURCECODE -> GenerationMode.SOURCE_CODE
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.kotlin.native.interop.gen.jvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.CURRENT
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
|
import org.jetbrains.kotlin.konan.library.impl.KonanLibraryWriterImpl
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import org.jetbrains.kotlin.library.KonanLibraryVersioning
|
||||||
|
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
data class LibraryCreationArguments(
|
||||||
|
val outputPath: String,
|
||||||
|
val moduleName: String,
|
||||||
|
val nativeBitcodePath: String,
|
||||||
|
val target: KonanTarget,
|
||||||
|
val manifest: Properties
|
||||||
|
)
|
||||||
|
|
||||||
|
fun createInteropLibrary(arguments: LibraryCreationArguments) {
|
||||||
|
val version = KonanLibraryVersioning(
|
||||||
|
libraryVersion = null,
|
||||||
|
abiVersion = KotlinAbiVersion.CURRENT,
|
||||||
|
compilerVersion = KonanVersion.CURRENT
|
||||||
|
)
|
||||||
|
KonanLibraryWriterImpl(
|
||||||
|
File(arguments.outputPath),arguments.moduleName, version, arguments.target
|
||||||
|
).apply {
|
||||||
|
addNativeBitcode(arguments.nativeBitcodePath)
|
||||||
|
addManifestAddend(arguments.manifest)
|
||||||
|
commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
+59
-32
@@ -34,8 +34,10 @@ fun main(args: Array<String>) {
|
|||||||
processCLib(args)
|
processCLib(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun interop(flavor: String, args: Array<String>, additionalArgs: Map<String, Any> = mapOf()) =
|
fun interop(
|
||||||
when(flavor) {
|
flavor: String, args: Array<String>,
|
||||||
|
additionalArgs: Map<String, Any> = mapOf()
|
||||||
|
): Array<String>? = when(flavor) {
|
||||||
"jvm", "native" -> processCLib(args, additionalArgs)
|
"jvm", "native" -> processCLib(args, additionalArgs)
|
||||||
"wasm" -> processIdlLib(args, additionalArgs)
|
"wasm" -> processIdlLib(args, additionalArgs)
|
||||||
else -> error("Unexpected flavor")
|
else -> error("Unexpected flavor")
|
||||||
@@ -159,7 +161,7 @@ private fun findFilesByGlobs(roots: List<Path>, globs: List<String>): Map<Path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun processCLib(args: Array<String>, additionalArgs: Map<String, Any> = mapOf()): Array<String> {
|
private fun processCLib(args: Array<String>, additionalArgs: Map<String, Any> = mapOf()): Array<String>? {
|
||||||
val cinteropArguments = CInteropArguments()
|
val cinteropArguments = CInteropArguments()
|
||||||
cinteropArguments.argParser.parse(args)
|
cinteropArguments.argParser.parse(args)
|
||||||
val ktGenRoot = cinteropArguments.generated
|
val ktGenRoot = cinteropArguments.generated
|
||||||
@@ -204,11 +206,7 @@ private fun processCLib(args: Array<String>, additionalArgs: Map<String, Any> =
|
|||||||
val fqParts = (cinteropArguments.pkg ?: def.config.packageName)?.split('.')
|
val fqParts = (cinteropArguments.pkg ?: def.config.packageName)?.split('.')
|
||||||
?: defFile!!.name.split('.').reversed().drop(1)
|
?: defFile!!.name.split('.').reversed().drop(1)
|
||||||
|
|
||||||
val outKtFileName = fqParts.last() + ".kt"
|
|
||||||
|
|
||||||
val outKtPkg = fqParts.joinToString(".")
|
val outKtPkg = fqParts.joinToString(".")
|
||||||
val outKtFileRelative = (fqParts + outKtFileName).joinToString("/")
|
|
||||||
val outKtFile = File(ktGenRoot, outKtFileRelative)
|
|
||||||
|
|
||||||
val libName = (additionalArgs["cstubsname"] as? String)?: fqParts.joinToString("") + "stubs"
|
val libName = (additionalArgs["cstubsname"] as? String)?: fqParts.joinToString("") + "stubs"
|
||||||
|
|
||||||
@@ -240,7 +238,6 @@ private fun processCLib(args: Array<String>, additionalArgs: Map<String, Any> =
|
|||||||
target = target
|
target = target
|
||||||
)
|
)
|
||||||
|
|
||||||
outKtFile.parentFile.mkdirs()
|
|
||||||
|
|
||||||
File(nativeLibsDir).mkdirs()
|
File(nativeLibsDir).mkdirs()
|
||||||
val outCFile = tempFiles.create(libName, ".${language.sourceFileExtension}")
|
val outCFile = tempFiles.create(libName, ".${language.sourceFileExtension}")
|
||||||
@@ -251,9 +248,22 @@ private fun processCLib(args: Array<String>, additionalArgs: Map<String, Any> =
|
|||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val mode = parseGenerationMode(cinteropArguments.mode)
|
||||||
|
?: error ("Unexpected interop generation mode: ${cinteropArguments.mode}")
|
||||||
|
|
||||||
val stubIrContext = StubIrContext(logger, configuration, nativeIndex, imports, flavor, libName)
|
val stubIrContext = StubIrContext(logger, configuration, nativeIndex, imports, flavor, libName)
|
||||||
val stubIrDriver = StubIrDriver(stubIrContext)
|
val stubIrOutput = run {
|
||||||
stubIrDriver.run(outKtFile, File(outCFile.absolutePath), entryPoint)
|
val outKtFileCreator = {
|
||||||
|
val outKtFileName = fqParts.last() + ".kt"
|
||||||
|
val outKtFileRelative = (fqParts + outKtFileName).joinToString("/")
|
||||||
|
val file = File(ktGenRoot, outKtFileRelative)
|
||||||
|
file.parentFile.mkdirs()
|
||||||
|
file
|
||||||
|
}
|
||||||
|
val driverOptions = StubIrDriver.DriverOptions(mode, entryPoint, File(outCFile.absolutePath), outKtFileCreator)
|
||||||
|
val stubIrDriver = StubIrDriver(stubIrContext, driverOptions)
|
||||||
|
stubIrDriver.run()
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: if a library has partially included headers, then it shouldn't be used as a dependency.
|
// TODO: if a library has partially included headers, then it shouldn't be used as a dependency.
|
||||||
def.manifestAddendProperties["includedHeaders"] = nativeIndex.includedHeaders.joinToString(" ") { it.value }
|
def.manifestAddendProperties["includedHeaders"] = nativeIndex.includedHeaders.joinToString(" ") { it.value }
|
||||||
@@ -270,31 +280,48 @@ private fun processCLib(args: Array<String>, additionalArgs: Map<String, Any> =
|
|||||||
manifestAddend?.parentFile?.mkdirs()
|
manifestAddend?.parentFile?.mkdirs()
|
||||||
manifestAddend?.let { def.manifestAddendProperties.storeProperties(it) }
|
manifestAddend?.let { def.manifestAddendProperties.storeProperties(it) }
|
||||||
|
|
||||||
if (flavor == KotlinPlatform.JVM) {
|
val compilerArgs = stubIrContext.libraryForCStubs.compilerArgs.toTypedArray()
|
||||||
|
val nativeOutputPath: String = when (flavor) {
|
||||||
|
KotlinPlatform.JVM -> {
|
||||||
|
val outOFile = tempFiles.create(libName,".o")
|
||||||
|
val compilerCmd = arrayOf(compiler, *compilerArgs,
|
||||||
|
"-c", outCFile.absolutePath, "-o", outOFile.absolutePath)
|
||||||
|
runCmd(compilerCmd, verbose)
|
||||||
|
|
||||||
val outOFile = tempFiles.create(libName,".o")
|
val outLib = File(nativeLibsDir, System.mapLibraryName(libName))
|
||||||
|
val linkerCmd = arrayOf(linker,
|
||||||
|
outOFile.absolutePath, "-shared", "-o", outLib.absolutePath,
|
||||||
|
*linkerOpts)
|
||||||
|
runCmd(linkerCmd, verbose)
|
||||||
|
outOFile.absolutePath
|
||||||
|
}
|
||||||
|
KotlinPlatform.NATIVE -> {
|
||||||
|
val outLib = File(nativeLibsDir, "$libName.bc")
|
||||||
|
val compilerCmd = arrayOf(compiler, *compilerArgs,
|
||||||
|
"-emit-llvm", "-c", outCFile.absolutePath, "-o", outLib.absolutePath)
|
||||||
|
|
||||||
val compilerCmd = arrayOf(compiler, *stubIrContext.libraryForCStubs.compilerArgs.toTypedArray(),
|
runCmd(compilerCmd, verbose)
|
||||||
"-c", outCFile.absolutePath, "-o", outOFile.absolutePath)
|
outLib.absolutePath
|
||||||
|
}
|
||||||
runCmd(compilerCmd, verbose)
|
}
|
||||||
|
|
||||||
val outLib = File(nativeLibsDir, System.mapLibraryName(libName))
|
return when (stubIrOutput) {
|
||||||
|
is StubIrDriver.Result.SourceCode -> {
|
||||||
val linkerCmd = arrayOf(linker,
|
argsToCompiler(staticLibraries, libraryPaths)
|
||||||
outOFile.absolutePath, "-shared", "-o", outLib.absolutePath,
|
}
|
||||||
*linkerOpts)
|
is StubIrDriver.Result.Metadata -> {
|
||||||
|
val moduleName = File(cinteropArguments.output).nameWithoutExtension
|
||||||
runCmd(linkerCmd, verbose)
|
val args = LibraryCreationArguments(
|
||||||
} else if (flavor == KotlinPlatform.NATIVE) {
|
nativeBitcodePath = nativeOutputPath,
|
||||||
val outBcName = libName + ".bc"
|
target = tool.target,
|
||||||
val outLib = File(nativeLibsDir, outBcName)
|
moduleName = moduleName,
|
||||||
val compilerCmd = arrayOf(compiler, *stubIrContext.libraryForCStubs.compilerArgs.toTypedArray(),
|
outputPath = cinteropArguments.output,
|
||||||
"-emit-llvm", "-c", outCFile.absolutePath, "-o", outLib.absolutePath)
|
manifest = def.manifestAddendProperties
|
||||||
|
)
|
||||||
runCmd(compilerCmd, verbose)
|
createInteropLibrary(args)
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return argsToCompiler(staticLibraries, libraryPaths)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun prepareTool(target: String?, flavor: KotlinPlatform): ToolConfig {
|
internal fun prepareTool(target: String?, flavor: KotlinPlatform): ToolConfig {
|
||||||
|
|||||||
+1
-1
@@ -83,7 +83,7 @@ private fun generatePlatformLibraries(target: String, inputDirectory: File, outp
|
|||||||
"-no-default-libs", "-no-endorsed-libs", "-Xpurge-user-libs",
|
"-no-default-libs", "-no-endorsed-libs", "-Xpurge-user-libs",
|
||||||
*def.depends.flatMap { listOf("-l", "$outputDirectory/${it.name}") }.toTypedArray())
|
*def.depends.flatMap { listOf("-l", "$outputDirectory/${it.name}") }.toTypedArray())
|
||||||
println("Processing ${def.name}...")
|
println("Processing ${def.name}...")
|
||||||
K2Native.mainNoExit(invokeInterop("native", args))
|
invokeInterop("native", args)?.let { K2Native.mainNoExit(it) }
|
||||||
org.jetbrains.kotlin.cli.klib.main(arrayOf("install", outKlib,
|
org.jetbrains.kotlin.cli.klib.main(arrayOf("install", outKlib,
|
||||||
"-target", target,
|
"-target", target,
|
||||||
"-repository", "${outputDirectory.absolutePath}"
|
"-repository", "${outputDirectory.absolutePath}"
|
||||||
|
|||||||
@@ -19,7 +19,11 @@ import org.jetbrains.kotlin.native.interop.tool.*
|
|||||||
// TODO: this function should eventually be eliminated from 'utilities'.
|
// TODO: this function should eventually be eliminated from 'utilities'.
|
||||||
// The interaction of interop and the compiler should be streamlined.
|
// The interaction of interop and the compiler should be streamlined.
|
||||||
|
|
||||||
fun invokeInterop(flavor: String, args: Array<String>): Array<String> {
|
/**
|
||||||
|
* @return null if there is no need in compiler invocation.
|
||||||
|
* Otherwise returns array of compiler args.
|
||||||
|
*/
|
||||||
|
fun invokeInterop(flavor: String, args: Array<String>): Array<String>? {
|
||||||
val arguments = if (flavor == "native") CInteropArguments() else JSInteropArguments()
|
val arguments = if (flavor == "native") CInteropArguments() else JSInteropArguments()
|
||||||
arguments.argParser.parse(args)
|
arguments.argParser.parse(args)
|
||||||
val outputFileName = arguments.output
|
val outputFileName = arguments.output
|
||||||
@@ -68,7 +72,9 @@ fun invokeInterop(flavor: String, args: Array<String>): Array<String> {
|
|||||||
additionalProperties.putAll(mapOf("cstubsname" to cstubsName, "import" to imports))
|
additionalProperties.putAll(mapOf("cstubsname" to cstubsName, "import" to imports))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val cinteropArgsToCompiler = interop(flavor, args + additionalArgs, additionalProperties)
|
val cinteropArgsToCompiler = interop(flavor, args + additionalArgs, additionalProperties)
|
||||||
|
?: return null // There is no need in compiler invocation if we're generating only metadata.
|
||||||
|
|
||||||
val nativeStubs =
|
val nativeStubs =
|
||||||
if (flavor == "wasm")
|
if (flavor == "wasm")
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ private fun mainImpl(args: Array<String>, konancMain: (Array<String>) -> Unit) {
|
|||||||
konancMain(utilityArgs)
|
konancMain(utilityArgs)
|
||||||
"cinterop" -> {
|
"cinterop" -> {
|
||||||
val konancArgs = invokeInterop("native", utilityArgs)
|
val konancArgs = invokeInterop("native", utilityArgs)
|
||||||
konancMain(konancArgs)
|
konancArgs?.let { konancMain(it) }
|
||||||
}
|
}
|
||||||
"jsinterop" -> {
|
"jsinterop" -> {
|
||||||
val konancArgs = invokeInterop("wasm", utilityArgs)
|
val konancArgs = invokeInterop("wasm", utilityArgs)
|
||||||
konancMain(konancArgs)
|
konancArgs?.let { konancMain(it) }
|
||||||
}
|
}
|
||||||
"klib" ->
|
"klib" ->
|
||||||
klibMain(utilityArgs)
|
klibMain(utilityArgs)
|
||||||
|
|||||||
Reference in New Issue
Block a user