Pass linkerOpts from .def to klib manifest.

This commit is contained in:
Alexander Gorshenev
2017-06-29 16:25:30 +03:00
committed by alexander-gorshenev
parent e2516f42e6
commit 5effdcb1d2
13 changed files with 80 additions and 14 deletions
@@ -30,7 +30,6 @@ fun main(args: Array<String>) {
"arch" to (System.getenv("TARGET_ARCH") ?: "x86-64"),
"os" to (System.getenv("TARGET_OS") ?: host)
)
processLib(konanHome, substitutions, parseArgs(args))
}
@@ -256,11 +255,17 @@ private fun loadProperties(file: File?, substitutions: Map<String, String>): Pro
return result
}
private fun parseDefFile(file: File?, substitutions: Map<String, String>): Pair<Properties, List<String>> {
private fun Properties.storeProperties(file: File) {
file.outputStream().use {
this.store(it, null)
}
}
private fun parseDefFile(file: File?, substitutions: Map<String, String>): Triple<Properties, Properties, List<String>> {
val properties = Properties()
if (file == null) {
return properties to emptyList()
return Triple(properties, Properties(), emptyList())
}
val lines = file.readLines()
@@ -281,11 +286,18 @@ private fun parseDefFile(file: File?, substitutions: Map<String, String>): Pair<
val propertiesReader = StringReader(propertyLines.joinToString(System.lineSeparator()))
properties.load(propertiesReader)
// Pass unsubstituted copy of properties we have obtained from `.def`
// to compiler `-maniest`.
val manifestAddendProperties = properties.duplicate()
substitute(properties, substitutions)
return properties to headerLines
return Triple(properties, manifestAddendProperties, headerLines)
}
private fun Properties.duplicate() = Properties().apply{ putAll(this@duplicate) }
private fun usage() {
println("""
Run interop tool with -def <def_file_for_lib>.def
@@ -316,13 +328,15 @@ private fun processLib(konanHome: String,
val flavor = KotlinPlatform.values().single { it.name.equals(flavorName, ignoreCase = true) }
val target = args["-target"]?.single()?.targetSuffix() ?: defaultTarget
val defFile = args["-def"]?.single()?.let { File(it) }
val manifestAddend = args["-manifest"]?.single()?.let { File(it) }
if (defFile == null && args["-pkg"] == null) {
usage()
return
}
val (config, defHeaderLines) = parseDefFile(defFile, substitutions)
val (config, manifestAddendProperties, defHeaderLines)
= parseDefFile(defFile, substitutions)
val konanFileName = args["-properties"]?.single() ?:
"${konanHome}/konan/konan.properties"
@@ -409,6 +423,9 @@ private fun processLib(konanHome: String,
}
}
manifestAddend?.parentFile?.mkdirs()
manifestAddend ?.let { manifestAddendProperties.storeProperties(it) }
val workDir = defFile?.absoluteFile?.parentFile ?: File(userDir)
if (flavor == KotlinPlatform.JVM) {
@@ -124,6 +124,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
put(ABI_VERSION, 1)
arguments.mainPackage ?.let{ put(ENTRY, it) }
arguments.manifestFile ?.let{ put(MANIFEST_FILE, it) }
arguments.runtimeFile ?.let{ put(RUNTIME_FILE, it) }
arguments.propertyFile ?.let{ put(PROPERTY_FILE, it) }
@@ -36,6 +36,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
@field:Argument(value = "-list_targets", description = "List available hardware targets")
@JvmField var listTargets: Boolean = false
@field:Argument(value = "-manifest", valueDescription = "<path>", description = "Provide a maniferst addend file")
@JvmField var manifestFile: String? = null
@field:Argument(value = "-nativelibrary", shortName = "-nl", valueDescription = "<path>", description = "Include the native library")
@JvmField var nativeLibraries: Array<String>? = null
@@ -43,6 +43,8 @@ class KonanConfigKeys {
= CompilerConfigurationKey.create("list backend phases")
val LIST_TARGETS: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("list available targets")
val MANIFEST_FILE: CompilerConfigurationKey<String?>
= CompilerConfigurationKey.create("provide manifest addend file")
val META_INFO: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("generate metadata")
val MODULE_KIND: CompilerConfigurationKey<ModuleKind>
@@ -248,13 +248,14 @@ internal class LinkStage(val context: Context) {
val entryPointSelector: List<String>
get() = if (nomain) emptyList() else platform.entrySelector
fun link(objectFiles: List<ObjectFile>): ExecutableFile {
fun link(objectFiles: List<ObjectFile>, libraryProvidedLinkerFlags: List<String>): ExecutableFile {
val executable = context.config.outputFile
val linkCommand = platform.linkCommand(objectFiles, executable, optimize, config.getBoolean(KonanConfigKeys.DEBUG)) +
distribution.libffi +
asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) +
entryPointSelector +
platform.linkCommandSuffix()
platform.linkCommandSuffix() +
libraryProvidedLinkerFlags
runTool(*linkCommand.toTypedArray())
if (platform is MacOSBasedPlatform && context.shouldContainDebugInfo()) {
@@ -312,6 +313,9 @@ internal class LinkStage(val context: Context) {
val bitcodeFiles = listOf(emitted) +
libraries.map{it -> it.bitcodePaths}.flatten()
val libraryProvidedLinkerFlags =
libraries.map{it -> it.linkerOpts}.flatten()
var objectFiles: List<String> = listOf()
val phaser = PhaseManager(context)
@@ -319,7 +323,7 @@ internal class LinkStage(val context: Context) {
objectFiles = listOf( llvmLto(bitcodeFiles ) )
}
phaser.phase(KonanPhase.LINKER) {
link(objectFiles)
link(objectFiles, libraryProvidedLinkerFlags)
}
}
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
interface KonanLibraryReader {
val libraryName: String
val bitcodePaths: List<String>
val linkerOpts: List<String>
fun moduleDescriptor(specifics: LanguageVersionSettings): ModuleDescriptor
}
@@ -22,6 +22,7 @@ interface KonanLibraryWriter {
fun addLinkData(linkData: LinkData)
fun addNativeBitcode(library: String)
fun addKotlinBitcode(llvmModule: LLVMModuleRef)
fun addManifestAddend(path: String)
val mainBitcodeFileName: String
fun commit()
}
@@ -89,5 +89,7 @@ class LibraryReaderImpl(override val libDir: File, currentAbiVersion: Int,
override val bitcodePaths: List<String>
get() = (kotlinDir.listFiles + nativeDir.listFiles).map{it.absolutePath}
override val linkerOpts: List<String>
get() = manifestProperties.propertyList("linkerOpts", target!!.targetSuffix)
}
@@ -71,6 +71,12 @@ class LibraryWriterImpl(override val libDir: File, currentAbiVersion: Int,
File(library).copyTo(File(nativeDir, basename))
}
override fun addManifestAddend(path: String) {
val properties = File(path).loadProperties()
manifestProperties.putAll(properties)
println("manifest addend: ${properties.stringPropertyNames().joinToString(" ")}")
}
override fun commit() {
manifestProperties.saveToFile(manifestFile)
if (!nopack) {
@@ -80,7 +86,15 @@ class LibraryWriterImpl(override val libDir: File, currentAbiVersion: Int,
}
}
internal fun buildLibrary(natives: List<String>, linkData: LinkData, abiVersion: Int, target: KonanTarget, output: String, llvmModule: LLVMModuleRef, nopack: Boolean): KonanLibraryWriter {
internal fun buildLibrary(
natives: List<String>,
linkData: LinkData,
abiVersion: Int,
target: KonanTarget,
output: String,
llvmModule: LLVMModuleRef,
nopack: Boolean,
manifest: String?): KonanLibraryWriter {
val library = LibraryWriterImpl(output, abiVersion, target, nopack)
@@ -89,6 +103,7 @@ internal fun buildLibrary(natives: List<String>, linkData: LinkData, abiVersion:
natives.forEach {
library.addNativeBitcode(it)
}
manifest ?.let { library.addManifestAddend(it) }
library.commit()
return library
@@ -110,6 +110,7 @@ internal fun produceOutput(context: Context) {
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,
@@ -118,7 +119,8 @@ internal fun produceOutput(context: Context) {
target,
libraryName,
llvmModule,
nopack)
nopack,
manifest)
context.library = library
context.bitcodeFileName = library.mainBitcodeFileName
@@ -131,6 +131,8 @@ open class KonanCompileTask: KonanTargetableTask() {
internal set
@Optional @Input var apiVersion : String? = null
internal set
@Input var manifest : String? = null
internal set
@Input var dumpParameters: Boolean = false
// TODO: Is there a better way to rerun tasks when the compiler version changes?
@@ -150,6 +152,7 @@ open class KonanCompileTask: KonanTargetableTask() {
addArgIfNotNull("-target", target)
addArgIfNotNull("-language-version", languageVersion)
addArgIfNotNull("-api-version", apiVersion)
addArgIfNotNull("-manifest", manifest)
addKey("-g", enableDebug)
addKey("-nostdlib", noStdLib)
@@ -232,6 +235,7 @@ open class KonanCompileConfig(
builtBy(generateStubsTask)
include("**/*.bc")
})
generateStubsTask.manifest ?.let {manifest(it)}
}
fun useInterops(interops: ArrayList<String>) {
@@ -287,6 +291,10 @@ open class KonanCompileConfig(
linkerOpts.addAll(args)
}
fun manifest(arg: String) = with(compilationTask) {
manifest = arg
}
fun target(tgt: String) = with(compilationTask) {
target = tgt
}
@@ -82,6 +82,9 @@ open class KonanInteropTask: KonanTargetableTask() {
@Optional @Input var linker: String? = null
internal set
@Optional @Input var manifest: String? = null
internal set
@Input var dumpParameters: Boolean = false
@Input val compilerOpts = mutableListOf<String>()
@Input val linkerOpts = mutableListOf<String>()
@@ -118,6 +121,7 @@ open class KonanInteropTask: KonanTargetableTask() {
addArg("-generated", stubsDir.canonicalPath)
addArg("-natives", libsDir.canonicalPath)
manifest ?.let {addArg("-manifest", it)}
addArgIfNotNull("-target", target)
val defFilePath = defFile?.canonicalPath ?:
@@ -156,14 +160,16 @@ open class KonanInteropConfig(
val generateStubsTask: KonanInteropTask = project.tasks.create(
"gen${name.capitalize()}InteropStubs",
KonanInteropTask::class.java
) { it.init(name) }
// Config and task to compile *.kt stubs in a *.bc library
) { it.init(name)
it.manifest = "${it.stubsDir.path}/manifest.properties"
}
// Config and task to compile *.kt stubs into a library
internal val compileStubsConfig = KonanCompileConfig("${name}InteropStubs", project, "compile").apply {
compilationTask.dependsOn(generateStubsTask)
outputDir("${project.konanInteropCompiledStubsDir}/$name")
produce("library")
inputFiles(project.fileTree(generateStubsTask.stubsDir).apply { builtBy(generateStubsTask) })
manifest("${generateStubsTask.stubsDir.path}/manifest.properties")
}
val compileStubsTask = compileStubsConfig.compilationTask
@@ -19,11 +19,13 @@ fun invokeCinterop(args: Array<String>) {
val generatedDir = File(buildDir, "kotlin")
val nativesDir = File(buildDir, "natives")
val cstubsName ="cstubs"
val manifest = File(buildDir, "manifest.properties")
val additionalArgs = listOf<String>(
"-generated", generatedDir.path,
"-natives", nativesDir.path,
"-cstubsname", cstubsName,
"-manifest", manifest.path,
"-flavor", "native")
val cinteropArgs = (additionalArgs + args.toList()).toTypedArray()
@@ -34,7 +36,9 @@ fun invokeCinterop(args: Array<String>) {
"-produce", "library",
"-nativelibrary", File(nativesDir, "$cstubsName.bc").path,
"-o", outputFileName,
"-target", target)
"-target", target,
"-manifest", manifest.path
)
konancMain(konancArgs)
}