diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt index ecbf9de86d8..a305bdda131 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt @@ -21,6 +21,8 @@ import java.lang.ProcessBuilder.Redirect import org.jetbrains.kotlin.konan.file.* import org.jetbrains.kotlin.konan.properties.* import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.backend.konan.util.listConstructor +import org.jetbrains.kotlin.backend.konan.util.If typealias BitcodeFile = String typealias ObjectFile = String @@ -36,7 +38,7 @@ internal abstract class PlatformFlags(val properties: KonanProperties) { val entrySelector = properties.entrySelector val linkerOptimizationFlags = properties.linkerOptimizationFlags val linkerKonanFlags = properties.linkerKonanFlags - val linkerDebugFlags = properties.linkerDebugFlags + val linkerNoDebugFlags = properties.linkerNoDebugFlags val linkerDynamicFlags = properties.linkerDynamicFlags val llvmDebugOptFlags = properties.llvmDebugOptFlags val s2wasmFlags = properties.s2wasmFlags @@ -89,7 +91,7 @@ internal open class AndroidPlatform(distribution: Distribution) add("-llog") addAll(objectFiles) if (optimize) addAll(linkerOptimizationFlags) - if (!debug) addAll(linkerDebugFlags) + if (!debug) addAll(linkerNoDebugFlags) if (dynamic) addAll(linkerDynamicFlags) addAll(linkerKonanFlags) } @@ -122,7 +124,7 @@ internal open class MacOSBasedPlatform(distribution: Distribution) addAll(listOf("-syslibroot", targetSysRoot, "-o", executable)) addAll(objectFiles) if (optimize) addAll(linkerOptimizationFlags) - if (!debug) addAll(linkerDebugFlags) + if (!debug) addAll(linkerNoDebugFlags) if (dynamic) addAll(linkerDynamicFlags) addAll(linkerKonanFlags) add("-lSystem") @@ -134,7 +136,6 @@ internal open class MacOSBasedPlatform(distribution: Distribution) open fun dsymutilDryRunVerboseCommand(executable: ExecutableFile): List = listOf(dsymutil, "-dump-debug-map" ,executable) } - internal open class LinuxBasedPlatform(val distribution: Distribution) : PlatformFlags(distribution.targetProperties) { @@ -149,30 +150,46 @@ internal open class LinuxBasedPlatform(val distribution: Distribution) = binaries.filter { it.isUnixStaticLib } override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): List { + val isMips = (distribution.target == KonanTarget.LINUX_MIPS32 || + distribution.target == KonanTarget.LINUX_MIPSEL32) // TODO: Can we extract more to the konan.properties? - return mutableListOf(linker).apply { - addAll(listOf("--sysroot=${targetSysRoot}", - "-export-dynamic", "-z", "relro", - "--build-id", "--eh-frame-hdr", // "-m", "elf_x86_64", - "-dynamic-linker", propertyTargetString("dynamicLinker"), - "-o", executable, - "${targetSysRoot}/usr/lib64/crt1.o", - "${targetSysRoot}/usr/lib64/crti.o", "${libGcc}/crtbegin.o", - "-L${llvmLib}", "-L${libGcc}")) - if (distribution.target != KonanTarget.LINUX_MIPS32 && distribution.target != KonanTarget.LINUX_MIPSEL32) add("--hash-style=gnu") // MIPS doesn't support hash-style=gnu - addAll(specificLibs) - addAll(listOf("-L${targetSysRoot}/../lib", "-L${targetSysRoot}/lib", "-L${targetSysRoot}/usr/lib")) - if (optimize) addAll(listOf("-plugin", "$llvmLib/LLVMgold.so") + pluginOptimizationFlags) - addAll(objectFiles) - if (optimize) addAll(linkerOptimizationFlags) - if (!debug) addAll(linkerDebugFlags) - if (dynamic) addAll(linkerDynamicFlags) - addAll(linkerKonanFlags) - addAll(listOf("-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed", - "-lc", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed", - "${libGcc}/crtend.o", - "${targetSysRoot}/usr/lib64/crtn.o")) - } + return listConstructor( + linker, + "--sysroot=${targetSysRoot}", + "-export-dynamic", "-z", "relro", + "--build-id", "--eh-frame-hdr", // "-m", "elf_x86_64", + "-dynamic-linker", propertyTargetString("dynamicLinker"), + "-o", executable, + If (!dynamic, + "${targetSysRoot}/usr/lib64/crt1.o"), + "${targetSysRoot}/usr/lib64/crti.o", + if (dynamic) + "${libGcc}/crtbeginS.o" + else + "${libGcc}/crtbegin.o", + "-L${llvmLib}", "-L${libGcc}", + If (!isMips, // MIPS doesn't support hash-style=gnu + "--hash-style=gnu"), + specificLibs, + "-L${targetSysRoot}/../lib", "-L${targetSysRoot}/lib", "-L${targetSysRoot}/usr/lib", + If (optimize, + "-plugin", "$llvmLib/LLVMgold.so", + pluginOptimizationFlags, + linkerOptimizationFlags), + If (!debug, + linkerNoDebugFlags), + If (dynamic, + linkerDynamicFlags), + objectFiles, + linkerKonanFlags, + "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed", + "-lc", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed", + if (dynamic) + "${libGcc}/crtendS.o" + else + "${libGcc}/crtend.o", + "${targetSysRoot}/usr/lib64/crtn.o" + ) } } @@ -187,13 +204,17 @@ internal open class MingwPlatform(distribution: Distribution) = binaries.filter { it.isWindowsStaticLib || it.isUnixStaticLib } override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): List { - return mutableListOf(linker).apply { - addAll(listOf("-o", executable)) - addAll(objectFiles) - if (optimize) addAll(linkerOptimizationFlags) - if (!debug) addAll(linkerDebugFlags) - if (dynamic) addAll(linkerDynamicFlags) - } + return listConstructor( + linker, + "-o", executable, + objectFiles, + If (optimize, + linkerOptimizationFlags), + If (!debug, + linkerNoDebugFlags), + If (dynamic, + linkerDynamicFlags) + ) } override fun linkCommandSuffix() = linkerKonanFlags diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt index 4c25dd27c1c..158ce66c4ea 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt @@ -48,11 +48,8 @@ class Runtime(bitcodeFile: String) { // TODO: deduce TLS model from explicit config parameter. val tlsMode by lazy { - when { - target.indexOf("android") != -1 -> LLVMThreadLocalMode.LLVMGeneralDynamicTLSModel - target.indexOf("wasm") != -1 -> LLVMThreadLocalMode.LLVMNotThreadLocal - else -> LLVMThreadLocalMode.LLVMLocalExecTLSModel - } + if (target.indexOf("wasm") != -1) LLVMThreadLocalMode.LLVMNotThreadLocal + else LLVMThreadLocalMode.LLVMGeneralDynamicTLSModel } val dataLayout = LLVMGetDataLayout(llvmModule)!!.toKString() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/util.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/util.kt index 1170f0a8047..6bf93c570d5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/util.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/util.kt @@ -46,3 +46,35 @@ fun String.removeSuffixIfPresent(suffix: String) = if (this.endsWith(suffix)) this.dropLast(suffix.length) else this fun Lazy.getValueOrNull(): T? = if (isInitialized()) value else null + +// The listConstructor() and If functions are convenient to construct +// command lines having a bunch of elements, lists and conditions. +// Use them like +// +// listConstructor( +// anElement1, +// If (condition1, +// element2), +// aList1, +// If (condition2, +// alist3, +// alist4) +// ) + +internal fun listConstructor(vararg elements: Any): List { + val result = mutableListOf() + for (element in elements) { + when (element) { + null -> {} + is String -> result.add(element) + is List<*> -> result.addAll(element as List) + else -> error("Unexpected element of listConstructor: $element") + } + } + return result +} + +internal fun If (condition: Boolean, vararg elements: Any): List = + if (condition) listConstructor(*elements) else emptyList() + + diff --git a/backend.native/konan.properties b/backend.native/konan.properties index 5e3e8df45a2..9afd07006ab 100644 --- a/backend.native/konan.properties +++ b/backend.native/konan.properties @@ -41,7 +41,7 @@ llvmLtoNooptFlags.osx = -O1 llvmLtoDynamicFlags.osx = -relocation-model=pic linkerKonanFlags.osx = -lc++ -lobjc -framework Foundation linkerOptimizationFlags.osx = -dead_strip -linkerDebugFlags.osx = -S +linkerNoDebugFlags.osx = -S linkerDynamicFlags.osx = -S -dylib osVersionMinFlagLd.osx = -macosx_version_min osVersionMinFlagClang.osx = -mmacosx-version-min @@ -64,7 +64,7 @@ targetSysRoot.ios = target-sysroot-2-darwin-ios libffiDir.ios = libffi-3.2.1-2-darwin-ios llvmLtoFlags.ios = llvmLtoOptFlags.ios = -O3 -function-sections -linkerDebugFlags.ios = -S +linkerNoDebugFlags.ios = -S linkerDynamicFlags.ios = -S -dylib llvmLtoNooptFlags.ios = -O1 llvmLtoDynamicFlags.ios = -relocation-model=pic @@ -91,7 +91,7 @@ llvmLtoNooptFlags.ios_sim = -O1 llvmLtoDynamicFlags.ios_sim = -relocation-model=pic linkerKonanFlags.ios_sim = -lc++ -lobjc -framework Foundation -sdk_version 10.2 linkerOptimizationFlags.ios_sim = -dead_strip -linkerDebugFlags.ios_sim = -S +linkerNoDebugFlags.ios_sim = -S linkerDynamicFlags.ios_sim = -S -dylib osVersionMinFlagLd.ios_sim = -ios_simulator_version_min osVersionMinFlagClang.ios_sim = -mios-simulator-version-min @@ -114,7 +114,7 @@ llvmLtoDynamicFlags.linux = -relocation-model=pic llvmLlcFlags.linux = -march=x86-64 linkerKonanFlags.linux = -Bstatic -lstdc++ -Bdynamic -ldl -lm -lpthread linkerOptimizationFlags.linux = --gc-sections -linkerDebugFlags.linux = -S +linkerNoDebugFlags.linux = -S linkerDynamicFlags.linux = -shared pluginOptimizationFlags.linux = -plugin-opt=mcpu=x86-64 -plugin-opt=O3 dynamicLinker.linux = /lib64/ld-linux-x86-64.so.2 @@ -137,7 +137,8 @@ dependencies.linux-raspberrypi = \ quadruple.raspberrypi = armv6-unknown-linux-gnueabihf entrySelector.raspberrypi = --defsym main=Konan_main -linkerDebugFlags.raspberrypi = -S +linkerNoDebugFlags.raspberrypi = -S +linkerDynamicFlags.raspberrypi = -shared linkerOptimizationFlags.raspberrypi = --gc-sections targetSysRoot.raspberrypi = target-sysroot-1-raspberrypi # We could reuse host toolchain here. @@ -166,6 +167,7 @@ dependencies.linux-linux_mips32 = \ quadruple.linux_mips32 = mips-unknown-linux-gnu entrySelector.linux_mips32 = --defsym main=Konan_main linkerOptimizationFlags.linux_mips32 = --gc-sections +linkerDynamicFlags.linux_mips32 = -shared targetSysRoot.linux_mips32 = target-sysroot-2-mips # We could reuse host toolchain here. libffiDir.linux_mips32 = libffi-3.2.1-2-linux-mips @@ -190,6 +192,7 @@ dependencies.linux-linux_mipsel32 = \ quadruple.linux_mipsel32 = mipsel-unknown-linux-gnu entrySelector.linux_mipsel32 = --defsym main=Konan_main linkerOptimizationFlags.linux_mipsel32 = --gc-sections +linkerDynamicFlags.linux_mipsel32 = -shared targetSysRoot.linux_mipsel32 = target-sysroot-2-mipsel # We could reuse host toolchain here. libffiDir.linux_mipsel32 = libffi-3.2.1-2-linux-mipsel @@ -222,7 +225,7 @@ quadruple.android_arm32 = arm-linux-androideabi entrySelector.android_arm32 = -Wl,--defsym -Wl,main=Konan_main llvmLtoFlags.android_arm32 = -emulated-tls -relocation-model=pic llvmLtoOptFlags.android_arm32 = -O3 -function-sections -linkerDebugFlags.android_arm32 = -Wl,-S +linkerNoDebugFlags.android_arm32 = -Wl,-S llvmLtoNooptFlags.android_arm32 = -O1 targetSysRoot.android_arm32 = target-sysroot-21-android_arm32 libffiDir.android_arm32 = libffi-3.2.1-2-android_arm32 @@ -249,7 +252,7 @@ llvmLtoFlags.android_arm64 = -emulated-tls -relocation-model=pic targetSysRoot.android_arm64 = target-sysroot-21-android_arm64 libffiDir.android_arm64 = libffi-3.2.1-2-android_arm64 linkerKonanFlags.android_arm64 = -lm -latomic -lstdc++ -landroid -linkerDebugFlags.android_arm64 = -Wl,-S +linkerNoDebugFlags.android_arm64 = -Wl,-S # Windows x86-64, based on mingw-w64. llvmHome.mingw = msys2-mingw-w64-x86_64-gcc-7.2.0-clang-llvm-5.0.0-windows-x86-64 @@ -261,7 +264,8 @@ libffiDir.mingw = libffi-3.2.1-mingw-w64-x86-64 llvmLtoFlags.mingw = llvmLtoOptFlags.mingw = -O3 -function-sections llvmLtoNooptFlags.mingw = -O1 -linkerDebugFlags.mingw = -Wl,-S +linkerNoDebugFlags.mingw = -Wl,-S +linkerDynamicFlags.mingw = -shared linkerKonanFlags.mingw =-static-libgcc -static-libstdc++ -Xclang -flto-visibility-public-std -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic linkerOptimizationFlags.mingw = -Wl,--gc-sections entrySelector.mingw = -Wl,--defsym,main=Konan_main diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanProperties.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanProperties.kt index 2df7a8aa47d..950a4289a5d 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanProperties.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanProperties.kt @@ -42,7 +42,7 @@ class KonanProperties(val target: KonanTarget, val properties: Properties, val b val entrySelector get() = targetList("entrySelector") val linkerOptimizationFlags get() = targetList("linkerOptimizationFlags") val linkerKonanFlags get() = targetList("linkerKonanFlags") - val linkerDebugFlags get() = targetList("linkerDebugFlags") + val linkerNoDebugFlags get() = targetList("linkerNoDebugFlags") val linkerDynamicFlags get() = targetList("linkerDynamicFlags") val llvmDebugOptFlags get() = targetList("llvmDebugOptFlags") val s2wasmFlags get() = targetList("s2wasmFlags")