Allow including external binaries within klibs with -includeBinary flag.

Link such binaries in case they are javascripts on wasm32.
Otherwise don't do anything useful yet.
This commit is contained in:
Alexander Gorshenev
2017-09-08 14:34:56 +03:00
committed by alexander-gorshenev
parent c363732eb5
commit e9720b7e13
12 changed files with 54 additions and 3 deletions
@@ -87,6 +87,8 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
arguments.target ?.let{ put(TARGET, it) }
put(INCLUDED_BINARY_FILES,
arguments.includeBinaries.toNonNullList())
put(NATIVE_LIBRARY_FILES,
arguments.nativeLibraries.toNonNullList())
put(REPOSITORIES,
@@ -30,6 +30,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-enable_assertions", shortName = "-ea", description = "Enable runtime assertions in generated code")
var enableAssertions: Boolean = false
@Argument(value = "-includeBinary", shortName = "-ib", valueDescription = "<path>", description = "Pack external binary within the klib")
var includeBinaries: Array<String>? = null
@Argument(value = "-library", shortName = "-l", valueDescription = "<path>", description = "Link with the library")
var libraries: Array<String>? = null
@@ -39,7 +42,7 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-manifest", valueDescription = "<path>", description = "Provide a maniferst addend file")
var manifestFile: String? = null
@Argument(value = "-nativelibrary", shortName = "-nl", valueDescription = "<path>", description = "Include the native library")
@Argument(value = "-nativelibrary", shortName = "-nl", valueDescription = "<path>", description = "Include the native bitcode library")
var nativeLibraries: Array<String>? = null
@Argument(value = "-nomain", description = "Assume 'main' entry point to be provided by external libraries")
@@ -98,6 +98,9 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
internal val nativeLibraries: List<String> =
configuration.getList(KonanConfigKeys.NATIVE_LIBRARY_FILES)
internal val includeBinaries: List<String> =
configuration.getList(KonanConfigKeys.INCLUDED_BINARY_FILES)
fun loadLibMetadata(): List<ModuleDescriptorImpl> {
val allMetadata = mutableListOf<ModuleDescriptorImpl>()
@@ -37,6 +37,8 @@ class KonanConfigKeys {
= CompilerConfigurationKey.create("enable backend phases")
val ENTRY: CompilerConfigurationKey<String?>
= CompilerConfigurationKey.create("fully qualified main() name")
val INCLUDED_BINARY_FILES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("included binary file paths")
val LIBRARY_FILES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("library file paths")
val LINKER_ARGS: CompilerConfigurationKey<List<String>>
@@ -292,7 +292,7 @@ internal class LinkStage(val context: Context) {
private val entryPointSelector: List<String>
get() = if (nomain) emptyList() else platform.entrySelector
private fun link(objectFiles: List<ObjectFile>, libraryProvidedLinkerFlags: List<String>): ExecutableFile? {
private fun link(objectFiles: List<ObjectFile>, includedBinaries: List<String>, libraryProvidedLinkerFlags: List<String>): ExecutableFile? {
val executable = context.config.outputFile
val linkCommand = platform.linkCommand(objectFiles, executable, optimize, debug) +
@@ -313,9 +313,25 @@ internal class LinkStage(val context: Context) {
runTool(*platform.dsymutilDryRunVerboseCommand(executable).toTypedArray())
runTool(*platform.dsymutilCommand(executable).toTypedArray())
}
if (platform is WasmPlatform) {
JavaScriptLinker(includedBinaries.filter{it.isJavaScript}, executable)
}
return executable
}
private val String.isJavaScript
get() = this.endsWith(".js")
private fun JavaScriptLinker(jsFiles: List<String>, executable: String): String {
val linkedJavaScript = File("$executable.js")
linkedJavaScript.writeBytes(ByteArray(0));
jsFiles.forEach {
linkedJavaScript.appendBytes(File(it).readBytes())
}
return linkedJavaScript.name
}
private fun executeCommand(vararg command: String): Int {
context.log{""}
@@ -362,6 +378,9 @@ internal class LinkStage(val context: Context) {
val bitcodeFiles = listOf(emitted) +
libraries.map{it -> it.bitcodePaths}.flatten()
val includedBinaries =
libraries.map{it -> it.includedPaths}.flatten()
val libraryProvidedLinkerFlags =
libraries.map{it -> it.linkerOpts}.flatten()
@@ -377,7 +396,7 @@ internal class LinkStage(val context: Context) {
)
}
phaser.phase(KonanPhase.LINKER) {
link(objectFiles, libraryProvidedLinkerFlags)
link(objectFiles, includedBinaries, libraryProvidedLinkerFlags)
}
}
}
@@ -37,6 +37,8 @@ interface KonanLibraryLayout {
get() = File(targetDir, "kotlin")
val nativeDir
get() = File(targetDir, "native")
val includedDir
get() = File(targetDir, "included")
val linkdataDir
get() = File(libDir, "linkdata")
val moduleHeaderFile
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
interface KonanLibraryReader {
val libraryName: String
val bitcodePaths: List<String>
val includedPaths: List<String>
val linkerOpts: List<String>
val escapeAnalysis: ByteArray?
fun moduleDescriptor(specifics: LanguageVersionSettings): ModuleDescriptor
@@ -21,6 +21,7 @@ import llvm.LLVMModuleRef
interface KonanLibraryWriter {
fun addLinkData(linkData: LinkData)
fun addNativeBitcode(library: String)
fun addIncludedBinary(library: String)
fun addKotlinBitcode(llvmModule: LLVMModuleRef)
fun addManifestAddend(path: String)
fun addEscapeAnalysis(escapeAnalysis: ByteArray)
@@ -63,6 +63,10 @@ class FileExtractor(zippedLibrary: KonanLibrary): KonanLibrary by zippedLibrary
extractDir(super.resourcesDir)
}
override val includedDir: File by lazy {
extractDir(super.includedDir)
}
override val kotlinDir: File by lazy {
extractDir(super.kotlinDir)
}
@@ -55,6 +55,9 @@ class LibraryReaderImpl(var libraryFile: File, val currentAbiVersion: Int, val t
override val bitcodePaths: List<String>
get() = (realFiles.kotlinDir.listFiles + realFiles.nativeDir.listFiles).map{it.absolutePath}
override val includedPaths: List<String>
get() = (realFiles.includedDir.listFiles).map{it.absolutePath}
override val linkerOpts: List<String>
get() = manifestProperties.propertyList("linkerOpts", target!!.targetSuffix)
@@ -56,6 +56,7 @@ class LibraryWriterImpl(override val libDir: File, currentAbiVersion: Int,
targetDir.mkdirs()
kotlinDir.mkdirs()
nativeDir.mkdirs()
includedDir.mkdirs()
resourcesDir.mkdirs()
manifestProperties.setProperty("abi_version", "$currentAbiVersion")
}
@@ -76,6 +77,11 @@ class LibraryWriterImpl(override val libDir: File, currentAbiVersion: Int,
File(library).copyTo(File(nativeDir, basename))
}
override fun addIncludedBinary(library: String) {
val basename = File(library).name
File(library).copyTo(File(includedDir, basename))
}
override fun addManifestAddend(path: String) {
val properties = File(path).loadProperties()
manifestProperties.putAll(properties)
@@ -97,6 +103,7 @@ class LibraryWriterImpl(override val libDir: File, currentAbiVersion: Int,
internal fun buildLibrary(
natives: List<String>,
included: List<String>,
linkData: LinkData,
abiVersion: Int,
target: KonanTarget,
@@ -113,6 +120,9 @@ internal fun buildLibrary(
natives.forEach {
library.addNativeBitcode(it)
}
included.forEach {
library.addIncludedBinary(it)
}
manifest ?.let { library.addManifestAddend(it) }
escapeAnalysis?.let { library.addEscapeAnalysis(it) }
@@ -121,6 +121,7 @@ internal fun produceOutput(context: Context) {
val library = buildLibrary(
context.config.nativeLibraries,
context.config.includeBinaries,
context.serializedLinkData!!,
abiVersion,
target,