diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt index 2e9d1a28ef1..c15805c94a2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt @@ -27,6 +27,7 @@ internal fun produceOutput(context: Context) { val config = context.config.configuration when (config.get(KonanConfigKeys.PRODUCE)) { + CompilerOutputKind.DYNAMIC, CompilerOutputKind.PROGRAM -> { val program = context.config.outputName val output = "$program.kt.bc" diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt index c1545df6ed0..8320bc87583 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt @@ -86,7 +86,8 @@ object KonanPhases { KonanPhase.SERIALIZER.enabled = (get(PRODUCE) == CompilerOutputKind.LIBRARY) KonanPhase.LINK_STAGE.enabled = - (get(PRODUCE) == CompilerOutputKind.PROGRAM) + (get(PRODUCE) == CompilerOutputKind.PROGRAM || + get(PRODUCE) == CompilerOutputKind.DYNAMIC) KonanPhase.TEST_PROCESSOR.enabled = getBoolean(GENERATE_TEST_RUNNER) 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 2c83ef178fd..f1bf77b42e0 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 @@ -32,10 +32,12 @@ internal abstract class PlatformFlags(val properties: KonanProperties) { val llvmLtoNooptFlags = properties.llvmLtoNooptFlags val llvmLtoOptFlags = properties.llvmLtoOptFlags val llvmLtoFlags = properties.llvmLtoFlags + val llvmLtoDynamicFlags = properties.llvmLtoDynamicFlags val entrySelector = properties.entrySelector val linkerOptimizationFlags = properties.linkerOptimizationFlags val linkerKonanFlags = properties.linkerKonanFlags val linkerDebugFlags = properties.linkerDebugFlags + val linkerDynamicFlags = properties.linkerDynamicFlags val llvmDebugOptFlags = properties.llvmDebugOptFlags val s2wasmFlags = properties.s2wasmFlags val targetToolchain = properties.absoluteTargetToolchain @@ -46,7 +48,7 @@ internal abstract class PlatformFlags(val properties: KonanProperties) { open val useCompilerDriverAsLinker: Boolean get() = false // TODO: refactor. abstract fun linkCommand(objectFiles: List, - executable: ExecutableFile, optimize: Boolean, debug: Boolean): List + executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): List open fun linkCommandSuffix(): List = emptyList() @@ -77,7 +79,7 @@ internal open class AndroidPlatform(distribution: Distribution) override fun filterStaticLibraries(binaries: List) = binaries.filter { it.isUnixStaticLib } - override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean): List { + override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): List { // liblog.so must be linked in, as we use its functionality in runtime. return mutableListOf(clang).apply{ add("-o") @@ -88,6 +90,7 @@ internal open class AndroidPlatform(distribution: Distribution) addAll(objectFiles) if (optimize) addAll(linkerOptimizationFlags) if (!debug) addAll(linkerDebugFlags) + if (dynamic) addAll(linkerDynamicFlags) addAll(linkerKonanFlags) } } @@ -110,7 +113,7 @@ internal open class MacOSBasedPlatform(distribution: Distribution) override fun filterStaticLibraries(binaries: List) = binaries.filter { it.isUnixStaticLib } - override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean): List { + override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): List { return mutableListOf(linker).apply { add("-demangle") addAll(listOf("-object_path_lto", "temporary.o", "-lto_library", libLTO)) @@ -120,6 +123,7 @@ internal open class MacOSBasedPlatform(distribution: Distribution) addAll(objectFiles) if (optimize) addAll(linkerOptimizationFlags) if (!debug) addAll(linkerDebugFlags) + if (dynamic) addAll(linkerDynamicFlags) addAll(linkerKonanFlags) add("-lSystem") } @@ -144,7 +148,7 @@ internal open class LinuxBasedPlatform(val distribution: Distribution) override fun filterStaticLibraries(binaries: List) = binaries.filter { it.isUnixStaticLib } - override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean): List { + override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): List { // TODO: Can we extract more to the konan.properties? return mutableListOf(linker).apply { addAll(listOf("--sysroot=${targetSysRoot}", @@ -162,6 +166,7 @@ internal open class LinuxBasedPlatform(val distribution: Distribution) 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", @@ -181,12 +186,13 @@ internal open class MingwPlatform(distribution: Distribution) override fun filterStaticLibraries(binaries: List) = binaries.filter { it.isWindowsStaticLib || it.isUnixStaticLib } - override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean): List { + 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) } } @@ -203,7 +209,7 @@ internal open class WasmPlatform(distribution: Distribution) override fun filterStaticLibraries(binaries: List) = emptyList() - override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean): List { + override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): List { //No link stage for WASM yet, just give '.wasm' as output. return mutableListOf("/bin/cp", objectFiles.single(), executable) @@ -233,6 +239,7 @@ internal class LinkStage(val context: Context) { private val optimize = config.get(KonanConfigKeys.OPTIMIZATION) ?: false private val debug = config.get(KonanConfigKeys.DEBUG) ?: false + private val dynamic = config.get(KonanConfigKeys.PRODUCE) == CompilerOutputKind.DYNAMIC private val nomain = config.get(KonanConfigKeys.NOMAIN) ?: false private val emitted = context.bitcodeFileName private val libraries = context.llvm.librariesToLink @@ -251,6 +258,7 @@ internal class LinkStage(val context: Context) { debug -> command.addNonEmpty(platform.llvmDebugOptFlags) else -> command.addNonEmpty(platform.llvmLtoNooptFlags) } + command.addNonEmpty(platform.llvmLtoDynamicFlags) command.addNonEmpty(files) runTool(*command.toTypedArray()) @@ -322,7 +330,7 @@ internal class LinkStage(val context: Context) { private fun link(objectFiles: List, includedBinaries: List, libraryProvidedLinkerFlags: List): ExecutableFile? { val executable = context.config.outputFile - val linkCommand = platform.linkCommand(objectFiles, executable, optimize, debug) + + val linkCommand = platform.linkCommand(objectFiles, executable, optimize, debug, dynamic) + platform.targetLibffi + asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) + entryPointSelector + diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt index 066887e1d37..9086e6313c3 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.CompilerOutputKind.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe @@ -36,7 +37,8 @@ import org.jetbrains.kotlin.utils.alwaysTrue internal fun findMainEntryPoint(context: Context): FunctionDescriptor? { val config = context.config.configuration - if (config.get(KonanConfigKeys.PRODUCE) != CompilerOutputKind.PROGRAM) return null + if (config.get(KonanConfigKeys.PRODUCE) != PROGRAM && + config.get(KonanConfigKeys.PRODUCE) != DYNAMIC) return null val entryPoint = FqName(config.get(KonanConfigKeys.ENTRY) ?: if (context.shouldGenerateTestRunner()) testEntryName else defaultEntryName) diff --git a/backend.native/konan.properties b/backend.native/konan.properties index a2adf2f1e25..0f7420039cc 100644 --- a/backend.native/konan.properties +++ b/backend.native/konan.properties @@ -38,9 +38,11 @@ libffiDir.osx = libffi-3.2.1-2-darwin-macos llvmLtoFlags.osx = llvmLtoOptFlags.osx = -O3 -function-sections llvmLtoNooptFlags.osx = -O1 +llvmLtoDynamicFlags.osx = -relocation-model=pic linkerKonanFlags.osx = -lc++ -lobjc linkerOptimizationFlags.osx = -dead_strip linkerDebugFlags.osx = -S +linkerDynamicFlags.osx = -S -dylib osVersionMinFlagLd.osx = -macosx_version_min osVersionMinFlagClang.osx = -mmacosx-version-min osVersionMin.osx = 10.11 @@ -105,10 +107,12 @@ libGcc.linux = ../../lib/gcc/x86_64-unknown-linux-gnu/4.8.5 llvmLtoFlags.linux = llvmLtoOptFlags.linux = -O3 -function-sections llvmLtoNooptFlags.linux = -O1 +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 +linkerDynamicFlags.linux = -shared pluginOptimizationFlags.linux = -plugin-opt=mcpu=x86-64 -plugin-opt=O3 dynamicLinker.linux = /lib64/ld-linux-x86-64.so.2 entrySelector.linux = --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 804d15af927..8267920745b 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 @@ -38,10 +38,12 @@ class KonanProperties(val target: KonanTarget, val properties: Properties, val b val llvmLtoNooptFlags get() = targetList("llvmLtoNooptFlags") val llvmLtoOptFlags get() = targetList("llvmLtoOptFlags") val llvmLtoFlags get() = targetList("llvmLtoFlags") + val llvmLtoDynamicFlags get() = targetList("llvmLtoDynamicFlags") val entrySelector get() = targetList("entrySelector") val linkerOptimizationFlags get() = targetList("linkerOptimizationFlags") val linkerKonanFlags get() = targetList("linkerKonanFlags") val linkerDebugFlags get() = targetList("linkerDebugFlags") + val linkerDynamicFlags get() = targetList("linkerDynamicFlags") val llvmDebugOptFlags get() = targetList("llvmDebugOptFlags") val s2wasmFlags get() = targetList("s2wasmFlags") diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt index 09e3e2f13fe..04e69dfe08e 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt @@ -61,7 +61,7 @@ enum class CompilerOutputKind { override fun suffix(target: KonanTarget?) = ".${target!!.family.exeSuffix}" }, DYNAMIC { - override fun suffix(target: KonanTarget?) = ".${target!!.family.dynamicSuffix!!}" + override fun suffix(target: KonanTarget?) = ".${target!!.family.dynamicSuffix}" }, LIBRARY { override fun suffix(target: KonanTarget?) = ".klib"