Implement -Xembed-bitcode and -Xembed-bitcode-marker
These options currently make the produced framework bitcode-friendly in release and debug environments correspondigly without embedding real bitcode.
This commit is contained in:
committed by
SvyatoslavScherbina
parent
af769d958e
commit
6cb4d0c241
@@ -50,6 +50,25 @@ framework("MyCustomFramework") {
|
||||
|
||||
</div>
|
||||
|
||||
### Q: How do I enable bitcode for my Kotlin framework?
|
||||
|
||||
A: Use either `-Xembed-bitcode` or `-Xembed-bitcode-marker` compiler option
|
||||
or matching Gradle DSL statement, i.e.
|
||||
|
||||
<div class="sample" markdown="1" theme="idea" mode="groovy">
|
||||
|
||||
```groovy
|
||||
framework("MyCustomFramework") {
|
||||
extraOpts '-Xembed-bitcode' // for release binaries
|
||||
// or '-Xembed-bitcode-marker' for debug binaries
|
||||
}
|
||||
```
|
||||
|
||||
These options have nearly the same effect as clang's `-fembed-bitcode`/`-fembed-bitcode-marker`
|
||||
and swiftc's `-embed-bitcode`/`-embed-bitcode-marker`.
|
||||
|
||||
</div>
|
||||
|
||||
### Q: Why do I see `InvalidMutabilityException`?
|
||||
|
||||
A: It likely happens, because you are trying to mutate a frozen object. An object can transfer to the
|
||||
|
||||
@@ -14,17 +14,14 @@ import org.jetbrains.kotlin.cli.common.CLITool
|
||||
import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
|
||||
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
|
||||
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
@@ -190,6 +187,8 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
})
|
||||
if (arguments.friendModules != null)
|
||||
put(FRIEND_MODULES, arguments.friendModules!!.split(File.pathSeparator).filterNot(String::isEmpty))
|
||||
|
||||
put(BITCODE_EMBEDDING_MODE, selectBitcodeEmbeddingMode(this, arguments, outputKind))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,5 +213,45 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectBitcodeEmbeddingMode(
|
||||
configuration: CompilerConfiguration,
|
||||
arguments: K2NativeCompilerArguments,
|
||||
outputKind: CompilerOutputKind
|
||||
): BitcodeEmbedding.Mode {
|
||||
|
||||
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(
|
||||
STRONG_WARNING,
|
||||
"'$flag' is only supported when producing frameworks, " +
|
||||
"but the compiler is producing ${outputKind.name.toLowerCase()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return when {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) = K2Native.main(args)
|
||||
|
||||
|
||||
@@ -94,6 +94,12 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
@Argument(value = "-Xdisable", deprecatedName = "--disable", valueDescription = "<Phase>", description = "Disable backend phase")
|
||||
var disablePhases: Array<String>? = null
|
||||
|
||||
@Argument(value = EMBED_BITCODE_FLAG, description = "Embed LLVM IR bitcode as data")
|
||||
var embedBitcode: Boolean = false
|
||||
|
||||
@Argument(value = EMBED_BITCODE_MARKER_FLAG, description = "Embed placeholder LLVM IR data as a marker")
|
||||
var embedBitcodeMarker: Boolean = false
|
||||
|
||||
@Argument(value = "-Xenable", deprecatedName = "--enable", valueDescription = "<Phase>", description = "Enable backend phase")
|
||||
var enablePhases: Array<String>? = null
|
||||
|
||||
@@ -153,3 +159,5 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
}
|
||||
}
|
||||
|
||||
const val EMBED_BITCODE_FLAG = "-Xembed-bitcode"
|
||||
const val EMBED_BITCODE_MARKER_FLAG = "-Xembed-bitcode-marker"
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
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 {
|
||||
|
||||
enum class Mode {
|
||||
NONE, MARKER, FULL
|
||||
}
|
||||
|
||||
internal fun getLinkerOptions(config: KonanConfig): List<String> = when (config.bitcodeEmbeddingMode) {
|
||||
Mode.NONE -> emptyList()
|
||||
Mode.MARKER -> listOf("-bitcode_bundle", "-bitcode_process_mode", "marker")
|
||||
Mode.FULL -> listOf("-bitcode_bundle")
|
||||
}
|
||||
|
||||
private val KonanConfig.bitcodeEmbeddingMode get() = configuration.get(KonanConfigKeys.BITCODE_EMBEDDING_MODE)!!.also {
|
||||
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
|
||||
}
|
||||
}
|
||||
+2
@@ -20,6 +20,8 @@ class KonanConfigKeys {
|
||||
= CompilerConfigurationKey.create("add debug information")
|
||||
val DISABLED_PHASES: CompilerConfigurationKey<List<String>>
|
||||
= CompilerConfigurationKey.create("disable backend phases")
|
||||
val BITCODE_EMBEDDING_MODE: CompilerConfigurationKey<BitcodeEmbedding.Mode>
|
||||
= CompilerConfigurationKey.create("bitcode embedding mode")
|
||||
val ENABLE_ASSERTIONS: CompilerConfigurationKey<Boolean>
|
||||
= CompilerConfigurationKey.create("enable runtime assertions in generated code")
|
||||
val ENABLED_PHASES: CompilerConfigurationKey<List<String>>
|
||||
|
||||
+1
@@ -183,6 +183,7 @@ internal class LinkStage(val context: Context, val phaser: PhaseManager) {
|
||||
libraries = linker.targetLibffi + linker.linkStaticLibraries(includedBinaries),
|
||||
linkerArgs = entryPointSelector +
|
||||
asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) +
|
||||
BitcodeEmbedding.getLinkerOptions(context.config) +
|
||||
libraryProvidedLinkerFlags + frameworkLinkerArgs,
|
||||
optimize = optimize, debug = debug, kind = linkerOutput,
|
||||
outputDsymBundle = context.config.outputFile + ".dSYM").forEach {
|
||||
|
||||
+2
@@ -383,6 +383,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
codegen.objCDataGenerator?.finishModule()
|
||||
|
||||
BitcodeEmbedding.processModule(context.llvm)
|
||||
|
||||
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
||||
appendLlvmUsed("llvm.compiler.used", context.llvm.compilerUsedGlobals)
|
||||
appendStaticInitializers()
|
||||
|
||||
@@ -2998,6 +2998,8 @@ if (isMac() && project.testTarget != 'wasm32') {
|
||||
if (!useCustomDist) {
|
||||
dependsOn ":${target}CrossDistRuntime", ':commonDistRuntime', ':distCompiler'
|
||||
}
|
||||
|
||||
extraOpts "-Xembed-bitcode-marker"
|
||||
}
|
||||
}
|
||||
swiftSources = ['framework/values/values.swift']
|
||||
@@ -3005,6 +3007,7 @@ if (isMac() && project.testTarget != 'wasm32') {
|
||||
|
||||
task testStdlibFramework(type: FrameworkTest) {
|
||||
frameworkName = 'Stdlib'
|
||||
fullBitcode = true
|
||||
konanArtifacts {
|
||||
framework(frameworkName, targets: [ target ]) {
|
||||
srcDir 'framework/stdlib'
|
||||
@@ -3013,6 +3016,8 @@ if (isMac() && project.testTarget != 'wasm32') {
|
||||
if (!useCustomDist) {
|
||||
dependsOn ":${target}CrossDistRuntime", ':commonDistRuntime', ':distCompiler'
|
||||
}
|
||||
|
||||
extraOpts "-Xembed-bitcode"
|
||||
}
|
||||
}
|
||||
swiftSources = ['framework/stdlib/stdlib.swift']
|
||||
|
||||
@@ -31,6 +31,9 @@ open class FrameworkTest : DefaultTask() {
|
||||
@Input
|
||||
lateinit var frameworkName: String
|
||||
|
||||
@Input
|
||||
var fullBitcode: Boolean = false
|
||||
|
||||
private val testOutput: String by lazy {
|
||||
project.file(project.property("testOutputFramework")!!).absolutePath
|
||||
}
|
||||
@@ -109,7 +112,8 @@ open class FrameworkTest : DefaultTask() {
|
||||
}
|
||||
|
||||
val args = listOf("-sdk", configs.absoluteTargetSysRoot, "-target", swiftTarget) +
|
||||
options + "-o" + output.toString() + sources
|
||||
options + "-o" + output.toString() + sources +
|
||||
if (fullBitcode) listOf("-embed-bitcode", "-Xlinker", "-bitcode_verify") else listOf("-embed-bitcode-marker")
|
||||
|
||||
val (stdOut, stdErr, exitCode) = runProcess(executor = localExecutor(project), executable = compiler, args = args)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user