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 729626443d4..8730b7e7fe6 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 @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.backend.konan import llvm.* import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary +import org.jetbrains.kotlin.backend.konan.llvm.Llvm +import org.jetbrains.kotlin.backend.konan.llvm.embedLlvmLinkOptions import org.jetbrains.kotlin.backend.konan.llvm.parseBitcodeFile import org.jetbrains.kotlin.konan.CURRENT import org.jetbrains.kotlin.konan.KonanAbiVersion @@ -74,6 +76,10 @@ internal fun produceOutput(context: Context) { parseAndLinkBitcodeFile(context.llvmModule!!, library) } + if (produce == CompilerOutputKind.FRAMEWORK && context.config.produceStaticFramework) { + embedAppleLinkerOptionsToBitcode(context.llvm, context.config) + } + LLVMWriteBitcodeToFile(context.llvmModule!!, output) } CompilerOutputKind.LIBRARY -> { @@ -121,3 +127,24 @@ private fun parseAndLinkBitcodeFile(llvmModule: LLVMModuleRef, path: String) { throw Error("failed to link $path") // TODO: retrieve error message from LLVM. } } + +private fun embedAppleLinkerOptionsToBitcode(llvm: Llvm, config: KonanConfig) { + fun findEmbeddableOptions(options: List): List> { + val result = mutableListOf>() + val iterator = options.iterator() + loop@while (iterator.hasNext()) { + val option = iterator.next() + result += when { + option.startsWith("-l") -> listOf(option) + option == "-framework" && iterator.hasNext() -> listOf(option, iterator.next()) + else -> break@loop // Ignore the rest. + } + } + return result + } + + val optionsToEmbed = findEmbeddableOptions(config.platform.configurables.linkerKonanFlags) + + llvm.nativeDependenciesToLink.flatMap { findEmbeddableOptions(it.linkerOpts) } + + embedLlvmLinkOptions(llvm.llvmModule, optionsToEmbed) +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 4e7c8d73349..19f82e9aa95 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -59,6 +59,8 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration internal val produce get() = configuration.get(KonanConfigKeys.PRODUCE)!! + internal val produceStaticFramework get() = configuration.getBoolean(KonanConfigKeys.STATIC_FRAMEWORK) + val outputFiles = OutputFiles(configuration.get(KonanConfigKeys.OUTPUT), target, produce) val tempFiles = TempFiles(outputFiles.outputName, configuration.get(KonanConfigKeys.TEMPORARY_FILES_DIR)) 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 72ed02ddcee..cb0f31e6493 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 @@ -18,7 +18,7 @@ typealias ExecutableFile = String private fun determineLinkerOutput(context: Context): LinkerOutputKind = when (context.config.produce) { CompilerOutputKind.FRAMEWORK -> { - val staticFramework = context.config.configuration.getBoolean(KonanConfigKeys.STATIC_FRAMEWORK) + val staticFramework = context.config.produceStaticFramework if (staticFramework) LinkerOutputKind.STATIC_LIBRARY else LinkerOutputKind.DYNAMIC_LIBRARY } CompilerOutputKind.DYNAMIC -> LinkerOutputKind.DYNAMIC_LIBRARY diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmLinkOptions.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmLinkOptions.kt new file mode 100644 index 00000000000..d3e78578e91 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmLinkOptions.kt @@ -0,0 +1,16 @@ +/* + * 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.backend.konan.llvm + +import llvm.LLVMAddNamedMetadataOperand +import llvm.LLVMModuleRef + +fun embedLlvmLinkOptions(module: LLVMModuleRef, options: List>) { + options.forEach { + val node = node(*it.map { it.mdString() }.toTypedArray()) + LLVMAddNamedMetadataOperand(module, "llvm.linker.options", node) + } +} \ No newline at end of file