Splitted KonanProperties into Configurables hierarchy.
Untangled Platfrom classes from the LinkStage and Distribution. Simplified clang management a little.
This commit is contained in:
committed by
alexander-gorshenev
parent
c5276cf6da
commit
d4b47ac709
@@ -72,7 +72,7 @@ model {
|
||||
}
|
||||
|
||||
binaries.all {
|
||||
cCompiler.args hostCompilerArgsForJni
|
||||
cCompiler.args hostPlatform.clang.hostCompilerArgsForJni
|
||||
cCompiler.args.addAll(cflags)
|
||||
}
|
||||
|
||||
@@ -157,4 +157,4 @@ task updatePrebuilt {
|
||||
into 'prebuilt/nativeInteropStubs/c'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ model {
|
||||
|
||||
def hostLibffiDir = rootProject.ext.get("${host}LibffiDir")
|
||||
|
||||
cCompiler.args hostCompilerArgsForJni
|
||||
cCompiler.args hostPlatform.clang.hostCompilerArgsForJni
|
||||
cCompiler.args "-I$hostLibffiDir/include"
|
||||
|
||||
linker.args "$hostLibffiDir/lib/libffi.a"
|
||||
|
||||
+14
-13
@@ -16,10 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.native.interop.tool
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.util.*
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.properties.loadProperties
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.PlatformManager
|
||||
import org.jetbrains.kotlin.konan.target.TargetManager
|
||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||
import org.jetbrains.kotlin.konan.util.visibleName
|
||||
|
||||
class ToolConfig(userProvidedTargetName: String?, userProvidedKonanProperties: String?, runnerProvidedKonanHome: String) {
|
||||
|
||||
@@ -33,23 +36,21 @@ class ToolConfig(userProvidedTargetName: String?, userProvidedKonanProperties: S
|
||||
|
||||
private val dependencies = DependencyProcessor.defaultDependenciesRoot
|
||||
|
||||
private val targetProperties = KonanProperties(target, properties, dependencies.path)
|
||||
private val platform = PlatformManager(properties, dependencies.path).platform(target)
|
||||
|
||||
val substitutions = mapOf<String, String> (
|
||||
"target" to target.detailedName,
|
||||
"arch" to target.architecture.visibleName)
|
||||
|
||||
fun downloadDependencies() = targetProperties.downloadDependencies()
|
||||
fun downloadDependencies() = platform.downloadDependencies()
|
||||
|
||||
val llvmHome = targetProperties.absoluteLlvmHome
|
||||
val defaultCompilerOpts =
|
||||
platform.clang.targetLibclangArgs.toList()
|
||||
|
||||
val sysRoot get() = targetProperties.absoluteTargetSysRoot
|
||||
val llvmHome = platform.absoluteLlvmHome
|
||||
val sysRoot = platform.absoluteTargetSysRoot
|
||||
|
||||
val defaultCompilerOpts = ClangManager(properties, dependencies.path)
|
||||
.targetLibclangArgs(targetProperties.target).toList()
|
||||
|
||||
|
||||
val libclang = when (host) {
|
||||
val libclang = when (host) {
|
||||
KonanTarget.MINGW -> "$llvmHome/bin/libclang.dll"
|
||||
else -> "$llvmHome/lib/${System.mapLibraryName("clang")}"
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.konan.exec.*
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
|
||||
fun produceCAdapterBitcode(clang: TargetClang, cppFileName: String, bitcodeFileName: String) {
|
||||
fun produceCAdapterBitcode(clang: ClangArgs, cppFileName: String, bitcodeFileName: String) {
|
||||
val clangCommand = clang.clangCXX("-std=c++11", cppFileName, "-emit-llvm", "-c", "-o", bitcodeFileName)
|
||||
Command(clangCommand).execute()
|
||||
}
|
||||
|
||||
+7
-25
@@ -16,21 +16,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.util.visibleName
|
||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||
|
||||
class Distribution(val targetManager: TargetManager,
|
||||
val propertyFileOverride: String? = null,
|
||||
val runtimeFileOverride: String? = null) {
|
||||
|
||||
val target = targetManager.target
|
||||
val targetName = targetManager.targetName
|
||||
val host = TargetManager.host
|
||||
val hostSuffix = TargetManager.hostSuffix
|
||||
val hostTargetSuffix = targetManager.hostTargetSuffix
|
||||
val targetSuffix = targetManager.targetSuffix
|
||||
class Distribution(val target: KonanTarget,
|
||||
propertyFileOverride: String? = null,
|
||||
runtimeFileOverride: String? = null) {
|
||||
|
||||
val localKonanDir = "${File.userHome}/.konan"
|
||||
|
||||
@@ -46,22 +40,10 @@ class Distribution(val targetManager: TargetManager,
|
||||
|
||||
val klib = "$konanHome/klib"
|
||||
val stdlib = "$klib/common/stdlib"
|
||||
|
||||
val targetName = target.visibleName
|
||||
val defaultNatives = "$konanHome/konan/targets/${targetName}/native"
|
||||
val runtime = runtimeFileOverride ?: "$stdlib/targets/${targetName}/native/runtime.bc"
|
||||
|
||||
val dependenciesDir = DependencyProcessor.defaultDependenciesRoot.absolutePath
|
||||
|
||||
val targetProperties = KonanProperties(target, properties, dependenciesDir)
|
||||
|
||||
val llvmHome = targetProperties.absoluteLlvmHome
|
||||
val llvmBin = "$llvmHome/bin"
|
||||
val llvmLib = "$llvmHome/lib"
|
||||
val llvmLto = "$llvmBin/llvm-lto"
|
||||
|
||||
private val libLTODir = when (TargetManager.host) {
|
||||
KonanTarget.MACBOOK, KonanTarget.LINUX -> llvmLib
|
||||
KonanTarget.MINGW -> llvmBin
|
||||
else -> error("Don't know libLTO location for this platform.")
|
||||
}
|
||||
val libLTO = "$libLTODir/${System.mapLibraryName("LTO")}"
|
||||
}
|
||||
|
||||
+8
-10
@@ -52,19 +52,17 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
|
||||
val indirectBranchesAreAllowed = target != KonanTarget.WASM32
|
||||
|
||||
private fun Distribution.prepareDependencies(checkDependencies: Boolean) {
|
||||
if (checkDependencies) {
|
||||
targetProperties.downloadDependencies()
|
||||
internal val distribution = Distribution(target,
|
||||
configuration.get(KonanConfigKeys.PROPERTY_FILE),
|
||||
configuration.get(KonanConfigKeys.RUNTIME_FILE))
|
||||
|
||||
internal val platform = PlatformManager(distribution.properties, distribution.dependenciesDir).platform(target).apply {
|
||||
if (configuration.getBoolean(KonanConfigKeys.CHECK_DEPENDENCIES)) {
|
||||
downloadDependencies()
|
||||
}
|
||||
}
|
||||
|
||||
internal val distribution = Distribution(targetManager,
|
||||
configuration.get(KonanConfigKeys.PROPERTY_FILE),
|
||||
configuration.get(KonanConfigKeys.RUNTIME_FILE)).apply {
|
||||
prepareDependencies(configuration.getBoolean(KonanConfigKeys.CHECK_DEPENDENCIES))
|
||||
}
|
||||
|
||||
internal val clang = TargetClang(distribution.properties, distribution.dependenciesDir, target)
|
||||
internal val clang = platform.clang
|
||||
|
||||
internal val produce get() = configuration.get(KonanConfigKeys.PRODUCE)!!
|
||||
private val prefix = produce.prefix(target)
|
||||
|
||||
+15
-304
@@ -16,310 +16,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import java.lang.ProcessBuilder
|
||||
import java.lang.ProcessBuilder.Redirect
|
||||
import org.jetbrains.kotlin.konan.KonanExternalToolFailure
|
||||
import org.jetbrains.kotlin.konan.exec.Command
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
|
||||
typealias BitcodeFile = String
|
||||
typealias ObjectFile = String
|
||||
typealias ExecutableFile = String
|
||||
|
||||
// Use "clang -v -save-temps" to write linkCommand() method
|
||||
// for another implementation of this class.
|
||||
internal abstract class PlatformFlags(val properties: KonanProperties) {
|
||||
val llvmLtoNooptFlags = properties.llvmLtoNooptFlags
|
||||
val llvmLtoOptFlags = properties.llvmLtoOptFlags
|
||||
val llvmLtoFlags = properties.llvmLtoFlags
|
||||
val llvmLtoDynamicFlags = properties.llvmLtoDynamicFlags
|
||||
val entrySelector = properties.entrySelector
|
||||
val linkerOptimizationFlags = properties.linkerOptimizationFlags
|
||||
val linkerKonanFlags = properties.linkerKonanFlags
|
||||
val linkerNoDebugFlags = properties.linkerNoDebugFlags
|
||||
val linkerDynamicFlags = properties.linkerDynamicFlags
|
||||
val llvmDebugOptFlags = properties.llvmDebugOptFlags
|
||||
val s2wasmFlags = properties.s2wasmFlags
|
||||
val targetToolchain = properties.absoluteTargetToolchain
|
||||
val targetSysRoot = properties.absoluteTargetSysRoot
|
||||
|
||||
val targetLibffi = properties.libffiDir ?.let { listOf("${properties.absoluteLibffiDir}/lib/libffi.a") } ?: emptyList()
|
||||
|
||||
open val useCompilerDriverAsLinker: Boolean get() = false // TODO: refactor.
|
||||
|
||||
abstract fun linkCommand(objectFiles: List<ObjectFile>,
|
||||
executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command
|
||||
|
||||
open fun linkCommandSuffix(): List<String> = emptyList()
|
||||
|
||||
protected fun propertyTargetString(name: String)
|
||||
= properties.targetString(name)!!
|
||||
protected fun propertyTargetList(name: String)
|
||||
= properties.targetList(name)
|
||||
|
||||
abstract fun filterStaticLibraries(binaries: List<String>): List<String>
|
||||
|
||||
open fun linkStaticLibraries(binaries: List<String>): List<String> {
|
||||
val libraries = filterStaticLibraries(binaries)
|
||||
// Let's just pass them as absolute paths
|
||||
return libraries
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal open class AndroidPlatform(distribution: Distribution)
|
||||
: PlatformFlags(distribution.targetProperties) {
|
||||
|
||||
private val prefix = "$targetToolchain/bin/"
|
||||
private val clang = "$prefix/clang"
|
||||
|
||||
override val useCompilerDriverAsLinker: Boolean get() = true
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>)
|
||||
= binaries.filter { it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command {
|
||||
// liblog.so must be linked in, as we use its functionality in runtime.
|
||||
return Command(clang).apply {
|
||||
+ "-o"
|
||||
+ executable
|
||||
+ "-fPIC"
|
||||
+ "-shared"
|
||||
+ "-llog"
|
||||
+ objectFiles
|
||||
if (optimize) + linkerOptimizationFlags
|
||||
if (!debug) + linkerNoDebugFlags
|
||||
if (dynamic) + linkerDynamicFlags
|
||||
+ linkerKonanFlags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal open class MacOSBasedPlatform(distribution: Distribution)
|
||||
: PlatformFlags(distribution.targetProperties) {
|
||||
|
||||
private val linker = "$targetToolchain/usr/bin/ld"
|
||||
internal val dsymutil = "${distribution.llvmBin}/llvm-dsymutil"
|
||||
internal val libLTO = distribution.libLTO
|
||||
|
||||
open val osVersionMin by lazy {
|
||||
listOf(
|
||||
propertyTargetString("osVersionMinFlagLd"),
|
||||
properties.osVersionMin!! + ".0")
|
||||
}
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>)
|
||||
= binaries.filter { it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command {
|
||||
return object : Command(linker) {} .apply {
|
||||
+ "-demangle"
|
||||
+ listOf("-object_path_lto", "temporary.o", "-lto_library", libLTO)
|
||||
+ listOf("-dynamic", "-arch", propertyTargetString("arch"))
|
||||
+ osVersionMin
|
||||
+ listOf("-syslibroot", targetSysRoot, "-o", executable)
|
||||
+ objectFiles
|
||||
if (optimize) + linkerOptimizationFlags
|
||||
if (!debug) + linkerNoDebugFlags
|
||||
if (dynamic) + linkerDynamicFlags
|
||||
+ linkerKonanFlags
|
||||
+ "-lSystem"
|
||||
}
|
||||
}
|
||||
|
||||
fun dsymUtilCommand(executable: ExecutableFile, outputDsymBundle: String) =
|
||||
object : Command(dsymutilCommand(executable, outputDsymBundle)) {
|
||||
override fun runProcess(): Int =
|
||||
executeCommandWithFilter(command)
|
||||
}
|
||||
|
||||
// TODO: consider introducing a better filtering directly in Command.
|
||||
private fun executeCommandWithFilter(command: List<String>): Int {
|
||||
val builder = ProcessBuilder(command)
|
||||
|
||||
// Inherit main process output streams.
|
||||
val isDsymUtil = (command[0] == dsymutil)
|
||||
|
||||
builder.redirectOutput(Redirect.INHERIT)
|
||||
builder.redirectInput(Redirect.INHERIT)
|
||||
if (!isDsymUtil)
|
||||
builder.redirectError(Redirect.INHERIT)
|
||||
|
||||
val process = builder.start()
|
||||
if (isDsymUtil) {
|
||||
/**
|
||||
* llvm-lto has option -alias that lets tool to know which symbol we use instead of _main,
|
||||
* llvm-dsym doesn't have such a option, so we ignore annoying warning manually.
|
||||
*/
|
||||
val errorStream = process.errorStream
|
||||
val outputStream = bufferedReader(errorStream)
|
||||
while (true) {
|
||||
val line = outputStream.readLine() ?: break
|
||||
if (!line.contains("warning: could not find object file symbol for symbol _main"))
|
||||
System.err.println(line)
|
||||
}
|
||||
outputStream.close()
|
||||
}
|
||||
val exitCode = process.waitFor()
|
||||
return exitCode
|
||||
}
|
||||
|
||||
open fun dsymutilCommand(executable: ExecutableFile, outputDsymBundle: String): List<String> =
|
||||
listOf(dsymutil, executable, "-o", outputDsymBundle)
|
||||
|
||||
open fun dsymutilDryRunVerboseCommand(executable: ExecutableFile): List<String> =
|
||||
listOf(dsymutil, "-dump-debug-map" ,executable)
|
||||
}
|
||||
|
||||
internal open class LinuxBasedPlatform(val distribution: Distribution)
|
||||
: PlatformFlags(distribution.targetProperties) {
|
||||
|
||||
private val llvmLib = distribution.llvmLib
|
||||
private val libGcc = "$targetSysRoot/${propertyTargetString("libGcc")}"
|
||||
private val linker = "$targetToolchain/bin/ld.gold"
|
||||
private val pluginOptimizationFlags = propertyTargetList("pluginOptimizationFlags")
|
||||
private val specificLibs
|
||||
= propertyTargetList("abiSpecificLibraries").map { "-L${targetSysRoot}/$it" }
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>)
|
||||
= binaries.filter { it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command {
|
||||
val isMips = (distribution.target == KonanTarget.LINUX_MIPS32 ||
|
||||
distribution.target == KonanTarget.LINUX_MIPSEL32)
|
||||
// TODO: Can we extract more to the konan.properties?
|
||||
return Command(linker).apply {
|
||||
+ "--sysroot=${targetSysRoot}"
|
||||
+ "-export-dynamic"
|
||||
+ "-z"
|
||||
+ "relro"
|
||||
+ "--build-id"
|
||||
+ "--eh-frame-hdr"
|
||||
// + "-m"
|
||||
// + "elf_x86_64",
|
||||
+ "-dynamic-linker"
|
||||
+ propertyTargetString("dynamicLinker")
|
||||
+ "-o"
|
||||
+ executable
|
||||
if (!dynamic) + "$targetSysRoot/usr/lib64/crt1.o"
|
||||
+ "$targetSysRoot/usr/lib64/crti.o"
|
||||
if (dynamic)
|
||||
+ "$libGcc/crtbeginS.o"
|
||||
else
|
||||
+ "$libGcc/crtbegin.o"
|
||||
+ "-L$llvmLib"
|
||||
+ "-L$libGcc"
|
||||
if (!isMips) + "--hash-style=gnu" // MIPS doesn't support hash-style=gnu
|
||||
+ specificLibs
|
||||
+ listOf("-L$targetSysRoot/../lib", "-L$targetSysRoot/lib", "-L$targetSysRoot/usr/lib")
|
||||
if (optimize) {
|
||||
+ "-plugin"
|
||||
+"$llvmLib/LLVMgold.so"
|
||||
+ pluginOptimizationFlags
|
||||
}
|
||||
if (optimize) + linkerOptimizationFlags
|
||||
if (!debug) + linkerNoDebugFlags
|
||||
if (dynamic) + linkerDynamicFlags
|
||||
+ objectFiles
|
||||
+ linkerKonanFlags
|
||||
+ listOf("-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed",
|
||||
"-lc", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed")
|
||||
if (dynamic)
|
||||
+ "$libGcc/crtendS.o"
|
||||
else
|
||||
+ "$libGcc/crtend.o"
|
||||
+ "$targetSysRoot/usr/lib64/crtn.o"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal open class MingwPlatform(distribution: Distribution)
|
||||
: PlatformFlags(distribution.targetProperties) {
|
||||
|
||||
private val linker = "$targetToolchain/bin/clang++"
|
||||
|
||||
override val useCompilerDriverAsLinker: Boolean get() = true
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>)
|
||||
= binaries.filter { it.isWindowsStaticLib || it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command {
|
||||
return Command(linker).apply {
|
||||
+ listOf("-o", executable)
|
||||
+ objectFiles
|
||||
if (optimize) + linkerOptimizationFlags
|
||||
if (!debug) + linkerNoDebugFlags
|
||||
if (dynamic) + linkerDynamicFlags
|
||||
}
|
||||
}
|
||||
|
||||
override fun linkCommandSuffix() = linkerKonanFlags
|
||||
}
|
||||
|
||||
internal open class WasmPlatform(distribution: Distribution)
|
||||
: PlatformFlags(distribution.targetProperties) {
|
||||
|
||||
private val clang = "clang"
|
||||
|
||||
override val useCompilerDriverAsLinker: Boolean get() = false
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>)
|
||||
= binaries.filter{it.isJavaScript}
|
||||
|
||||
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command {
|
||||
return object: Command("") {
|
||||
override fun execute() {
|
||||
val src = File(objectFiles.single())
|
||||
val dst = File(executable)
|
||||
src.recursiveCopyTo(dst)
|
||||
javaScriptLink(args, executable)
|
||||
}
|
||||
|
||||
private fun javaScriptLink(jsFiles: List<String>, executable: String): String {
|
||||
val linkedJavaScript = File("$executable.js")
|
||||
|
||||
val linkerHeader = "var konan = { libraries: [] };\n"
|
||||
val linkerFooter = """|if (isBrowser()) {
|
||||
| konan.moduleEntry([]);
|
||||
|} else {
|
||||
| konan.moduleEntry(arguments);
|
||||
|}""".trimMargin()
|
||||
|
||||
linkedJavaScript.writeBytes(linkerHeader.toByteArray());
|
||||
|
||||
jsFiles.forEach {
|
||||
linkedJavaScript.appendBytes(File(it).readBytes())
|
||||
}
|
||||
|
||||
linkedJavaScript.appendBytes(linkerFooter.toByteArray());
|
||||
return linkedJavaScript.name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class LinkStage(val context: Context) {
|
||||
|
||||
val config = context.config.configuration
|
||||
val target = context.config.targetManager.target
|
||||
|
||||
private val distribution = context.config.distribution
|
||||
|
||||
private val platform = when (target) {
|
||||
KonanTarget.LINUX, KonanTarget.RASPBERRYPI,
|
||||
KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 ->
|
||||
LinuxBasedPlatform(distribution)
|
||||
KonanTarget.MACBOOK, KonanTarget.IPHONE, KonanTarget.IPHONE_SIM ->
|
||||
MacOSBasedPlatform(distribution)
|
||||
KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64 ->
|
||||
AndroidPlatform(distribution)
|
||||
KonanTarget.MINGW ->
|
||||
MingwPlatform(distribution)
|
||||
KonanTarget.WASM32 ->
|
||||
WasmPlatform(distribution)
|
||||
}
|
||||
private val config = context.config.configuration
|
||||
private val target = context.config.targetManager.target
|
||||
private val platform = context.config.platform
|
||||
private val linker = platform.linker
|
||||
|
||||
private val optimize = config.get(KonanConfigKeys.OPTIMIZATION) ?: false
|
||||
private val debug = config.get(KonanConfigKeys.DEBUG) ?: false
|
||||
@@ -341,7 +52,7 @@ internal class LinkStage(val context: Context) {
|
||||
private fun llvmLto(files: List<BitcodeFile>): ObjectFile {
|
||||
val combined = temporary("combined", ".o")
|
||||
|
||||
val tool = distribution.llvmLto
|
||||
val tool = "${platform.absoluteLlvmHome}/bin/llvm-lto"
|
||||
val command = mutableListOf(tool, "-o", combined)
|
||||
command.addNonEmpty(platform.llvmLtoFlags)
|
||||
when {
|
||||
@@ -363,12 +74,12 @@ internal class LinkStage(val context: Context) {
|
||||
}
|
||||
|
||||
private fun targetTool(tool: String, vararg arg: String) {
|
||||
val absoluteToolName = "${platform.targetToolchain}/bin/$tool"
|
||||
val absoluteToolName = "${platform.absoluteTargetToolchain}/bin/$tool"
|
||||
runTool(absoluteToolName, *arg)
|
||||
}
|
||||
|
||||
private fun hostLlvmTool(tool: String, args: List<String>) {
|
||||
val absoluteToolName = "${distribution.llvmBin}/$tool"
|
||||
val absoluteToolName = "${platform.absoluteLlvmHome}/bin/$tool"
|
||||
val command = listOf(absoluteToolName) + args
|
||||
runTool(command)
|
||||
}
|
||||
@@ -380,7 +91,7 @@ internal class LinkStage(val context: Context) {
|
||||
val combinedS = temporary("combined", ".s")
|
||||
targetTool("llc", combinedBc, "-o", combinedS)
|
||||
|
||||
val s2wasmFlags = platform.s2wasmFlags.toTypedArray()
|
||||
val s2wasmFlags = (platform.configurables as WasmConfigurables).s2wasmFlags.toTypedArray()
|
||||
val combinedWast = temporary( "combined", ".wast")
|
||||
targetTool("s2wasm", combinedS, "-o", combinedWast, *s2wasmFlags)
|
||||
|
||||
@@ -392,7 +103,7 @@ internal class LinkStage(val context: Context) {
|
||||
}
|
||||
|
||||
private fun asLinkerArgs(args: List<String>): List<String> {
|
||||
if (platform.useCompilerDriverAsLinker) {
|
||||
if (linker.useCompilerDriverAsLinker) {
|
||||
return args
|
||||
}
|
||||
|
||||
@@ -440,21 +151,21 @@ internal class LinkStage(val context: Context) {
|
||||
}
|
||||
|
||||
try {
|
||||
platform.linkCommand(objectFiles, executable, optimize, debug, dynamic).apply {
|
||||
+ platform.targetLibffi
|
||||
linker.linkCommand(objectFiles, executable, optimize, debug, dynamic).apply {
|
||||
+ linker.targetLibffi
|
||||
+ asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS))
|
||||
+ entryPointSelector
|
||||
+ frameworkLinkerArgs
|
||||
+ platform.linkCommandSuffix()
|
||||
+ platform.linkStaticLibraries(includedBinaries)
|
||||
+ linker.linkCommandSuffix()
|
||||
+ linker.linkStaticLibraries(includedBinaries)
|
||||
+ libraryProvidedLinkerFlags
|
||||
logger = context::log
|
||||
}.execute()
|
||||
|
||||
if (debug && platform is MacOSBasedPlatform) {
|
||||
if (debug && linker is MacOSBasedLinker) {
|
||||
val outputDsymBundle = context.config.outputFile + ".dSYM" // `outputFile` is either binary or bundle.
|
||||
|
||||
platform.dsymUtilCommand(executable, outputDsymBundle)
|
||||
linker.dsymUtilCommand(executable, outputDsymBundle)
|
||||
.logWith(context::log)
|
||||
.execute()
|
||||
}
|
||||
|
||||
+6
-5
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.backend.konan.util.suffixIfNot
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.TargetManager
|
||||
import org.jetbrains.kotlin.konan.util.visibleName
|
||||
|
||||
interface SearchPathResolver {
|
||||
val searchRoots: List<File>
|
||||
@@ -30,13 +31,13 @@ interface SearchPathResolver {
|
||||
fun defaultLinks(nostdlib: Boolean, noDefaultLibs: Boolean): List<File>
|
||||
}
|
||||
|
||||
fun defaultResolver(repositories: List<String>, targetManager: TargetManager): SearchPathResolver =
|
||||
defaultResolver(repositories, Distribution(targetManager))
|
||||
fun defaultResolver(repositories: List<String>, target: KonanTarget): SearchPathResolver =
|
||||
defaultResolver(repositories, Distribution(target))
|
||||
|
||||
fun defaultResolver(repositories: List<String>, distribution: Distribution): SearchPathResolver =
|
||||
KonanLibrarySearchPathResolver(
|
||||
repositories,
|
||||
distribution.targetManager,
|
||||
distribution.target,
|
||||
distribution.klib,
|
||||
distribution.localKonanDir
|
||||
)
|
||||
@@ -133,7 +134,7 @@ fun SearchPathResolver.resolveLibrariesRecursive(libraryNames: List<String>,
|
||||
|
||||
class KonanLibrarySearchPathResolver(
|
||||
repositories: List<String>,
|
||||
val targetManager: TargetManager?,
|
||||
val target: KonanTarget?,
|
||||
val distributionKlib: String?,
|
||||
val localKonanDir: String?,
|
||||
val skipCurrentDir: Boolean = false
|
||||
@@ -146,7 +147,7 @@ class KonanLibrarySearchPathResolver(
|
||||
get() = distributionKlib?.File()?.child("common")
|
||||
|
||||
val distPlatformHead: File?
|
||||
get() = targetManager?.let { distributionKlib?.File()?.child("platform")?.child(targetManager.targetName) }
|
||||
get() = target?.let { distributionKlib?.File()?.child("platform")?.child(target.visibleName) }
|
||||
|
||||
val currentDirHead: File?
|
||||
get() = if (!skipCurrentDir) File.userDir else null
|
||||
|
||||
+3
-1
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.AppleConfigurables
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.isSubpackageOf
|
||||
@@ -102,7 +103,8 @@ internal class ObjCExport(val context: Context) {
|
||||
KonanTarget.MACBOOK -> "MacOSX"
|
||||
else -> error(target)
|
||||
}
|
||||
val minimumOsVersion = context.config.distribution.targetProperties.osVersionMin!!
|
||||
val properties = context.config.platform.configurables as AppleConfigurables
|
||||
val minimumOsVersion = properties.osVersionMin!!
|
||||
|
||||
val contents = StringBuilder()
|
||||
contents.append("""
|
||||
|
||||
@@ -193,9 +193,11 @@ targetToolchain.linux-linux_mips32 = target-gcc-toolchain-2-linux-mips/x86_64-un
|
||||
dependencies.linux-linux_mips32 = \
|
||||
clang-llvm-5.0.0-linux-x86-64 \
|
||||
target-gcc-toolchain-2-linux-mips \
|
||||
target-gcc-toolchain-3-linux-x86-64 \
|
||||
target-sysroot-2-mips \
|
||||
libffi-3.2.1-2-linux-x86-64 \
|
||||
libffi-3.2.1-2-linux-mips
|
||||
|
||||
quadruple.linux_mips32 = mips-unknown-linux-gnu
|
||||
entrySelector.linux_mips32 = --defsym main=Konan_main
|
||||
linkerOptimizationFlags.linux_mips32 = --gc-sections
|
||||
@@ -220,6 +222,7 @@ targetToolchain.linux-linux_mipsel32 = target-gcc-toolchain-2-linux-mips/x86_64-
|
||||
dependencies.linux-linux_mipsel32 = \
|
||||
clang-llvm-5.0.0-linux-x86-64 \
|
||||
target-gcc-toolchain-2-linux-mips \
|
||||
target-gcc-toolchain-3-linux-x86-64 \
|
||||
target-sysroot-2-mipsel \
|
||||
libffi-3.2.1-2-linux-x86-64 \
|
||||
libffi-3.2.1-2-linux-mipsel
|
||||
|
||||
+4
-4
@@ -39,7 +39,7 @@ ext {
|
||||
|
||||
distDir = file('dist')
|
||||
dependenciesDir = DependencyProcessor.defaultDependenciesRoot
|
||||
clangManager = new ClangManager(konanProperties, dependenciesDir.absolutePath)
|
||||
platformManager = new PlatformManager(konanProperties, dependenciesDir.absolutePath)
|
||||
kotlinCompilerModule="org.jetbrains.kotlin:kotlin-compiler:${kotlinCompilerVersion}"
|
||||
kotlinStdLibModule="org.jetbrains.kotlin:kotlin-stdlib:${kotlinStdLibVersion}"
|
||||
kotlinReflectModule="org.jetbrains.kotlin:kotlin-reflect:${kotlinReflectVersion}"
|
||||
@@ -71,7 +71,7 @@ void setupHostAndTarget() {
|
||||
|
||||
void setupClang(Project project) {
|
||||
|
||||
project.convention.plugins.clangManager = project.rootProject.ext.clangManager
|
||||
project.convention.plugins.platformManager = project.rootProject.ext.platformManager
|
||||
project.convention.plugins.execClang = new org.jetbrains.kotlin.ExecClang(project)
|
||||
|
||||
project.plugins.withType(NativeComponentPlugin) {
|
||||
@@ -98,13 +98,13 @@ void setupClang(Project project) {
|
||||
|
||||
toolChains {
|
||||
clang(Clang) {
|
||||
hostClang.hostClangPath.each {
|
||||
hostPlatform.clang.clangPaths.each {
|
||||
path it
|
||||
}
|
||||
|
||||
eachPlatform { // TODO: will not work when cross-compiling
|
||||
[cCompiler, cppCompiler, linker].each {
|
||||
it.withArguments { it.addAll(project.hostClangArgs) }
|
||||
it.withArguments { it.addAll(project.hostPlatform.clang.clangArgs) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class ExecClang {
|
||||
}
|
||||
|
||||
private List<String> konanArgs(KonanTarget target) {
|
||||
return project.rootProject.targetClangArgsForKonanSources(target)
|
||||
return project.rootProject.platform(target).clang.clangArgsForKonanSources
|
||||
}
|
||||
|
||||
private List<String> konanArgs(String target) {
|
||||
@@ -95,7 +95,7 @@ class ExecClang {
|
||||
throw new GradleException("unsupported clang executable: $executable")
|
||||
}
|
||||
|
||||
environment["PATH"] = project.files(project.hostClang.hostClangPath).asPath +
|
||||
environment["PATH"] = project.files(project.hostPlatform.clang.clangPaths).asPath +
|
||||
File.pathSeparator + environment["PATH"]
|
||||
args defaultArgs
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ class NamedNativeInteropConfig implements Named {
|
||||
}
|
||||
|
||||
// TODO: the interop plugin should probably be reworked to execute clang from build scripts directly
|
||||
environment['PATH'] = project.files(project.hostClang.hostClangPath).asPath +
|
||||
environment['PATH'] = project.files(project.hostPlatform.clang.clangPaths).asPath +
|
||||
File.pathSeparator + environment['PATH']
|
||||
|
||||
args compilerOpts.collectMany { ['-copt', it] }
|
||||
|
||||
Vendored
+5
-5
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||
import static org.jetbrains.kotlin.konan.target.KonanTarget.*
|
||||
import static org.jetbrains.kotlin.konan.util.VisibleNamedKt.*
|
||||
import org.jetbrains.kotlin.konan.properties.KonanProperties
|
||||
import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
|
||||
buildscript {
|
||||
@@ -210,14 +210,14 @@ class HelperNativeDep extends TgzNativeDep {
|
||||
|
||||
enum DependencyKind {
|
||||
LLVM( "llvm", { it.llvmHome }, { "llvmDir" } ),
|
||||
GCC_TOOLCHAIN( "gccToolchain", { it.gccToolchain }, { "gccToolchainDir" }),
|
||||
GCC_TOOLCHAIN( "gccToolchain", { (it instanceof LinuxBasedConfigurables) ? it.gccToolchain : null }, { "gccToolchainDir" }),
|
||||
SYSROOT( "sysroot", { it.targetSysRoot } ),
|
||||
LIBFFI( "libffi", { it.libffiDir } ),
|
||||
TARGET_TOOLCHAIN("targetToolchain", { it.targetToolchain } )
|
||||
|
||||
|
||||
DependencyKind(String name,
|
||||
@ClosureParams(value = FromString.class, options = "KonanProperties") Closure<String> dirGetter,
|
||||
@ClosureParams(value = FromString.class, options = "KonanPropertiesLoader") Closure<String> dirGetter,
|
||||
@ClosureParams(value = FromString.class, options = "KonanTarget") Closure<String> propertyNameGetter =
|
||||
{target -> "${getVisibleName(target)}${name.capitalize()}Dir"}) {
|
||||
this.name = name
|
||||
@@ -229,7 +229,7 @@ enum DependencyKind {
|
||||
private Closure<String> dirGetter // KonanProperties -> String
|
||||
private Closure<String> propertyNameGetter // KonanTarget -> String
|
||||
|
||||
String getDirectory(KonanProperties properties) {
|
||||
String getDirectory(KonanPropertiesLoader properties) {
|
||||
return dirGetter(properties)
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ enum DependencyKind {
|
||||
}
|
||||
|
||||
TargetManager.enabled.each { target ->
|
||||
def konanProperties = new KonanProperties(target,
|
||||
def konanProperties = new KonanPropertiesLoader(target,
|
||||
rootProject.ext.konanProperties,
|
||||
rootProject.ext.dependenciesDir.canonicalPath
|
||||
)
|
||||
|
||||
@@ -135,7 +135,7 @@ val currentAbiVersion = 1
|
||||
fun libraryInRepo(repository: File, name: String): File {
|
||||
val resolver = KonanLibrarySearchPathResolver(
|
||||
repositories = listOf(repository.absolutePath),
|
||||
targetManager = null,
|
||||
target = null,
|
||||
distributionKlib = null,
|
||||
localKonanDir = null,
|
||||
skipCurrentDir = true
|
||||
@@ -146,7 +146,7 @@ fun libraryInRepo(repository: File, name: String): File {
|
||||
fun libraryInCurrentDir(name: String): File {
|
||||
val resolver = KonanLibrarySearchPathResolver(
|
||||
repositories = emptyList(),
|
||||
targetManager = null,
|
||||
target = null,
|
||||
distributionKlib = null,
|
||||
localKonanDir = null
|
||||
)
|
||||
@@ -156,7 +156,7 @@ fun libraryInCurrentDir(name: String): File {
|
||||
fun libraryInRepoOrCurrentDir(repository: File, name: String): File {
|
||||
val resolver = KonanLibrarySearchPathResolver(
|
||||
repositories = listOf(repository.absolutePath),
|
||||
targetManager = null,
|
||||
target = null,
|
||||
distributionKlib = null,
|
||||
localKonanDir = null
|
||||
)
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
package org.jetbrains.kotlin.konan.file
|
||||
|
||||
val String.isJavaScript
|
||||
get() = this.endsWith(".js")
|
||||
@@ -16,70 +16,70 @@
|
||||
|
||||
package org.jetbrains.kotlin.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.properties.KonanProperties
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
|
||||
class ClangTargetArgs(val target: KonanTarget, konanProperties: KonanProperties) {
|
||||
class ClangArgs(private val configurables: Configurables) : Configurables by configurables {
|
||||
|
||||
val sysRoot = konanProperties.absoluteTargetSysRoot
|
||||
val targetArg = konanProperties.targetArg
|
||||
val targetArg = if (configurables is NonAppleConfigurables)
|
||||
configurables.targetArg
|
||||
else null
|
||||
|
||||
val specificClangArgs: List<String> get() {
|
||||
val result = when (target) {
|
||||
KonanTarget.LINUX ->
|
||||
listOf("--sysroot=$sysRoot")
|
||||
listOf("--sysroot=$absoluteTargetSysRoot")
|
||||
KonanTarget.RASPBERRYPI ->
|
||||
listOf("-target", targetArg!!,
|
||||
"-mfpu=vfp", "-mfloat-abi=hard",
|
||||
"--sysroot=$sysRoot",
|
||||
"--sysroot=$absoluteTargetSysRoot",
|
||||
// TODO: those two are hacks.
|
||||
"-I$sysRoot/usr/include/c++/4.8.3",
|
||||
"-I$sysRoot/usr/include/c++/4.8.3/arm-linux-gnueabihf")
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.8.3",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.8.3/arm-linux-gnueabihf")
|
||||
|
||||
KonanTarget.LINUX_MIPS32 ->
|
||||
listOf("-target", targetArg!!,
|
||||
"--sysroot=$sysRoot",
|
||||
"-I$sysRoot/usr/include/c++/4.9.4",
|
||||
"-I$sysRoot/usr/include/c++/4.9.4/mips-unknown-linux-gnu")
|
||||
"--sysroot=$absoluteTargetSysRoot",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.4",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.4/mips-unknown-linux-gnu")
|
||||
|
||||
KonanTarget.LINUX_MIPSEL32 ->
|
||||
listOf("-target", targetArg!!,
|
||||
"--sysroot=$sysRoot",
|
||||
"-I$sysRoot/usr/include/c++/4.9.4",
|
||||
"-I$sysRoot/usr/include/c++/4.9.4/mipsel-unknown-linux-gnu")
|
||||
"--sysroot=$absoluteTargetSysRoot",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.4",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.4/mipsel-unknown-linux-gnu")
|
||||
|
||||
KonanTarget.MINGW ->
|
||||
listOf("-target", targetArg!!, "--sysroot=$sysRoot", "-Xclang", "-flto-visibility-public-std")
|
||||
listOf("-target", targetArg!!, "--sysroot=$absoluteTargetSysRoot", "-Xclang", "-flto-visibility-public-std")
|
||||
|
||||
KonanTarget.MACBOOK ->
|
||||
listOf("--sysroot=$sysRoot", "-mmacosx-version-min=10.11")
|
||||
listOf("--sysroot=$absoluteTargetSysRoot", "-mmacosx-version-min=10.11")
|
||||
|
||||
KonanTarget.IPHONE ->
|
||||
listOf("-stdlib=libc++", "-arch", "arm64", "-isysroot", sysRoot, "-miphoneos-version-min=8.0.0")
|
||||
listOf("-stdlib=libc++", "-arch", "arm64", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=8.0.0")
|
||||
|
||||
KonanTarget.IPHONE_SIM ->
|
||||
listOf("-stdlib=libc++", "-isysroot", sysRoot, "-miphoneos-version-min=8.0.0")
|
||||
listOf("-stdlib=libc++", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=8.0.0")
|
||||
|
||||
KonanTarget.ANDROID_ARM32 ->
|
||||
listOf("-target", targetArg!!,
|
||||
"--sysroot=$sysRoot",
|
||||
"--sysroot=$absoluteTargetSysRoot",
|
||||
// HACKS!
|
||||
"-I$sysRoot/usr/include/c++/4.9.x",
|
||||
"-I$sysRoot/usr/include/c++/4.9.x/arm-linux-androideabi")
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.x",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.x/arm-linux-androideabi")
|
||||
|
||||
KonanTarget.ANDROID_ARM64 ->
|
||||
listOf("-target", targetArg!!,
|
||||
"--sysroot=$sysRoot",
|
||||
"--sysroot=$absoluteTargetSysRoot",
|
||||
// HACKS!
|
||||
"-I$sysRoot/usr/include/c++/4.9.x",
|
||||
"-I$sysRoot/usr/include/c++/4.9.x/aarch64-linux-android")
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.x",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.x/aarch64-linux-android")
|
||||
|
||||
KonanTarget.WASM32 ->
|
||||
listOf("-target", targetArg!!, "-O1", "-fno-rtti", "-fno-exceptions",
|
||||
"-D_LIBCPP_ABI_VERSION=2", "-D_LIBCPP_NO_EXCEPTIONS=1",
|
||||
"-nostdinc", "-Xclang", "-nobuiltininc", "-Xclang", "-nostdsysteminc",
|
||||
"-Xclang", "-isystem$sysRoot/include/libcxx", "-Xclang", "-isystem$sysRoot/lib/libcxxabi/include",
|
||||
"-Xclang", "-isystem$sysRoot/include/compat", "-Xclang", "-isystem$sysRoot/include/libc")
|
||||
"-Xclang", "-isystem$absoluteTargetSysRoot/include/libcxx", "-Xclang", "-isystem$absoluteTargetSysRoot/lib/libcxxabi/include",
|
||||
"-Xclang", "-isystem$absoluteTargetSysRoot/include/compat", "-Xclang", "-isystem$absoluteTargetSysRoot/include/libc")
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -119,35 +119,58 @@ class ClangTargetArgs(val target: KonanTarget, konanProperties: KonanProperties)
|
||||
listOf("-DKONAN_WASM=1", "-DKONAN_NO_FFI=1", "-DKONAN_NO_THREADS=1", "-DKONAN_NO_EXCEPTIONS=1",
|
||||
"-DKONAN_INTERNAL_DLMALLOC=1", "-DKONAN_INTERNAL_SNPRINTF=1", "-DKONAN_INTERNAL_NOW=1")
|
||||
}
|
||||
}
|
||||
|
||||
class ClangHostArgs(val hostProperties: KonanProperties) {
|
||||
private val host = TargetManager.host
|
||||
|
||||
val targetToolchain get() = hostProperties.absoluteTargetToolchain
|
||||
val gccToolchain get() = hostProperties.absoluteGccToolchain
|
||||
val sysRoot get() = hostProperties.absoluteTargetSysRoot
|
||||
val llvmDir get() = hostProperties.absoluteLlvmHome
|
||||
|
||||
val binDir = when(TargetManager.host) {
|
||||
KonanTarget.LINUX -> "$targetToolchain/bin"
|
||||
KonanTarget.MINGW -> "$sysRoot/bin"
|
||||
KonanTarget.MACBOOK -> "$targetToolchain/usr/bin"
|
||||
private val binDir = when(host) {
|
||||
KonanTarget.LINUX -> "$absoluteTargetToolchain/bin"
|
||||
KonanTarget.MINGW -> "$absoluteTargetToolchain/bin"
|
||||
KonanTarget.MACBOOK -> "$absoluteTargetToolchain/usr/bin"
|
||||
else -> throw TargetSupportException("Unexpected host platform")
|
||||
}
|
||||
|
||||
private val extraHostClangArgs =
|
||||
if (TargetManager.host == KonanTarget.LINUX) {
|
||||
listOf("--gcc-toolchain=$gccToolchain")
|
||||
if (configurables is LinuxBasedConfigurables) {
|
||||
listOf("--gcc-toolchain=${configurables.absoluteGccToolchain}")
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
val commonClangArgs = listOf("-B$binDir") + extraHostClangArgs
|
||||
|
||||
val hostClangPath = listOf("$llvmDir/bin", binDir)
|
||||
val clangPaths = listOf("$absoluteLlvmHome/bin", binDir)
|
||||
|
||||
private val jdkHome = File.jdkHome.absoluteFile.parent
|
||||
|
||||
val hostCompilerArgsForJni = listOf("", TargetManager.jniHostPlatformIncludeDir).map { "-I$jdkHome/include/$it" }
|
||||
val hostCompilerArgsForJni = listOf("", TargetManager.jniHostPlatformIncludeDir).map { "-I$jdkHome/include/$it" }.toTypedArray()
|
||||
|
||||
val clangArgs =
|
||||
(commonClangArgs + specificClangArgs).toTypedArray()
|
||||
|
||||
val clangArgsForKonanSources =
|
||||
clangArgs + clangArgsSpecificForKonanSources
|
||||
|
||||
val targetLibclangArgs: List<String> get() {
|
||||
// libclang works not exactly the same way as the clang binary and
|
||||
// (in particular) uses different default header search path.
|
||||
// See e.g. http://lists.llvm.org/pipermail/cfe-dev/2013-November/033680.html
|
||||
// We workaround the problem with -isystem flag below.
|
||||
val llvmVersion = llvmVersion
|
||||
val llvmHome = absoluteLlvmHome
|
||||
val isystemArgs = listOf("-isystem", "$llvmHome/lib/clang/$llvmVersion/include")
|
||||
|
||||
return isystemArgs + clangArgs.toList()
|
||||
}
|
||||
|
||||
val targetClangCmd
|
||||
= listOf("${absoluteLlvmHome}/bin/clang") + clangArgs
|
||||
|
||||
val targetClangXXCmd
|
||||
= listOf("${absoluteLlvmHome}/bin/clang++") + clangArgs
|
||||
|
||||
fun clangC(vararg userArgs: String) = targetClangCmd + userArgs.asList()
|
||||
|
||||
fun clangCXX(vararg userArgs: String) = targetClangXXCmd + userArgs.asList()
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,74 +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 -> 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.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
|
||||
class ClangManager(val properties: Properties, val baseDir: String) {
|
||||
private val host = TargetManager.host
|
||||
private val enabledTargets = TargetManager.enabled
|
||||
private val konanProperties = enabledTargets.map {
|
||||
it to KonanProperties(it, properties, baseDir)
|
||||
}.toMap()
|
||||
|
||||
private val targetClangArgs = enabledTargets.map {
|
||||
it to ClangTargetArgs(it, konanProperties[it]!!)
|
||||
}.toMap()
|
||||
|
||||
private val hostClang = ClangHostArgs(konanProperties[host]!!)
|
||||
|
||||
// These are converted to arrays to be convenient
|
||||
// in groovy plugins.
|
||||
val hostClangArgs = (hostClang.commonClangArgs + targetClangArgs[host]!!.specificClangArgs).toTypedArray()
|
||||
|
||||
fun targetClangArgs(target: KonanTarget)
|
||||
= (hostClang.commonClangArgs + targetClangArgs[target]!!.specificClangArgs).toTypedArray()
|
||||
|
||||
fun targetClangArgsForKonanSources(target: KonanTarget) =
|
||||
targetClangArgs(target) + targetClangArgs[target]!!.clangArgsSpecificForKonanSources
|
||||
|
||||
val hostCompilerArgsForJni = hostClang.hostCompilerArgsForJni.toTypedArray()
|
||||
|
||||
fun targetLibclangArgs(target: KonanTarget): List<String> {
|
||||
// libclang works not exactly the same way as the clang binary and
|
||||
// (in particular) uses different default header search path.
|
||||
// See e.g. http://lists.llvm.org/pipermail/cfe-dev/2013-November/033680.html
|
||||
// We workaround the problem with -isystem flag below.
|
||||
val llvmVersion = properties.hostString("llvmVersion")!!
|
||||
val llvmHome = konanProperties[target]!!.absoluteLlvmHome
|
||||
val isystemArgs = listOf("-isystem", "$llvmHome/lib/clang/$llvmVersion/include")
|
||||
|
||||
return isystemArgs + targetClangArgs(target).toList()
|
||||
}
|
||||
|
||||
fun targetClangCmd(target: KonanTarget)
|
||||
= listOf("${hostClang.llvmDir}/bin/clang") + targetClangArgs(target)
|
||||
|
||||
fun targetClangXXCmd(target: KonanTarget)
|
||||
= listOf("${hostClang.llvmDir}/bin/clang++") + targetClangArgs(target)
|
||||
}
|
||||
|
||||
class TargetClang(private val clangManager: ClangManager, private val target: KonanTarget) {
|
||||
constructor (properties: Properties, baseDir: String, target: KonanTarget)
|
||||
: this (ClangManager(properties, baseDir), target)
|
||||
|
||||
fun clangC(vararg userArgs: String) = clangManager.targetClangCmd(target) + userArgs.asList()
|
||||
|
||||
fun clangCXX(vararg userArgs: String) = clangManager.targetClangXXCmd(target) + userArgs.asList()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 -> 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.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
|
||||
interface Configurables : TargetableExternalStorage {
|
||||
|
||||
val target: KonanTarget
|
||||
|
||||
val llvmHome get() = hostString("llvmHome")
|
||||
val llvmVersion get() = hostString("llvmVersion")
|
||||
|
||||
// TODO: Delegate to a map?
|
||||
val llvmLtoNooptFlags get() = targetList("llvmLtoNooptFlags")
|
||||
val llvmLtoOptFlags get() = targetList("llvmLtoOptFlags")
|
||||
val llvmLtoFlags get() = targetList("llvmLtoFlags")
|
||||
val llvmLtoDynamicFlags get() = targetList("llvmLtoDynamicFlags")
|
||||
val entrySelector get() = targetList("entrySelector")
|
||||
val linkerOptimizationFlags get() = targetList("linkerOptimizationFlags")
|
||||
val linkerKonanFlags get() = targetList("linkerKonanFlags")
|
||||
val linkerNoDebugFlags get() = targetList("linkerNoDebugFlags")
|
||||
val linkerDynamicFlags get() = targetList("linkerDynamicFlags")
|
||||
val llvmDebugOptFlags get() = targetList("llvmDebugOptFlags")
|
||||
val targetSysRoot get() = targetString("targetSysRoot")
|
||||
val libffiDir get() = targetString("libffiDir")
|
||||
|
||||
// Notice: these ones are host-target.
|
||||
val targetToolchain get() = hostTargetString("targetToolchain")
|
||||
|
||||
val absoluteTargetSysRoot get() = absolute(targetSysRoot)
|
||||
val absoluteTargetToolchain get() = absolute(targetToolchain)
|
||||
val absoluteLlvmHome get() = absolute(llvmHome)
|
||||
val absoluteLibffiDir get() = absolute(libffiDir)
|
||||
}
|
||||
|
||||
interface NonAppleConfigurables : Configurables {
|
||||
val targetArg get() = targetString("quadruple")
|
||||
}
|
||||
|
||||
interface AppleConfigurables : Configurables {
|
||||
val arch get() = targetString("arch")!!
|
||||
val osVersionMin get() = targetString("osVersionMin")!!
|
||||
val osVersionMinFlagLd get() = targetString("osVersionMinFlagLd")!!
|
||||
}
|
||||
|
||||
interface MingwConfigurables : NonAppleConfigurables
|
||||
|
||||
interface LinuxBasedConfigurables : NonAppleConfigurables {
|
||||
val gccToolchain get() = hostString("gccToolchain")
|
||||
val absoluteGccToolchain get() = absolute(gccToolchain)
|
||||
|
||||
val libGcc get() = targetString("libGcc")!!
|
||||
val dynamicLinker get() = targetString("dynamicLinker")!!
|
||||
val pluginOptimizationFlags get() = targetList("pluginOptimizationFlags")
|
||||
val abiSpecificLibraries get() = targetList("abiSpecificLibraries")
|
||||
}
|
||||
|
||||
interface LinuxConfigurables : LinuxBasedConfigurables
|
||||
interface LinuxMIPSConfigurables : LinuxBasedConfigurables
|
||||
interface RaspberryPiConfigurables : LinuxBasedConfigurables
|
||||
interface AndroidConfigurables : NonAppleConfigurables
|
||||
|
||||
interface WasmConfigurables : NonAppleConfigurables {
|
||||
val s2wasmFlags get() = targetList("s2wasmFlags")
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 -> 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.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
|
||||
class LinuxConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: LinuxConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
class LinuxMIPSConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: LinuxMIPSConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
class AndroidConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: AndroidConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
class AppleConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: AppleConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
class MingwConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: MingwConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
class WasmConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: WasmConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
|
||||
fun loadConfigurables(target: KonanTarget, properties: Properties, baseDir: String?) = when (target) {
|
||||
KonanTarget.LINUX, KonanTarget.RASPBERRYPI ->
|
||||
LinuxConfigurablesImpl(target, properties, baseDir)
|
||||
KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 ->
|
||||
LinuxMIPSConfigurablesImpl(target, properties, baseDir)
|
||||
KonanTarget.MACBOOK, KonanTarget.IPHONE, KonanTarget.IPHONE_SIM ->
|
||||
AppleConfigurablesImpl(target, properties, baseDir)
|
||||
KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64 ->
|
||||
AndroidConfigurablesImpl(target, properties, baseDir)
|
||||
KonanTarget.MINGW ->
|
||||
MingwConfigurablesImpl(target, properties, baseDir)
|
||||
KonanTarget.WASM32 ->
|
||||
WasmConfigurablesImpl(target, properties, baseDir)
|
||||
}
|
||||
|
||||
@@ -16,73 +16,44 @@
|
||||
|
||||
package org.jetbrains.kotlin.konan.properties
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.Configurables
|
||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||
|
||||
class KonanProperties(val target: KonanTarget, val properties: Properties, val baseDir: String? = null) {
|
||||
interface TargetableExternalStorage {
|
||||
fun targetString(key: String): String?
|
||||
fun targetList(key: String): List<String>
|
||||
fun hostString(key: String): String?
|
||||
fun hostList(key: String): List<String>
|
||||
fun hostTargetString(key: String): String?
|
||||
fun hostTargetList(key: String): List<String>
|
||||
fun absolute(value: String?): String
|
||||
fun downloadDependencies()
|
||||
}
|
||||
|
||||
fun downloadDependencies() {
|
||||
open class KonanPropertiesLoader(override val target: KonanTarget, val properties: Properties, val baseDir: String? = null) : Configurables {
|
||||
val dependencies get() = hostTargetList("dependencies")
|
||||
|
||||
override fun downloadDependencies() {
|
||||
dependencyProcessor!!.run()
|
||||
}
|
||||
|
||||
fun targetString(key: String): String?
|
||||
override fun targetString(key: String): String?
|
||||
= properties.targetString(key, target)
|
||||
fun targetList(key: String): List<String>
|
||||
override fun targetList(key: String): List<String>
|
||||
= properties.targetList(key, target)
|
||||
fun hostString(key: String): String?
|
||||
override fun hostString(key: String): String?
|
||||
= properties.hostString(key)
|
||||
fun hostList(key: String): List<String>
|
||||
override fun hostList(key: String): List<String>
|
||||
= properties.hostList(key)
|
||||
fun hostTargetString(key: String): String?
|
||||
override fun hostTargetString(key: String): String?
|
||||
= properties.hostTargetString(key, target)
|
||||
fun hostTargetList(key: String): List<String>
|
||||
override fun hostTargetList(key: String): List<String>
|
||||
= properties.hostTargetList(key, target)
|
||||
|
||||
val llvmHome get() = hostString("llvmHome")
|
||||
|
||||
// TODO: Delegate to a map?
|
||||
val llvmLtoNooptFlags get() = targetList("llvmLtoNooptFlags")
|
||||
val llvmLtoOptFlags get() = targetList("llvmLtoOptFlags")
|
||||
val llvmLtoFlags get() = targetList("llvmLtoFlags")
|
||||
val llvmLtoDynamicFlags get() = targetList("llvmLtoDynamicFlags")
|
||||
val entrySelector get() = targetList("entrySelector")
|
||||
val linkerOptimizationFlags get() = targetList("linkerOptimizationFlags")
|
||||
val linkerKonanFlags get() = targetList("linkerKonanFlags")
|
||||
val linkerNoDebugFlags get() = targetList("linkerNoDebugFlags")
|
||||
val linkerDynamicFlags get() = targetList("linkerDynamicFlags")
|
||||
val llvmDebugOptFlags get() = targetList("llvmDebugOptFlags")
|
||||
val s2wasmFlags get() = targetList("s2wasmFlags")
|
||||
|
||||
val targetSysRoot get() = targetString("targetSysRoot")
|
||||
val libffiDir get() = targetString("libffiDir")
|
||||
val gccToolchain get() = targetString("gccToolchain")
|
||||
val targetArg get() = targetString("quadruple")
|
||||
// Notice: these ones are host-target.
|
||||
val targetToolchain get() = hostTargetString("targetToolchain")
|
||||
val dependencies get() = hostTargetList("dependencies")
|
||||
|
||||
private fun absolute(value: String?): String =
|
||||
override fun absolute(value: String?): String =
|
||||
dependencyProcessor!!.resolveRelative(value!!).absolutePath
|
||||
|
||||
val absoluteTargetSysRoot get() = absolute(targetSysRoot)
|
||||
val absoluteTargetToolchain get() = absolute(targetToolchain)
|
||||
val absoluteGccToolchain get() = absolute(gccToolchain)
|
||||
val absoluteLlvmHome get() = absolute(llvmHome)
|
||||
val absoluteLibffiDir get() = absolute(libffiDir)
|
||||
|
||||
val mingwWithLlvm: String?
|
||||
get() {
|
||||
if (target != KonanTarget.MINGW) {
|
||||
error("Only mingw target can have '.mingwWithLlvm' property")
|
||||
}
|
||||
// TODO: make it a property in the konan.properties.
|
||||
// Use (equal) llvmHome fow now.
|
||||
return targetString("llvmHome")
|
||||
}
|
||||
|
||||
val osVersionMin: String? get() = targetString("osVersionMin")
|
||||
|
||||
private val dependencyProcessor = baseDir?.let { DependencyProcessor(java.io.File(it), this) }
|
||||
|
||||
private val dependencyProcessor by lazy {
|
||||
baseDir?.let { DependencyProcessor(java.io.File(it), this) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* 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.konan.target
|
||||
|
||||
import java.lang.ProcessBuilder
|
||||
import java.lang.ProcessBuilder.Redirect
|
||||
import org.jetbrains.kotlin.konan.exec.Command
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
|
||||
typealias BitcodeFile = String
|
||||
typealias ObjectFile = String
|
||||
typealias ExecutableFile = String
|
||||
|
||||
// Use "clang -v -save-temps" to write linkCommand() method
|
||||
// for another implementation of this class.
|
||||
abstract class LinkerFlags(val configurables: Configurables)
|
||||
/* : Configurables by configurables */{
|
||||
|
||||
protected val llvmBin = "${configurables.absoluteLlvmHome}/bin"
|
||||
protected val llvmLib = "${configurables.absoluteLlvmHome}/lib"
|
||||
|
||||
private val libLTODir = when (TargetManager.host) {
|
||||
KonanTarget.MACBOOK, KonanTarget.LINUX -> llvmLib
|
||||
KonanTarget.MINGW -> llvmBin
|
||||
else -> error("Don't know libLTO location for this platform.")
|
||||
}
|
||||
|
||||
val libLTO = "$libLTODir/${System.mapLibraryName("LTO")}"
|
||||
|
||||
val targetLibffi = configurables.libffiDir ?.let { listOf("${configurables.absoluteLibffiDir}/lib/libffi.a") } ?: emptyList()
|
||||
|
||||
open val useCompilerDriverAsLinker: Boolean get() = false // TODO: refactor.
|
||||
|
||||
abstract fun linkCommand(objectFiles: List<ObjectFile>,
|
||||
executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command
|
||||
|
||||
open fun linkCommandSuffix(): List<String> = emptyList()
|
||||
|
||||
abstract fun filterStaticLibraries(binaries: List<String>): List<String>
|
||||
|
||||
open fun linkStaticLibraries(binaries: List<String>): List<String> {
|
||||
val libraries = filterStaticLibraries(binaries)
|
||||
// Let's just pass them as absolute paths
|
||||
return libraries
|
||||
}
|
||||
}
|
||||
|
||||
open class AndroidLinker(targetProperties: AndroidConfigurables)
|
||||
: LinkerFlags(targetProperties), AndroidConfigurables by targetProperties {
|
||||
|
||||
private val prefix = "$absoluteTargetToolchain/bin/"
|
||||
private val clang = "$prefix/clang"
|
||||
|
||||
override val useCompilerDriverAsLinker: Boolean get() = true
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>)
|
||||
= binaries.filter { it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command {
|
||||
// liblog.so must be linked in, as we use its functionality in runtime.
|
||||
return Command(clang).apply {
|
||||
+ "-o"
|
||||
+ executable
|
||||
+ "-fPIC"
|
||||
+ "-shared"
|
||||
+ "-llog"
|
||||
+ objectFiles
|
||||
if (optimize) + linkerOptimizationFlags
|
||||
if (!debug) + linkerNoDebugFlags
|
||||
if (dynamic) + linkerDynamicFlags
|
||||
+ linkerKonanFlags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
: LinkerFlags(targetProperties), AppleConfigurables by targetProperties {
|
||||
|
||||
private val linker = "$absoluteTargetToolchain/usr/bin/ld"
|
||||
internal val dsymutil = "$absoluteLlvmHome/bin/llvm-dsymutil"
|
||||
|
||||
open val osVersionMinFlags: List<String> by lazy {
|
||||
listOf(
|
||||
osVersionMinFlagLd,
|
||||
osVersionMin + ".0")
|
||||
}
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>)
|
||||
= binaries.filter { it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command {
|
||||
return object : Command(linker) {} .apply {
|
||||
+ "-demangle"
|
||||
+ listOf("-object_path_lto", "temporary.o", "-lto_library", libLTO)
|
||||
+ listOf("-dynamic", "-arch", arch)
|
||||
+ osVersionMinFlags
|
||||
+ listOf("-syslibroot", absoluteTargetSysRoot, "-o", executable)
|
||||
+ objectFiles
|
||||
if (optimize) + linkerOptimizationFlags
|
||||
if (!debug) + linkerNoDebugFlags
|
||||
if (dynamic) + linkerDynamicFlags
|
||||
+ linkerKonanFlags
|
||||
+ "-lSystem"
|
||||
}
|
||||
}
|
||||
|
||||
fun dsymUtilCommand(executable: ExecutableFile, outputDsymBundle: String) =
|
||||
object : Command(dsymutilCommand(executable, outputDsymBundle)) {
|
||||
override fun runProcess(): Int =
|
||||
executeCommandWithFilter(command)
|
||||
}
|
||||
|
||||
// TODO: consider introducing a better filtering directly in Command.
|
||||
private fun executeCommandWithFilter(command: List<String>): Int {
|
||||
val builder = ProcessBuilder(command)
|
||||
|
||||
// Inherit main process output streams.
|
||||
val isDsymUtil = (command[0] == dsymutil)
|
||||
|
||||
builder.redirectOutput(Redirect.INHERIT)
|
||||
builder.redirectInput(Redirect.INHERIT)
|
||||
if (!isDsymUtil)
|
||||
builder.redirectError(Redirect.INHERIT)
|
||||
|
||||
val process = builder.start()
|
||||
if (isDsymUtil) {
|
||||
/**
|
||||
* llvm-lto has option -alias that lets tool to know which symbol we use instead of _main,
|
||||
* llvm-dsym doesn't have such a option, so we ignore annoying warning manually.
|
||||
*/
|
||||
val errorStream = process.errorStream
|
||||
val outputStream = bufferedReader(errorStream)
|
||||
while (true) {
|
||||
val line = outputStream.readLine() ?: break
|
||||
if (!line.contains("warning: could not find object file symbol for symbol _main"))
|
||||
System.err.println(line)
|
||||
}
|
||||
outputStream.close()
|
||||
}
|
||||
val exitCode = process.waitFor()
|
||||
return exitCode
|
||||
}
|
||||
|
||||
open fun dsymutilCommand(executable: ExecutableFile, outputDsymBundle: String): List<String> =
|
||||
listOf(dsymutil, executable, "-o", outputDsymBundle)
|
||||
|
||||
open fun dsymutilDryRunVerboseCommand(executable: ExecutableFile): List<String> =
|
||||
listOf(dsymutil, "-dump-debug-map" ,executable)
|
||||
}
|
||||
|
||||
open class LinuxBasedLinker(targetProperties: LinuxBasedConfigurables)
|
||||
: LinkerFlags(targetProperties), LinuxBasedConfigurables by targetProperties {
|
||||
|
||||
override val libGcc: String = "$absoluteTargetSysRoot/${super.libGcc}"
|
||||
private val linker = "$absoluteTargetToolchain/bin/ld.gold"
|
||||
private val specificLibs
|
||||
= abiSpecificLibraries.map { "-L${absoluteTargetSysRoot}/$it" }
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>)
|
||||
= binaries.filter { it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command {
|
||||
val isMips = (configurables is LinuxMIPSConfigurables)
|
||||
|
||||
// TODO: Can we extract more to the konan.configurables?
|
||||
return Command(linker).apply {
|
||||
+ "--sysroot=${absoluteTargetSysRoot}"
|
||||
+ "-export-dynamic"
|
||||
+ "-z"
|
||||
+ "relro"
|
||||
+ "--build-id"
|
||||
+ "--eh-frame-hdr"
|
||||
+ "-dynamic-linker"
|
||||
+ dynamicLinker
|
||||
+ "-o"
|
||||
+ executable
|
||||
if (!dynamic) + "$absoluteTargetSysRoot/usr/lib64/crt1.o"
|
||||
+ "$absoluteTargetSysRoot/usr/lib64/crti.o"
|
||||
if (dynamic)
|
||||
+ "$libGcc/crtbeginS.o"
|
||||
else
|
||||
+ "$libGcc/crtbegin.o"
|
||||
+ "-L$llvmLib"
|
||||
+ "-L$libGcc"
|
||||
if (!isMips) + "--hash-style=gnu" // MIPS doesn't support hash-style=gnu
|
||||
+ specificLibs
|
||||
+ listOf("-L$absoluteTargetSysRoot/../lib", "-L$absoluteTargetSysRoot/lib", "-L$absoluteTargetSysRoot/usr/lib")
|
||||
if (optimize) {
|
||||
+ "-plugin"
|
||||
+"$llvmLib/LLVMgold.so"
|
||||
+ pluginOptimizationFlags
|
||||
}
|
||||
if (optimize) + linkerOptimizationFlags
|
||||
if (!debug) + linkerNoDebugFlags
|
||||
if (dynamic) + linkerDynamicFlags
|
||||
+ objectFiles
|
||||
+ linkerKonanFlags
|
||||
+ listOf("-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed",
|
||||
"-lc", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed")
|
||||
if (dynamic)
|
||||
+ "$libGcc/crtendS.o"
|
||||
else
|
||||
+ "$libGcc/crtend.o"
|
||||
+ "$absoluteTargetSysRoot/usr/lib64/crtn.o"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class MingwLinker(targetProperties: MingwConfigurables)
|
||||
: LinkerFlags(targetProperties), MingwConfigurables by targetProperties {
|
||||
|
||||
private val linker = "$absoluteTargetToolchain/bin/clang++"
|
||||
|
||||
override val useCompilerDriverAsLinker: Boolean get() = true
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>)
|
||||
= binaries.filter { it.isWindowsStaticLib || it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command {
|
||||
return Command(linker).apply {
|
||||
+ listOf("-o", executable)
|
||||
+ objectFiles
|
||||
if (optimize) + linkerOptimizationFlags
|
||||
if (!debug) + linkerNoDebugFlags
|
||||
if (dynamic) + linkerDynamicFlags
|
||||
}
|
||||
}
|
||||
|
||||
override fun linkCommandSuffix() = linkerKonanFlags
|
||||
}
|
||||
|
||||
open class WasmLinker(targetProperties: WasmConfigurables)
|
||||
: LinkerFlags(targetProperties), WasmConfigurables by targetProperties {
|
||||
|
||||
private val clang = "clang"
|
||||
|
||||
override val useCompilerDriverAsLinker: Boolean get() = false
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>)
|
||||
= binaries.filter{it.isJavaScript}
|
||||
|
||||
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command {
|
||||
return object: Command("") {
|
||||
override fun execute() {
|
||||
val src = File(objectFiles.single())
|
||||
val dst = File(executable)
|
||||
src.recursiveCopyTo(dst)
|
||||
javaScriptLink(args, executable)
|
||||
}
|
||||
|
||||
private fun javaScriptLink(jsFiles: List<String>, executable: String): String {
|
||||
val linkedJavaScript = File("$executable.js")
|
||||
|
||||
val linkerHeader = "var konan = { libraries: [] };\n"
|
||||
val linkerFooter = """|if (isBrowser()) {
|
||||
| konan.moduleEntry([]);
|
||||
|} else {
|
||||
| konan.moduleEntry(arguments);
|
||||
|}""".trimMargin()
|
||||
|
||||
linkedJavaScript.writeBytes(linkerHeader.toByteArray());
|
||||
|
||||
jsFiles.forEach {
|
||||
linkedJavaScript.appendBytes(File(it).readBytes())
|
||||
}
|
||||
|
||||
linkedJavaScript.appendBytes(linkerFooter.toByteArray());
|
||||
return linkedJavaScript.name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun linker(configurables: Configurables): LinkerFlags =
|
||||
when (configurables.target) {
|
||||
KonanTarget.LINUX, KonanTarget.RASPBERRYPI ->
|
||||
LinuxBasedLinker(configurables as LinuxConfigurables)
|
||||
KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 ->
|
||||
LinuxBasedLinker(configurables as LinuxMIPSConfigurables)
|
||||
KonanTarget.MACBOOK, KonanTarget.IPHONE, KonanTarget.IPHONE_SIM ->
|
||||
MacOSBasedLinker(configurables as AppleConfigurables)
|
||||
KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64 ->
|
||||
AndroidLinker(configurables as AndroidConfigurables)
|
||||
KonanTarget.MINGW ->
|
||||
MingwLinker(configurables as MingwConfigurables)
|
||||
KonanTarget.WASM32 ->
|
||||
WasmLinker(configurables as WasmConfigurables)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2010-2018 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.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
|
||||
class Platform(val configurables: Configurables)
|
||||
: Configurables by configurables {
|
||||
|
||||
val clang by lazy {
|
||||
ClangArgs(configurables)
|
||||
}
|
||||
val linker by lazy {
|
||||
linker(configurables)
|
||||
}
|
||||
}
|
||||
|
||||
class PlatformManager(properties: Properties, baseDir: String) {
|
||||
private val host = TargetManager.host
|
||||
private val platforms = TargetManager.enabled.map {
|
||||
it to Platform(loadConfigurables(it, properties, baseDir))
|
||||
}.toMap()
|
||||
|
||||
fun platform(target: KonanTarget) = platforms[target]!!
|
||||
val hostPlatform = platforms[host]!!
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.jetbrains.kotlin.konan.util
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.use
|
||||
import org.jetbrains.kotlin.konan.properties.KonanProperties
|
||||
import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader
|
||||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
import org.jetbrains.kotlin.konan.properties.propertyList
|
||||
import java.io.File
|
||||
@@ -69,11 +69,11 @@ private fun Properties.findCandidates(dependencies: List<String>): Map<String, L
|
||||
}
|
||||
|
||||
|
||||
private val KonanProperties.dependenciesUrl : String get() = properties.dependenciesUrl
|
||||
private val KonanProperties.airplaneMode : Boolean get() = properties.airplaneMode
|
||||
private val KonanProperties.downloadingAttempts : Int get() = properties.downloadingAttempts
|
||||
private val KonanProperties.downloadingAttemptIntervalMs : Long get() = properties.downloadingAttemptIntervalMs
|
||||
private val KonanProperties.homeDependencyCache : String get() = properties.homeDependencyCache
|
||||
private val KonanPropertiesLoader.dependenciesUrl : String get() = properties.dependenciesUrl
|
||||
private val KonanPropertiesLoader.airplaneMode : Boolean get() = properties.airplaneMode
|
||||
private val KonanPropertiesLoader.downloadingAttempts : Int get() = properties.downloadingAttempts
|
||||
private val KonanPropertiesLoader.downloadingAttemptIntervalMs : Long get() = properties.downloadingAttemptIntervalMs
|
||||
private val KonanPropertiesLoader.homeDependencyCache : String get() = properties.homeDependencyCache
|
||||
|
||||
sealed class DependencySource {
|
||||
data class Local(val path: File) : DependencySource()
|
||||
@@ -114,7 +114,7 @@ class DependencyProcessor(dependenciesRoot: File,
|
||||
private val archiveExtension get() = extractor.archiveExtension
|
||||
|
||||
constructor(dependenciesRoot: File,
|
||||
properties: KonanProperties,
|
||||
properties: KonanPropertiesLoader,
|
||||
dependenciesUrl: String = properties.dependenciesUrl,
|
||||
keepUnstable:Boolean = true) : this(
|
||||
dependenciesRoot,
|
||||
|
||||
@@ -65,7 +65,7 @@ fun invokeInterop(flavor: String, args: Array<String>): Array<String> {
|
||||
val manifest = File(buildDir, "manifest.properties")
|
||||
|
||||
val targetManager = TargetManager(target)
|
||||
val resolver = defaultResolver(repos, targetManager)
|
||||
val resolver = defaultResolver(repos, targetManager.target)
|
||||
val allLibraries = resolver.resolveLibrariesRecursive(
|
||||
libraries, targetManager.target, noStdLib = true, noDefaultLibs = noDefaultLibs
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user