Embed some linker options to static frameworks (#2828)

This commit is contained in:
SvyatoslavScherbina
2019-03-29 12:10:18 +03:00
committed by GitHub
parent 6bb4171c60
commit ed44620814
4 changed files with 46 additions and 1 deletions
@@ -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<String>): List<List<String>> {
val result = mutableListOf<List<String>>()
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)
}
@@ -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))
@@ -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
@@ -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<List<String>>) {
options.forEach {
val node = node(*it.map { it.mdString() }.toTypedArray())
LLVMAddNamedMetadataOperand(module, "llvm.linker.options", node)
}
}