Add "_main" as alias to "Konan_main" via LLVMAddAlias

This commit is contained in:
Sergey Bogolepov
2019-08-28 19:51:57 +07:00
committed by Sergey Bogolepov
parent 8e0e346492
commit 7844dc5228
6 changed files with 29 additions and 132 deletions
@@ -205,7 +205,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
put(FRAMEWORK_IMPORT_HEADERS, arguments.frameworkImportHeaders.toNonNullList()) put(FRAMEWORK_IMPORT_HEADERS, arguments.frameworkImportHeaders.toNonNullList())
arguments.emitLazyObjCHeader?.let { put(EMIT_LAZY_OBJC_HEADER_FILE, it) } arguments.emitLazyObjCHeader?.let { put(EMIT_LAZY_OBJC_HEADER_FILE, it) }
put(BITCODE_EMBEDDING_MODE, selectBitcodeEmbeddingMode(this, arguments, outputKind)) put(BITCODE_EMBEDDING_MODE, selectBitcodeEmbeddingMode(this, arguments))
put(DEBUG_INFO_VERSION, arguments.debugInfoFormatVersion.toInt()) put(DEBUG_INFO_VERSION, arguments.debugInfoFormatVersion.toInt())
put(COVERAGE, arguments.coverage) put(COVERAGE, arguments.coverage)
put(LIBRARIES_TO_COVER, arguments.coveredLibraries.toNonNullList()) put(LIBRARIES_TO_COVER, arguments.coveredLibraries.toNonNullList())
@@ -247,41 +247,21 @@ private fun selectFrameworkType(
private fun selectBitcodeEmbeddingMode( private fun selectBitcodeEmbeddingMode(
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
arguments: K2NativeCompilerArguments, arguments: K2NativeCompilerArguments
outputKind: CompilerOutputKind ): BitcodeEmbedding.Mode = when {
): BitcodeEmbedding.Mode { arguments.embedBitcodeMarker -> {
if (arguments.embedBitcode) {
if (outputKind != CompilerOutputKind.FRAMEWORK) {
return BitcodeEmbedding.Mode.NONE.also {
val flag = when {
arguments.embedBitcodeMarker -> EMBED_BITCODE_MARKER_FLAG
arguments.embedBitcode -> EMBED_BITCODE_FLAG
else -> return@also
}
configuration.report( configuration.report(
STRONG_WARNING, STRONG_WARNING,
"'$flag' is only supported when producing frameworks, " + "'$EMBED_BITCODE_FLAG' is ignored because '$EMBED_BITCODE_MARKER_FLAG' is specified"
"but the compiler is producing ${outputKind.name.toLowerCase()}"
) )
} }
BitcodeEmbedding.Mode.MARKER
} }
arguments.embedBitcode -> {
return when { BitcodeEmbedding.Mode.FULL
arguments.embedBitcodeMarker -> {
if (arguments.embedBitcode) {
configuration.report(
STRONG_WARNING,
"'$EMBED_BITCODE_FLAG' is ignored because '$EMBED_BITCODE_MARKER_FLAG' is specified"
)
}
BitcodeEmbedding.Mode.MARKER
}
arguments.embedBitcode -> {
BitcodeEmbedding.Mode.FULL
}
else -> BitcodeEmbedding.Mode.NONE
} }
else -> BitcodeEmbedding.Mode.NONE
} }
private fun selectExportedLibraries( private fun selectExportedLibraries(
@@ -1,9 +1,5 @@
package org.jetbrains.kotlin.backend.konan package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.llvm.Int8
import org.jetbrains.kotlin.backend.konan.llvm.Llvm
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
object BitcodeEmbedding { object BitcodeEmbedding {
enum class Mode { enum class Mode {
@@ -17,31 +13,10 @@ object BitcodeEmbedding {
} }
internal fun getClangOptions(config: KonanConfig): List<String> = when (config.bitcodeEmbeddingMode) { internal fun getClangOptions(config: KonanConfig): List<String> = when (config.bitcodeEmbeddingMode) {
BitcodeEmbedding.Mode.NONE -> listOf("-fembed-bitcode=off") Mode.NONE -> listOf("-fembed-bitcode=off")
BitcodeEmbedding.Mode.MARKER -> listOf("-fembed-bitcode=marker") Mode.MARKER -> listOf("-fembed-bitcode=marker")
BitcodeEmbedding.Mode.FULL -> listOf("-fembed-bitcode=all") Mode.FULL -> listOf("-fembed-bitcode=all")
} }
private val KonanConfig.bitcodeEmbeddingMode get() = configuration.get(KonanConfigKeys.BITCODE_EMBEDDING_MODE)!!.also { private val KonanConfig.bitcodeEmbeddingMode get() = configuration.get(KonanConfigKeys.BITCODE_EMBEDDING_MODE)!!
require(it == Mode.NONE || this.produce == CompilerOutputKind.FRAMEWORK) {
"${it.name.toLowerCase()} bitcode embedding mode is not supported when producing ${this.produce.name.toLowerCase()}"
}
}
internal fun processModule(llvm: Llvm) = when (llvm.context.config.bitcodeEmbeddingMode) {
Mode.NONE -> {}
Mode.MARKER -> {
addEmptyMarker(llvm, "konan_llvm_bitcode", "__LLVM,__bitcode")
addEmptyMarker(llvm, "konan_llvm_cmdline", "__LLVM,__cmdline")
}
Mode.FULL -> {
addEmptyMarker(llvm, "konan_llvm_asm", "__LLVM,__asm")
}
}
private fun addEmptyMarker(llvm: Llvm, name: String, section: String) {
val global = llvm.staticData.placeGlobal(name, Int8(0), isExported = false)
global.setSection(section)
llvm.usedGlobals += global.llvmGlobal
}
} }
@@ -4,9 +4,7 @@
*/ */
package org.jetbrains.kotlin.backend.konan package org.jetbrains.kotlin.backend.konan
import llvm.LLVMLinkModules2 import llvm.*
import llvm.LLVMModuleRef
import llvm.LLVMWriteBitcodeToFile
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.backend.konan.llvm.*
import org.jetbrains.kotlin.backend.konan.llvm.Llvm import org.jetbrains.kotlin.backend.konan.llvm.Llvm
@@ -57,6 +55,16 @@ private fun runLlvmPipeline(context: Context) = when {
else -> {} else -> {}
} }
private fun insertAliasToEntryPoint(context: Context) {
val nomain = context.config.configuration.get(KonanConfigKeys.NOMAIN) ?: false
if (context.config.produce != CompilerOutputKind.PROGRAM || nomain)
return
val module = context.llvmModule
val entryPoint = LLVMGetNamedFunction(module, "Konan_main")
?: error("Module doesn't contain `Konan_main`")
LLVMAddAlias(module, LLVMTypeOf(entryPoint)!!, entryPoint, "main")
}
internal fun produceOutput(context: Context) { internal fun produceOutput(context: Context) {
val config = context.config.configuration val config = context.config.configuration
@@ -83,6 +91,9 @@ internal fun produceOutput(context: Context) {
} }
linkAllDependecies(context, generatedBitcodeFiles) linkAllDependecies(context, generatedBitcodeFiles)
runLlvmPipeline(context) runLlvmPipeline(context)
// Insert `_main` after pipeline so we won't worry about optimizations
// corrupting entry point.
insertAliasToEntryPoint(context)
LLVMWriteBitcodeToFile(context.llvmModule!!, output) LLVMWriteBitcodeToFile(context.llvmModule!!, output)
} }
CompilerOutputKind.LIBRARY -> { CompilerOutputKind.LIBRARY -> {
@@ -24,22 +24,11 @@ internal class Linker(val context: Context) {
private val platform = context.config.platform private val platform = context.config.platform
private val config = context.config.configuration private val config = context.config.configuration
private val linkerOutput = determineLinkerOutput(context) private val linkerOutput = determineLinkerOutput(context)
private val nomain = config.get(KonanConfigKeys.NOMAIN) ?: false
private val linker = platform.linker private val linker = platform.linker
private val target = context.config.target private val target = context.config.target
private val optimize = context.shouldOptimize() private val optimize = context.shouldOptimize()
private val debug = context.config.debug || context.config.lightDebug private val debug = context.config.debug || context.config.lightDebug
// Ideally we'd want to have
// #pragma weak main = Konan_main
// in the launcher.cpp.
// Unfortunately, anything related to weak linking on MacOS
// only seems to be working with dynamic libraries.
// So we stick to "-alias _main _konan_main" on Mac.
// And just do the same on Linux.
private val entryPointSelector: List<String>
get() = if (nomain || linkerOutput != LinkerOutputKind.EXECUTABLE) emptyList() else platform.entrySelector
fun link(objectFiles: List<ObjectFile>) { fun link(objectFiles: List<ObjectFile>) {
val nativeDependencies = context.llvm.nativeDependenciesToLink val nativeDependencies = context.llvm.nativeDependenciesToLink
val includedBinaries = nativeDependencies.map { it.includedPaths }.flatten() val includedBinaries = nativeDependencies.map { it.includedPaths }.flatten()
@@ -91,8 +80,7 @@ internal class Linker(val context: Context) {
File(executable).delete() File(executable).delete()
linker.linkCommands(objectFiles = objectFiles, executable = executable, linker.linkCommands(objectFiles = objectFiles, executable = executable,
libraries = linker.linkStaticLibraries(includedBinaries) + context.config.defaultSystemLibraries, libraries = linker.linkStaticLibraries(includedBinaries) + context.config.defaultSystemLibraries,
linkerArgs = entryPointSelector + linkerArgs = asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) +
asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) +
BitcodeEmbedding.getLinkerOptions(context.config) + BitcodeEmbedding.getLinkerOptions(context.config) +
libraryProvidedLinkerFlags + frameworkLinkerArgs, libraryProvidedLinkerFlags + frameworkLinkerArgs,
optimize = optimize, debug = debug, kind = linkerOutput, optimize = optimize, debug = debug, kind = linkerOutput,
@@ -308,7 +308,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
if (context.isNativeLibrary) { if (context.isNativeLibrary) {
appendCAdapters() appendCAdapters()
} }
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
@@ -2246,47 +2245,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
llvmDebugSelector.setLinkage(LLVMLinkage.LLVMExternalLinkage) llvmDebugSelector.setLinkage(LLVMLinkage.LLVMExternalLinkage)
} }
//-------------------------------------------------------------------------//
private fun entryPointSelector(entryPoint: LLVMValueRef,
entryPointType: LLVMTypeRef, selectorName: String, argCount: Int): LLVMValueRef {
assert(LLVMCountParams(entryPoint) <= 1)
val selector = LLVMAddFunction(context.llvmModule, selectorName, entryPointType)!!
generateFunction(codegen, selector) {
// Note, that 'parameter' is an object reference, and as such, shall
// be accounted for in the rootset. However, current object management
// scheme for arguments guarantees, that reference is being held in C++
// launcher, so we could optimize out creating slot for 'parameter' in
// this function.
val parameters = if (argCount == 1)
listOf(LLVMGetParam(selector, 0)!!)
else
emptyList()
call(entryPoint, parameters, Lifetime.IRRELEVANT, ExceptionHandler.Caller)
ret(null)
}
return selector
}
//-------------------------------------------------------------------------//
private fun appendEntryPointSelector(function: IrFunction?) {
if (function == null) return
val entryPoint = codegen.llvmFunction(function)
val selectorName = "EntryPointSelector"
val entryPointType = getFunctionType(entryPoint)
val argCount = function.valueParameters.size
assert(argCount <= 1)
val selector = entryPointSelector(entryPoint, entryPointType, selectorName, argCount)
LLVMSetLinkage(selector, LLVMLinkage.LLVMExternalLinkage)
}
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
// Create type { i32, void ()*, i8* } // Create type { i32, void ()*, i8* }
-15
View File
@@ -58,7 +58,6 @@ linkerDynamicFlags.macos_x64 = -dylib
osVersionMinFlagLd.macos_x64 = -macosx_version_min osVersionMinFlagLd.macos_x64 = -macosx_version_min
osVersionMinFlagClang.macos_x64 = -mmacosx-version-min osVersionMinFlagClang.macos_x64 = -mmacosx-version-min
osVersionMin.macos_x64 = 10.11 osVersionMin.macos_x64 = 10.11
entrySelector.macos_x64 = -alias _Konan_main _main
dependencies.macos_x64 = \ dependencies.macos_x64 = \
libffi-3.2.1-3-darwin-macos \ libffi-3.2.1-3-darwin-macos \
lldb-1-macos \ lldb-1-macos \
@@ -84,7 +83,6 @@ target-sysroot-9-ios_arm32.default = \
remote:internal remote:internal
arch.ios_arm32 = armv7 arch.ios_arm32 = armv7
entrySelector.ios_arm32 = -alias _Konan_main _main
# Shared with 64-bit version. # Shared with 64-bit version.
targetSysRoot.ios_arm32 = target-sysroot-9-ios_arm64 targetSysRoot.ios_arm32 = target-sysroot-9-ios_arm64
@@ -111,7 +109,6 @@ target-sysroot-9-ios_arm64.default = \
remote:internal remote:internal
arch.ios_arm64 = arm64 arch.ios_arm64 = arm64
entrySelector.ios_arm64 = -alias _Konan_main _main
targetSysRoot.ios_arm64 = target-sysroot-9-ios_arm64 targetSysRoot.ios_arm64 = target-sysroot-9-ios_arm64
clangFlags.ios_arm64 = -cc1 -emit-obj -disable-llvm-passes -x ir clangFlags.ios_arm64 = -cc1 -emit-obj -disable-llvm-passes -x ir
@@ -138,7 +135,6 @@ target-sysroot-9-ios_x64.default = \
remote:internal remote:internal
arch.ios_x64 = x86_64 arch.ios_x64 = x86_64
entrySelector.ios_x64 = -alias _Konan_main _main
targetSysRoot.ios_x64 = target-sysroot-9-ios_x64 targetSysRoot.ios_x64 = target-sysroot-9-ios_x64
clangFlags.ios_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir clangFlags.ios_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir
@@ -197,7 +193,6 @@ linkerNoDebugFlags.linux_x64 = -S
linkerDynamicFlags.linux_x64 = -shared linkerDynamicFlags.linux_x64 = -shared
pluginOptimizationFlags.linux_x64 = -plugin-opt=target-cpu x86-64 -plugin-opt=O3 pluginOptimizationFlags.linux_x64 = -plugin-opt=target-cpu x86-64 -plugin-opt=O3
dynamicLinker.linux_x64 = /lib64/ld-linux-x86-64.so.2 dynamicLinker.linux_x64 = /lib64/ld-linux-x86-64.so.2
entrySelector.linux_x64 = --defsym main=Konan_main
# targetSysRoot relative # targetSysRoot relative
abiSpecificLibraries.linux_x64 = ../lib64 lib64 usr/lib64 abiSpecificLibraries.linux_x64 = ../lib64 lib64 usr/lib64
@@ -222,7 +217,6 @@ dependencies.macos_x64-linux_arm32_hfp = \
target-sysroot-2-raspberrypi target-sysroot-2-raspberrypi
quadruple.linux_arm32_hfp = armv6-unknown-linux-gnueabihf quadruple.linux_arm32_hfp = armv6-unknown-linux-gnueabihf
entrySelector.linux_arm32_hfp = --defsym main=Konan_main
linkerNoDebugFlags.linux_arm32_hfp = -S linkerNoDebugFlags.linux_arm32_hfp = -S
linkerDynamicFlags.linux_arm32_hfp = -shared linkerDynamicFlags.linux_arm32_hfp = -shared
linkerOptimizationFlags.linux_arm32_hfp = --gc-sections linkerOptimizationFlags.linux_arm32_hfp = --gc-sections
@@ -265,7 +259,6 @@ dependencies.macos_x64-linux_arm64 = \
target-sysroot-1-linux-glibc-arm64 target-sysroot-1-linux-glibc-arm64
quadruple.linux_arm64 = aarch64-unknown-linux-gnu quadruple.linux_arm64 = aarch64-unknown-linux-gnu
entrySelector.linux_arm64 = --defsym main=Konan_main
linkerNoDebugFlags.linux_arm64 = -S linkerNoDebugFlags.linux_arm64 = -S
linkerDynamicFlags.linux_arm64 = -shared linkerDynamicFlags.linux_arm64 = -shared
linkerOptimizationFlags.linux_arm64 = --gc-sections linkerOptimizationFlags.linux_arm64 = --gc-sections
@@ -297,7 +290,6 @@ dependencies.linux_x64-linux_mips32 = \
libffi-3.2.1-2-linux-x86-64 libffi-3.2.1-2-linux-x86-64
quadruple.linux_mips32 = mips-unknown-linux-gnu quadruple.linux_mips32 = mips-unknown-linux-gnu
entrySelector.linux_mips32 = --defsym main=Konan_main
linkerOptimizationFlags.linux_mips32 = --gc-sections linkerOptimizationFlags.linux_mips32 = --gc-sections
linkerDynamicFlags.linux_mips32 = -shared linkerDynamicFlags.linux_mips32 = -shared
targetSysRoot.linux_mips32 = target-sysroot-2-mips targetSysRoot.linux_mips32 = target-sysroot-2-mips
@@ -324,7 +316,6 @@ dependencies.linux_x64-linux_mipsel32 = \
target-sysroot-2-mipsel \ target-sysroot-2-mipsel \
libffi-3.2.1-2-linux-x86-64 libffi-3.2.1-2-linux-x86-64
quadruple.linux_mipsel32 = mipsel-unknown-linux-gnu quadruple.linux_mipsel32 = mipsel-unknown-linux-gnu
entrySelector.linux_mipsel32 = --defsym main=Konan_main
linkerOptimizationFlags.linux_mipsel32 = --gc-sections linkerOptimizationFlags.linux_mipsel32 = --gc-sections
linkerDynamicFlags.linux_mipsel32 = -shared linkerDynamicFlags.linux_mipsel32 = -shared
targetSysRoot.linux_mipsel32 = target-sysroot-2-mipsel targetSysRoot.linux_mipsel32 = target-sysroot-2-mipsel
@@ -363,7 +354,6 @@ dependencies.mingw_x64-android_arm32 = \
libffi-3.2.1-mingw-w64-x86-64 libffi-3.2.1-mingw-w64-x86-64
quadruple.android_arm32 = arm-linux-androideabi quadruple.android_arm32 = arm-linux-androideabi
entrySelector.android_arm32 = -Wl,--defsym -Wl,main=Konan_main
clangFlags.android_arm32 = -cc1 -target-cpu arm7tdmi -emit-obj -disable-llvm-optzns -x ir -femulated-tls -mrelocation-model pic clangFlags.android_arm32 = -cc1 -target-cpu arm7tdmi -emit-obj -disable-llvm-optzns -x ir -femulated-tls -mrelocation-model pic
clangOptFlags.android_arm32 = -O3 -ffunction-sections clangOptFlags.android_arm32 = -O3 -ffunction-sections
linkerNoDebugFlags.android_arm32 = -Wl,-S linkerNoDebugFlags.android_arm32 = -Wl,-S
@@ -392,7 +382,6 @@ dependencies.mingw_x64-android_arm64 = \
libffi-3.2.1-mingw-w64-x86-64 libffi-3.2.1-mingw-w64-x86-64
quadruple.android_arm64 = aarch64-linux-android quadruple.android_arm64 = aarch64-linux-android
entrySelector.android_arm64 = -Wl,--defsym -Wl,main=Konan_main
clangFlags.android_arm64 = -cc1 -target-cpu cortex-a57 -emit-obj -disable-llvm-passes -x ir -femulated-tls -mrelocation-model pic clangFlags.android_arm64 = -cc1 -target-cpu cortex-a57 -emit-obj -disable-llvm-passes -x ir -femulated-tls -mrelocation-model pic
clangOptFlags.android_arm64 = -O3 -ffunction-sections clangOptFlags.android_arm64 = -O3 -ffunction-sections
clangNooptFlags.android_arm64 = -O1 clangNooptFlags.android_arm64 = -O1
@@ -421,7 +410,6 @@ dependencies.mingw_x64-android_x86 = \
libffi-3.2.1-mingw-w64-x86-64 libffi-3.2.1-mingw-w64-x86-64
quadruple.android_x86 = i686-linux-android quadruple.android_x86 = i686-linux-android
entrySelector.android_x86 = -Wl,--defsym -Wl,main=Konan_main
clangFlags.android_x86 = -cc1 -target-cpu i686 -emit-obj -disable-llvm-passes -x ir -femulated-tls -mrelocation-model pic clangFlags.android_x86 = -cc1 -target-cpu i686 -emit-obj -disable-llvm-passes -x ir -femulated-tls -mrelocation-model pic
clangOptFlags.android_x86 = -O3 -ffunction-sections clangOptFlags.android_x86 = -O3 -ffunction-sections
clangNooptFlags.android_x86 = -O1 clangNooptFlags.android_x86 = -O1
@@ -450,7 +438,6 @@ dependencies.mingw_x64-android_x64 = \
libffi-3.2.1-mingw-w64-x86-64 libffi-3.2.1-mingw-w64-x86-64
quadruple.android_x64 = x86_64-linux-android quadruple.android_x64 = x86_64-linux-android
entrySelector.android_x64 = -Wl,--defsym -Wl,main=Konan_main
clangFlags.android_x64 = -cc1 -target-cpu x86-64 -emit-obj -disable-llvm-passes -x ir -femulated-tls -mrelocation-model pic clangFlags.android_x64 = -cc1 -target-cpu x86-64 -emit-obj -disable-llvm-passes -x ir -femulated-tls -mrelocation-model pic
clangOptFlags.android_x64 = -O3 -ffunction-sections clangOptFlags.android_x64 = -O3 -ffunction-sections
clangNooptFlags.android_x64 = -O1 clangNooptFlags.android_x64 = -O1
@@ -494,7 +481,6 @@ linkerKonanFlags.mingw_x64 =-static-libgcc -static-libstdc++ \
-Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic \ -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic \
-Wl,--defsym,__cxa_demangle=Konan_cxa_demangle -Wl,--defsym,__cxa_demangle=Konan_cxa_demangle
linkerOptimizationFlags.mingw_x64 = -Wl,--gc-sections linkerOptimizationFlags.mingw_x64 = -Wl,--gc-sections
entrySelector.mingw_x64 = -Wl,--defsym,main=Konan_main
# Windows i686, based on mingw-w64. # Windows i686, based on mingw-w64.
targetToolchain.mingw_x64-mingw_x86 = msys2-mingw-w64-i686-gcc-7.4.0-clang-llvm-6.0.1 targetToolchain.mingw_x64-mingw_x86 = msys2-mingw-w64-i686-gcc-7.4.0-clang-llvm-6.0.1
@@ -532,7 +518,6 @@ linkerKonanFlags.mingw_x86 = -static-libgcc -static-libstdc++ \
-Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic \ -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic \
-Wl,--defsym,___cxa_demangle=_Konan_cxa_demangle -Wl,--defsym,___cxa_demangle=_Konan_cxa_demangle
linkerOptimizationFlags.mingw_x86 = -Wl,--gc-sections linkerOptimizationFlags.mingw_x86 = -Wl,--gc-sections
entrySelector.mingw_x86 = -Wl,--defsym,_main=_Konan_main
# WebAssembly 32-bit. # WebAssembly 32-bit.
targetToolchain.macos_x64-wasm32 = target-toolchain-3-macos-wasm targetToolchain.macos_x64-wasm32 = target-toolchain-3-macos-wasm