Collect dependent libraries in the manifest.
Link dependencies recursively.
This commit is contained in:
committed by
alexander-gorshenev
parent
3b1428597b
commit
42cbf8428b
@@ -162,7 +162,7 @@ targetList.each { target ->
|
||||
"-Djava.library.path=${project.buildDir}/nativelibs",
|
||||
"-Dfile.encoding=UTF-8"]
|
||||
|
||||
def defaultArgs = ['-nopack', '-nostdlib','-ea' ]
|
||||
def defaultArgs = ['-nopack', '-nostdlib', '-nodefaultlibs', '-ea' ]
|
||||
if (target != "wasm32") defaultArgs += '-g'
|
||||
def konanArgs = [*defaultArgs,
|
||||
'-target', target,
|
||||
@@ -176,7 +176,7 @@ targetList.each { target ->
|
||||
jvmArgs = konanJvmArgs
|
||||
args = [*konanArgs,
|
||||
'-output', project(':runtime').file("build/${target}Stdlib"),
|
||||
'-produce', 'library',
|
||||
'-produce', 'library', '-module_name', 'stdlib',
|
||||
project(':Interop:Runtime').file('src/main/kotlin'),
|
||||
project(':Interop:Runtime').file('src/native/kotlin'),
|
||||
project(':runtime').file('src/main/kotlin')]
|
||||
|
||||
@@ -86,7 +86,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
arguments.libraries.toNonNullList())
|
||||
|
||||
put(LINKER_ARGS, arguments.linkerArguments.toNonNullList())
|
||||
|
||||
arguments.moduleName ?. let{ put(MODULE_NAME, it) }
|
||||
arguments.target ?.let{ put(TARGET, it) }
|
||||
|
||||
put(INCLUDED_BINARY_FILES,
|
||||
|
||||
@@ -45,6 +45,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
@Argument(value = "-manifest", valueDescription = "<path>", description = "Provide a maniferst addend file")
|
||||
var manifestFile: String? = null
|
||||
|
||||
@Argument(value = "-module_name", valueDescription = "<name>", description = "Spicify a name for the compilation module")
|
||||
var moduleName: String? = null
|
||||
|
||||
@Argument(value = "-nativelibrary", shortName = "-nl", valueDescription = "<path>", description = "Include the native bitcode library")
|
||||
var nativeLibraries: Array<String>? = null
|
||||
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 llvm.LLVMLinkModules2
|
||||
import llvm.LLVMWriteBitcodeToFile
|
||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
|
||||
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.parseBitcodeFile
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
|
||||
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 output = context.config.outputName
|
||||
val libraryName = context.config.moduleId
|
||||
val neededLibraries
|
||||
= context.config.immediateLibraries.purgeUnneeded()
|
||||
val abiVersion = context.config.currentAbiVersion
|
||||
val target = context.config.targetManager.target
|
||||
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
||||
val manifest = config.get(KonanConfigKeys.MANIFEST_FILE)
|
||||
|
||||
val library = buildLibrary(
|
||||
context.config.nativeLibraries,
|
||||
context.config.includeBinaries,
|
||||
neededLibraries,
|
||||
context.serializedLinkData!!,
|
||||
abiVersion,
|
||||
target,
|
||||
output,
|
||||
libraryName,
|
||||
llvmModule,
|
||||
nopack,
|
||||
manifest,
|
||||
context.moduleEscapeAnalysisResult.build().toByteArray())
|
||||
|
||||
context.library = library
|
||||
context.bitcodeFileName = library.mainBitcodeFileName
|
||||
}
|
||||
CompilerOutputKind.BITCODE -> {
|
||||
val output = context.config.outputFile
|
||||
context.bitcodeFileName = output
|
||||
LLVMWriteBitcodeToFile(llvmModule, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun List<KonanLibraryReader>.purgeUnneeded(): List<KonanLibraryReader> {
|
||||
return this.map {
|
||||
if (!it.isNeededForLink && it.isDefaultLink) null else it
|
||||
}.filterNotNull()
|
||||
}
|
||||
+27
-7
@@ -71,15 +71,15 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
val outputFile = outputName.suffixIfNot(produce.suffix(targetManager.target))
|
||||
|
||||
val moduleId: String
|
||||
// This is a decision we could change
|
||||
get() = outputName
|
||||
get() = configuration.get(KonanConfigKeys.MODULE_NAME) ?: File(outputName).name
|
||||
|
||||
private val libraryNames: List<String>
|
||||
get() = configuration.getList(KonanConfigKeys.LIBRARY_FILES)
|
||||
|
||||
private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES)
|
||||
private val resolver = KonanLibrarySearchPathResolver(repositories, distribution.klib, distribution.localKonanDir)
|
||||
val libraries: List<KonanLibraryReader> by lazy {
|
||||
|
||||
val immediateLibraries: List<LibraryReaderImpl> by lazy {
|
||||
val target = targetManager.target
|
||||
|
||||
val defaultLibraries = resolver.defaultLinks(
|
||||
@@ -91,10 +91,25 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
.map { resolver.resolve(it) }
|
||||
.map{ LibraryReaderImpl(it, currentAbiVersion, target) }
|
||||
|
||||
val resolvedLibraries = defaultLibraries + userProvidedLibraries
|
||||
checkLibraryDuplicates(resolvedLibraries.map{it.libraryFile})
|
||||
var resolvedLibraries = defaultLibraries + userProvidedLibraries
|
||||
warnOnLibraryDuplicates(resolvedLibraries.map{ it.libraryFile })
|
||||
resolvedLibraries.distinctBy { it.libraryFile.absolutePath }
|
||||
}
|
||||
|
||||
resolvedLibraries
|
||||
val libraries: List<LibraryReaderImpl> by lazy {
|
||||
val result = mutableListOf<LibraryReaderImpl>()
|
||||
result.addAll(immediateLibraries)
|
||||
do {
|
||||
val dependencies = result
|
||||
.map { it.dependencies } .flatten()
|
||||
.map { resolver.resolve(it) }
|
||||
.map { LibraryReaderImpl(it, currentAbiVersion, targetManager.target) }
|
||||
|
||||
val newDependencies = dependencies.deleteMatching(result, { it.libraryFile.absolutePath })
|
||||
result.addAll(newDependencies)
|
||||
} while (newDependencies.size > 0)
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
private val loadedDescriptors = loadLibMetadata()
|
||||
@@ -144,7 +159,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
loadedDescriptors
|
||||
}
|
||||
|
||||
private fun checkLibraryDuplicates(resolvedLibraries: List<File>) {
|
||||
private fun warnOnLibraryDuplicates(resolvedLibraries: List<File>) {
|
||||
val duplicates = resolvedLibraries.groupBy { it.absolutePath } .values.filter { it.size > 1 }
|
||||
duplicates.forEach {
|
||||
configuration.report(STRONG_WARNING, "library included more than once: ${it.first().absolutePath}")
|
||||
@@ -152,5 +167,10 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T, K> List<T>.deleteMatching(other: List<T>, transform: (T) -> K): List<T> {
|
||||
val transformed = other.map { transform(it) }
|
||||
return this.filterNot { transformed.contains( transform(it) ) }
|
||||
}
|
||||
|
||||
fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String)
|
||||
= this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message)
|
||||
|
||||
+2
@@ -55,6 +55,8 @@ class KonanConfigKeys {
|
||||
= CompilerConfigurationKey.create("generate metadata")
|
||||
val MODULE_KIND: CompilerConfigurationKey<ModuleKind>
|
||||
= CompilerConfigurationKey.create("module kind")
|
||||
val MODULE_NAME: CompilerConfigurationKey<String?>
|
||||
= CompilerConfigurationKey.create("module name")
|
||||
val NATIVE_LIBRARY_FILES: CompilerConfigurationKey<List<String>>
|
||||
= CompilerConfigurationKey.create("native library file paths")
|
||||
val NODEFAULTLIBS: CompilerConfigurationKey<Boolean>
|
||||
|
||||
-1
@@ -22,7 +22,6 @@ 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
|
||||
|
||||
+1
-5
@@ -235,11 +235,7 @@ internal class LinkStage(val context: Context) {
|
||||
private val debug = config.get(KonanConfigKeys.DEBUG) ?: false
|
||||
private val nomain = config.get(KonanConfigKeys.NOMAIN) ?: false
|
||||
private val emitted = context.bitcodeFileName
|
||||
private val libraries = context.config.libraries
|
||||
.map {
|
||||
if (!it.isNeededForLink && it.isDefaultLink) null else it
|
||||
}.filterNotNull()
|
||||
|
||||
private val libraries = context.config.libraries.purgeUnneeded()
|
||||
private fun MutableList<String>.addNonEmpty(elements: List<String>) {
|
||||
addAll(elements.filter { !it.isEmpty() })
|
||||
}
|
||||
|
||||
+2
@@ -22,9 +22,11 @@ import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
interface KonanLibraryReader {
|
||||
val libraryName: String
|
||||
val uniqueName: String
|
||||
val bitcodePaths: List<String>
|
||||
val includedPaths: List<String>
|
||||
val linkerOpts: List<String>
|
||||
val dependencies: List<String>
|
||||
val escapeAnalysis: ByteArray?
|
||||
val isNeededForLink: Boolean get() = true
|
||||
val isDefaultLink: Boolean get() = false
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ interface KonanLibraryWriter {
|
||||
fun addNativeBitcode(library: String)
|
||||
fun addIncludedBinary(library: String)
|
||||
fun addKotlinBitcode(llvmModule: LLVMModuleRef)
|
||||
fun addLinkDependencies(libraries: List<KonanLibraryReader>)
|
||||
fun addManifestAddend(path: String)
|
||||
fun addEscapeAnalysis(escapeAnalysis: ByteArray)
|
||||
val mainBitcodeFileName: String
|
||||
|
||||
+6
@@ -56,6 +56,9 @@ class LibraryReaderImpl(var libraryFile: File, val currentAbiVersion: Int,
|
||||
override val libraryName
|
||||
get() = inPlace.libraryName
|
||||
|
||||
override val uniqueName
|
||||
get() = manifestProperties.propertyString("unique_name")!!
|
||||
|
||||
override val bitcodePaths: List<String>
|
||||
get() = (realFiles.kotlinDir.listFiles + realFiles.nativeDir.listFiles).map{it.absolutePath}
|
||||
|
||||
@@ -65,6 +68,9 @@ class LibraryReaderImpl(var libraryFile: File, val currentAbiVersion: Int,
|
||||
override val linkerOpts: List<String>
|
||||
get() = manifestProperties.propertyList("linkerOpts", target!!.detailedName)
|
||||
|
||||
override val dependencies: List<String>
|
||||
get() = manifestProperties.propertyList("dependencies")
|
||||
|
||||
val moduleHeaderData: ByteArray by lazy {
|
||||
reader.loadSerializedModule()
|
||||
}
|
||||
|
||||
+16
-5
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
|
||||
import llvm.LLVMModuleRef
|
||||
import llvm.LLVMWriteBitcodeToFile
|
||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibrary
|
||||
@@ -29,13 +30,13 @@ abstract class FileBasedLibraryWriter (
|
||||
val file: File, val currentAbiVersion: Int): KonanLibraryWriter {
|
||||
}
|
||||
|
||||
class LibraryWriterImpl(override val libDir: File, currentAbiVersion: Int,
|
||||
class LibraryWriterImpl(override val libDir: File, moduleName: String, currentAbiVersion: Int,
|
||||
override val target: KonanTarget?, val nopack: Boolean = false):
|
||||
FileBasedLibraryWriter(libDir, currentAbiVersion), KonanLibrary {
|
||||
|
||||
public constructor(path: String, currentAbiVersion: Int,
|
||||
public constructor(path: String, moduleName: String, currentAbiVersion: Int,
|
||||
target:KonanTarget?, nopack: Boolean):
|
||||
this(File(path), currentAbiVersion, target, nopack)
|
||||
this(File(path), moduleName, currentAbiVersion, target, nopack)
|
||||
|
||||
override val libraryName = libDir.path
|
||||
val klibFile
|
||||
@@ -58,6 +59,8 @@ class LibraryWriterImpl(override val libDir: File, currentAbiVersion: Int,
|
||||
nativeDir.mkdirs()
|
||||
includedDir.mkdirs()
|
||||
resourcesDir.mkdirs()
|
||||
// TODO: <name>:<hash> will go somewhere around here.
|
||||
manifestProperties.setProperty("unique_name", "$moduleName")
|
||||
manifestProperties.setProperty("abi_version", "$currentAbiVersion")
|
||||
}
|
||||
|
||||
@@ -82,6 +85,11 @@ class LibraryWriterImpl(override val libDir: File, currentAbiVersion: Int,
|
||||
File(library).copyTo(File(includedDir, basename))
|
||||
}
|
||||
|
||||
override fun addLinkDependencies(libraries: List<KonanLibraryReader>) {
|
||||
if (libraries.isEmpty()) return
|
||||
manifestProperties.setProperty("dependencies", libraries .map { it.uniqueName } . joinToString(" "))
|
||||
}
|
||||
|
||||
override fun addManifestAddend(path: String) {
|
||||
val properties = File(path).loadProperties()
|
||||
manifestProperties.putAll(properties)
|
||||
@@ -102,17 +110,19 @@ class LibraryWriterImpl(override val libDir: File, currentAbiVersion: Int,
|
||||
|
||||
internal fun buildLibrary(
|
||||
natives: List<String>,
|
||||
included: List<String>,
|
||||
included: List<String>,
|
||||
linkDependencies: List<KonanLibraryReader>,
|
||||
linkData: LinkData,
|
||||
abiVersion: Int,
|
||||
target: KonanTarget,
|
||||
output: String,
|
||||
moduleName: String,
|
||||
llvmModule: LLVMModuleRef,
|
||||
nopack: Boolean,
|
||||
manifest: String?,
|
||||
escapeAnalysis: ByteArray?): KonanLibraryWriter {
|
||||
|
||||
val library = LibraryWriterImpl(output, abiVersion, target, nopack)
|
||||
val library = LibraryWriterImpl(output, moduleName, abiVersion, target, nopack)
|
||||
|
||||
library.addKotlinBitcode(llvmModule)
|
||||
library.addLinkData(linkData)
|
||||
@@ -122,6 +132,7 @@ internal fun buildLibrary(
|
||||
included.forEach {
|
||||
library.addIncludedBinary(it)
|
||||
}
|
||||
library.addLinkDependencies(linkDependencies)
|
||||
manifest ?.let { library.addManifestAddend(it) }
|
||||
escapeAnalysis?.let { library.addEscapeAnalysis(it) }
|
||||
|
||||
|
||||
-56
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
@@ -39,7 +38,6 @@ 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.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -52,7 +50,6 @@ import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
|
||||
internal fun emitLLVM(context: Context) {
|
||||
val irModule = context.irModule!!
|
||||
|
||||
@@ -89,59 +86,6 @@ internal fun emitLLVM(context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
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 abiVersion = context.config.currentAbiVersion
|
||||
val target = context.config.targetManager.target
|
||||
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
||||
val manifest = config.get(KonanConfigKeys.MANIFEST_FILE)
|
||||
|
||||
val library = buildLibrary(
|
||||
context.config.nativeLibraries,
|
||||
context.config.includeBinaries,
|
||||
context.serializedLinkData!!,
|
||||
abiVersion,
|
||||
target,
|
||||
libraryName,
|
||||
llvmModule,
|
||||
nopack,
|
||||
manifest,
|
||||
context.moduleEscapeAnalysisResult.build().toByteArray())
|
||||
|
||||
context.library = library
|
||||
context.bitcodeFileName = library.mainBitcodeFileName
|
||||
}
|
||||
CompilerOutputKind.BITCODE -> {
|
||||
val output = context.config.outputFile
|
||||
context.bitcodeFileName = output
|
||||
LLVMWriteBitcodeToFile(llvmModule, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun verifyModule(llvmModule: LLVMModuleRef, current: String = "") {
|
||||
memScoped {
|
||||
val errorRef = allocPointerTo<ByteVar>()
|
||||
|
||||
Reference in New Issue
Block a user