Different extensions (and KonanTarget communalization). (#665)

This commit is contained in:
alexander-gorshenev
2017-06-19 12:45:57 +03:00
committed by Nikolay Igotti
parent c57ad51fc7
commit d3c24bb387
51 changed files with 419 additions and 245 deletions
+5 -1
View File
@@ -57,7 +57,10 @@ sourceSets {
srcDir 'compiler/ir/backend.native/src/'
srcDir 'build/renamed/source/proto/compiler/java'
}
kotlin.srcDir 'compiler/ir/backend.native/src/'
kotlin {
srcDir 'compiler/ir/backend.native/src/'
srcDir "${rootProject.projectDir}/shared/src/main/kotlin"
}
}
cli_bc {
java.srcDir 'cli.bc/src'
@@ -130,6 +133,7 @@ dependencies {
compilerCompile kotlinCompilerModule
compilerCompile kotlinNativeInterop['llvm'].configuration
compilerCompile kotlinNativeInterop['hash'].configuration
compilerCompile project(':shared')
cli_bcCompile "org.jetbrains.kotlin:kotlin-runtime:$kotlin_version"
cli_bcCompile sourceSets.compiler.output
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.cli.bc
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.CompilerOutputKind.*
import org.jetbrains.kotlin.backend.konan.util.profile
import org.jetbrains.kotlin.backend.konan.util.suffixIfNot
import org.jetbrains.kotlin.backend.konan.util.removeSuffixIfPresent
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.CLITool
import org.jetbrains.kotlin.cli.common.ExitCode
@@ -31,15 +28,16 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.config.addKotlinSourceRoots
import org.jetbrains.kotlin.konan.target.*
import java.util.*
import kotlin.reflect.KFunction
// TODO: Don't use reflection?
private fun maybeExecuteHelper(configuration: CompilerConfiguration) {
private fun maybeExecuteHelper(targetName: String) {
try {
val kClass = Class.forName("org.jetbrains.kotlin.konan.Helper0").kotlin
val ctor = kClass.constructors.single() as KFunction<Runnable>
val distribution = Distribution(configuration)
val distribution = Distribution(TargetManager(targetName))
val result = ctor.call(
distribution.dependenciesDir,
distribution.properties.properties,
@@ -109,18 +107,10 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
// TODO: Collect all the explicit file names into an object
// and teach the compiler to work with temporaries and -save-temps.
arguments.outputName ?.let { put(OUTPUT, it) }
val outputKind = CompilerOutputKind.valueOf(
(arguments.produce ?: "program").toUpperCase())
put(PRODUCE, outputKind)
val suffix = outputKind.suffix
val output = arguments.outputFile?.removeSuffixIfPresent(suffix)
?: outputKind.name.toLowerCase()
put(OUTPUT_NAME, output)
put(OUTPUT_FILE, output.suffixIfNot(outputKind.suffix))
// This is a decision we could change
put(CommonConfigurationKeys.MODULE_NAME, output)
put(ABI_VERSION, 1)
arguments.mainPackage ?.let{ put(ENTRY, it) }
@@ -154,7 +144,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
}
}
maybeExecuteHelper(configuration)
maybeExecuteHelper(arguments.target ?: "host")
}
override fun createArguments(): K2NativeCompilerArguments {
@@ -54,13 +54,13 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
@field:Argument(value = "-opt", description = "Enable optimizations during compilation")
@JvmField var optimization: Boolean = false
@field:Argument(value = "-output", shortName = "-o", valueDescription = "<path>", description = "Output file path")
@JvmField var outputFile: String? = null
@field:Argument(value = "-output", shortName = "-o", valueDescription = "<name>", description = "Output name")
@JvmField var outputName: String? = null
@field:Argument(value = "-entry", shortName = "-e", valueDescription = "<name>", description = "Qualified entry point name")
@JvmField var mainPackage: String? = null
@field:Argument(value = "-produce", shortName = "-p", valueDescription = "{program|library|bitcode}", description = "Produce either .kexe, .klib or a .bc file.")
@field:Argument(value = "-produce", shortName = "-p", valueDescription = "{program|library|bitcode}", description = "Specify output file kind")
@JvmField var produce: String? = null
@field:Argument(value = "-properties", valueDescription = "<path>", description = "Override standard 'konan.properties' location")
@@ -16,16 +16,17 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.config.CompilerConfiguration
import java.io.File
import org.jetbrains.kotlin.konan.target.*
class Distribution(val config: CompilerConfiguration) {
class Distribution(val targetManager: TargetManager,
val propertyFileOverride: String? = null,
val runtimeFileOverride: String? = null) {
val targetManager = TargetManager(config)
val target = targetManager.currentName
val hostSuffix = targetManager.hostSuffix()
val hostTargetSuffix = targetManager.hostTargetSuffix()
val targetSuffix = targetManager.targetSuffix()
val targetName = targetManager.targetName
val hostSuffix = targetManager.hostSuffix
val hostTargetSuffix = targetManager.hostTargetSuffix
val targetSuffix = targetManager.targetSuffix
private fun findUserHome() = File(System.getProperty("user.home")).absolutePath
val userHome = findUserHome()
@@ -38,8 +39,7 @@ class Distribution(val config: CompilerConfiguration) {
}
val konanHome = findKonanHome()
val propertyFile = config.get(KonanConfigKeys.PROPERTY_FILE)
?: "$konanHome/konan/konan.properties"
val propertyFile = propertyFileOverride ?: "$konanHome/konan/konan.properties"
val properties = KonanProperties(propertyFile)
val klib = "$konanHome/klib"
@@ -48,8 +48,7 @@ class Distribution(val config: CompilerConfiguration) {
val dependencies = properties.propertyList("dependencies.$hostTargetSuffix")
val stdlib = "$klib/stdlib"
val runtime = config.get(KonanConfigKeys.RUNTIME_FILE)
?: "$stdlib/targets/$target/native/runtime.bc"
val runtime = runtimeFileOverride ?: "$stdlib/targets/${targetName}/native/runtime.bc"
val llvmHome = "$dependenciesDir/${properties.propertyString("llvmHome.$hostSuffix")}"
val hostSysRoot = "$dependenciesDir/${properties.propertyString("targetSysRoot.$hostSuffix")}"
@@ -21,18 +21,39 @@ import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
import org.jetbrains.kotlin.backend.konan.library.SplitLibraryReader
import org.jetbrains.kotlin.backend.konan.library.KonanLibrarySearchPathResolver
import org.jetbrains.kotlin.backend.konan.util.profile
import org.jetbrains.kotlin.backend.konan.util.suffixIfNot
import org.jetbrains.kotlin.backend.konan.util.removeSuffixIfPresent
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.backend.konan.util.File
import org.jetbrains.kotlin.konan.target.*
import org.jetbrains.kotlin.konan.target.TargetManager.*
import org.jetbrains.kotlin.konan.target.CompilerOutputKind.*
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
val moduleId: String
get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
internal val targetManager = TargetManager(
configuration.get(KonanConfigKeys.TARGET))
internal val targetManager = TargetManager(configuration)
internal val distribution = Distribution(configuration)
init {
val target = targetManager.target
if (!target.enabled) {
error("Target $target is not available on the ${TargetManager.host} host")
}
}
internal val distribution = Distribution(targetManager,
configuration.get(KonanConfigKeys.PROPERTY_FILE),
configuration.get(KonanConfigKeys.RUNTIME_FILE))
private val produce = configuration.get(KonanConfigKeys.PRODUCE)!!
private val suffix = produce.suffix(targetManager.target)
val outputName = configuration.get(KonanConfigKeys.OUTPUT)?.removeSuffixIfPresent(suffix) ?: produce.name.toLowerCase()
val outputFile = outputName.suffixIfNot(produce.suffix(targetManager.target))
val moduleId: String
// This is a decision we could change
get() = outputName
private val libraryNames: List<String>
get() {
@@ -51,7 +72,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
internal val libraries: List<KonanLibraryReader> by lazy {
val currentAbiVersion = configuration.get(KonanConfigKeys.ABI_VERSION)!!
val target = targetManager.currentName
val target = targetManager.targetName
// Here we have chosen a particular KonanLibraryReader implementation.
librariesFound.map{it -> SplitLibraryReader(it, currentAbiVersion, target)}
}
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
class KonanConfigKeys {
companion object {
@@ -56,9 +57,7 @@ class KonanConfigKeys {
= CompilerConfigurationKey.create("don't the library into a klib file")
val OPTIMIZATION: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("optimized compilation")
val OUTPUT_FILE: CompilerConfigurationKey<String>
= CompilerConfigurationKey.create("final executable file path")
val OUTPUT_NAME: CompilerConfigurationKey<String>
val OUTPUT: CompilerConfigurationKey<String>
= CompilerConfigurationKey.create("program or library name")
val PRINT_BITCODE: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("print bitcode")
@@ -95,8 +94,3 @@ class KonanConfigKeys {
}
}
enum class CompilerOutputKind(val suffix: String) {
PROGRAM(".kexe"),
LIBRARY(".klib"),
BITCODE(".bc")
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.backend.konan.ir.ModuleIndex
import org.jetbrains.kotlin.backend.konan.llvm.emitLLVM
import org.jetbrains.kotlin.backend.konan.llvm.produceOutput
import org.jetbrains.kotlin.backend.konan.serialization.KonanSerializationUtil
import org.jetbrains.kotlin.backend.konan.serialization.markBackingFields
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
@@ -108,6 +109,7 @@ public fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEn
}
phaser.phase(KonanPhase.BITCODE) {
emitLLVM(context)
produceOutput(context)
}
// We always verify bitcode to prevent hard to debug bugs.
context.verifyBitCode()
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.util.*
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
enum class KonanPhase(val description: String,
vararg prerequisite: KonanPhase,
@@ -1,124 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.config.CompilerConfiguration
enum class KonanTarget(val suffix: String, var enabled: Boolean = false) {
ANDROID_ARM32("android_arm32"),
ANDROID_ARM64("android_arm64"),
IPHONE("ios"),
IPHONE_SIM("ios_sim"),
LINUX("linux"),
MINGW("mingw"),
MACBOOK("osx"),
RASPBERRYPI("raspberrypi")
}
class TargetManager(val userRequest: String? = null) {
constructor(config: CompilerConfiguration) : this(config.get(KonanConfigKeys.TARGET))
val targets = KonanTarget.values().associate{ it.name.toLowerCase() to it }
val current = determineCurrent()
val currentName
get() = current.name.toLowerCase()
init {
when (host) {
KonanTarget.LINUX -> {
KonanTarget.LINUX.enabled = true
KonanTarget.RASPBERRYPI.enabled = true
KonanTarget.ANDROID_ARM32.enabled = true
KonanTarget.ANDROID_ARM64.enabled = true
}
KonanTarget.MINGW -> {
KonanTarget.MINGW.enabled = true
}
KonanTarget.MACBOOK -> {
KonanTarget.MACBOOK.enabled = true
KonanTarget.IPHONE.enabled = true
KonanTarget.IPHONE_SIM.enabled = true
KonanTarget.ANDROID_ARM32.enabled = true
KonanTarget.ANDROID_ARM64.enabled = true
}
else ->
error("Unknown host platform: $host")
}
if (!current.enabled) {
error("Target $current is not available on the current host")
}
}
fun known(name: String): String {
if (targets[name] == null) {
error("Unknown target: $name. Use -list_targets to see the list of available targets")
}
return name
}
fun list() {
targets.forEach { key, target ->
if (target.enabled) {
val isDefault = if (target == current) "(default)" else ""
println(String.format("%1$-30s%2$-10s", "$key:", "$isDefault"))
}
}
}
fun determineCurrent(): KonanTarget {
return if (userRequest == null || userRequest == "host") {
host
} else {
targets[known(userRequest)]!!
}
}
fun hostSuffix() = host.suffix
fun hostTargetSuffix() =
if (current == host) host.suffix else "${host.suffix}-${current.suffix}"
fun targetSuffix() = current.suffix
companion object {
fun host_os(): String {
val javaOsName = System.getProperty("os.name")
return when {
javaOsName == "Mac OS X" -> "osx"
javaOsName == "Linux" -> "linux"
javaOsName.startsWith("Windows") -> "windows"
else -> error("Unknown operating system: ${javaOsName}")
}
}
fun host_arch(): String {
val javaArch = System.getProperty("os.arch")
return when (javaArch) {
"x86_64" -> "x86_64"
"amd64" -> "x86_64"
"arm64" -> "arm64"
else -> error("Unknown hardware platform: ${javaArch}")
}
}
val host: KonanTarget = when (host_os()) {
"osx" -> KonanTarget.MACBOOK
"linux" -> KonanTarget.LINUX
"windows" -> KonanTarget.MINGW
else -> error("Unknown host target: ${host_os()} ${host_arch()}")
}
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.konan
import java.io.File
import java.lang.ProcessBuilder
import java.lang.ProcessBuilder.Redirect
import org.jetbrains.kotlin.konan.target.*
typealias BitcodeFile = String
typealias ObjectFile = String
@@ -186,7 +187,7 @@ internal class LinkStage(val context: Context) {
private val distribution = context.config.distribution
val platform = when (context.config.targetManager.current) {
val platform = when (context.config.targetManager.target) {
KonanTarget.LINUX, KonanTarget.RASPBERRYPI ->
LinuxBasedPlatform(distribution)
KonanTarget.MACBOOK, KonanTarget.IPHONE, KonanTarget.IPHONE_SIM ->
@@ -196,7 +197,7 @@ internal class LinkStage(val context: Context) {
KonanTarget.MINGW ->
MingwPlatform(distribution)
else ->
error("Unexpected target platform: ${context.config.targetManager.current}")
error("Unexpected target platform: ${context.config.targetManager.target}")
}
val optimize = config.get(KonanConfigKeys.OPTIMIZATION) ?: false
@@ -251,7 +252,7 @@ internal class LinkStage(val context: Context) {
get() = if (nomain) emptyList() else platform.entrySelector
fun link(objectFiles: List<ObjectFile>): ExecutableFile {
val executable = config.get(KonanConfigKeys.OUTPUT_FILE)!!
val executable = context.config.outputFile
val linkCommand = platform.linkCommand(objectFiles, executable, optimize, config.getBoolean(KonanConfigKeys.DEBUG)) +
distribution.libffi +
asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) +
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.backend.konan.library
import llvm.LLVMModuleRef
import llvm.LLVMWriteBitcodeToFile
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.backend.konan.TargetManager
import org.jetbrains.kotlin.backend.konan.serialization.Base64
import org.jetbrains.kotlin.backend.konan.serialization.deserializeModule
import org.jetbrains.kotlin.backend.konan.util.File
@@ -20,7 +20,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanTarget
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -154,7 +154,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
get() {
return slotCount > 1 || localAllocs > 0 ||
// Prevent empty cleanup on mingw to workaround LLVM bug:
context.config.targetManager.current == KonanTarget.MINGW
context.config.targetManager.target == KonanTarget.MINGW
}
private fun releaseVars() {
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanTarget
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.backend.konan.hash.GlobalHash
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -259,7 +259,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
val throwExceptionFunction = importRtFunction("ThrowException")
val appendToInitalizersTail = importRtFunction("AppendToInitializersTail")
private val personalityFunctionName = when (context.config.targetManager.current) {
private val personalityFunctionName = when (context.config.targetManager.target) {
KonanTarget.MINGW -> "__gxx_personality_seh0"
else -> "__gxx_personality_v0"
}
@@ -22,7 +22,6 @@ import llvm.*
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.backend.konan.KonanVersion
import org.jetbrains.kotlin.backend.konan.TargetManager
import org.jetbrains.kotlin.backend.konan.util.File
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -103,7 +102,7 @@ internal fun String?.toFileAndFolder():FileAndFolder {
internal fun generateDebugInfoHeader(context: Context) {
if (context.shouldContainDebugInfo()) {
val path = context.config.configuration.get(KonanConfigKeys.OUTPUT_FILE)!!
val path = context.config.outputFile
.toFileAndFolder()
context.debugInfo.module = DICreateModule(
@@ -16,13 +16,13 @@
package org.jetbrains.kotlin.backend.konan.llvm
import org.jetbrains.kotlin.backend.konan.CompilerOutputKind
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
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.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.backend.konan.CompilerOutputKind
import org.jetbrains.kotlin.backend.konan.KonanPhase
import org.jetbrains.kotlin.backend.konan.library.LinkData
import org.jetbrains.kotlin.backend.konan.PhaseManager
@@ -43,6 +42,7 @@ import org.jetbrains.kotlin.ir.util.getArguments
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -85,65 +85,65 @@ internal fun emitLLVM(context: Context) {
if (context.shouldContainDebugInfo()) {
DIFinalize(context.debugInfo.builder)
}
when (config.get(KonanConfigKeys.PRODUCE)) {
CompilerOutputKind.PROGRAM -> {
val program = config.get(KonanConfigKeys.OUTPUT_NAME)!!
val output = "${program}.kt.bc"
context.bitcodeFileName = output
phaser.phase(KonanPhase.BITCODE_LINKER) {
for (library in context.config.nativeLibraries) {
val libraryModule = parseBitcodeFile(library)
val failed = LLVMLinkModules2(llvmModule, libraryModule)
if (failed != 0) {
throw Error("failed to link $library") // TODO: retrieve error message from LLVM.
}
}
}
LLVMWriteBitcodeToFile(llvmModule, output)
}
CompilerOutputKind.LIBRARY -> {
val libraryName = config.get(KonanConfigKeys.OUTPUT_NAME)!!
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
val targetName = context.config.targetManager.currentName
val library = buildLibrary(
phaser,
context.config.nativeLibraries,
context.serializedLinkData!!,
targetName,
libraryName,
llvmModule,
nopack)
context.library = library
context.bitcodeFileName = library.mainBitcodeFileName
}
CompilerOutputKind.BITCODE -> {
val output = config.get(KonanConfigKeys.OUTPUT_FILE)!!
context.bitcodeFileName = output
LLVMWriteBitcodeToFile(llvmModule, output)
}
}
}
internal fun buildLibrary(phaser: PhaseManager, natives: List<String>, linkData: LinkData, target: String, output: String, llvmModule: LLVMModuleRef, nopack: Boolean): KonanLibraryWriter {
internal fun produceOutput(context: Context) {
val llvmModule = context.llvmModule!!
val config = context.config.configuration
when (config.get(KonanConfigKeys.PRODUCE)) {
CompilerOutputKind.PROGRAM -> {
val program = context.config.outputName
val output = "${program}.kt.bc"
context.bitcodeFileName = output
PhaseManager(context).phase(KonanPhase.BITCODE_LINKER) {
for (library in context.config.nativeLibraries) {
val libraryModule = parseBitcodeFile(library)
val failed = LLVMLinkModules2(llvmModule, libraryModule)
if (failed != 0) {
throw Error("failed to link $library") // TODO: retrieve error message from LLVM.
}
}
}
LLVMWriteBitcodeToFile(llvmModule, output)
}
CompilerOutputKind.LIBRARY -> {
val libraryName = context.config.outputName
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
val targetName = context.config.targetManager.targetName
val library = buildLibrary(
context.config.nativeLibraries,
context.serializedLinkData!!,
targetName,
libraryName,
llvmModule,
nopack)
context.library = library
context.bitcodeFileName = library.mainBitcodeFileName
}
CompilerOutputKind.BITCODE -> {
val output = context.config.outputFile
context.bitcodeFileName = output
LLVMWriteBitcodeToFile(llvmModule, output)
}
}
}
internal fun buildLibrary(natives: List<String>, linkData: LinkData, target: String, output: String, llvmModule: LLVMModuleRef, nopack: Boolean): KonanLibraryWriter {
// TODO: May be we need a factory?
//val library = KtBcLibraryWriter(output, llvmModule)
val library = SplitLibraryWriter(output, target, nopack)
library.addKotlinBitcode(llvmModule)
library.addLinkData(linkData)
phaser.phase(KonanPhase.BITCODE_LINKER) {
natives.forEach {
library.addNativeBitcode(it)
}
natives.forEach {
library.addNativeBitcode(it)
}
library.commit()
+1 -1
View File
@@ -1093,7 +1093,7 @@ task intrinsic(type: RunKonanTest) {
/*
Disabled until we extract the classes that should be
always present from stdlib.kt.bc into a separate binary.
always present from stdlib into a separate binary.
task link(type: LinkKonanTest) {
goldValue = "0\n"