Android NDK support and build system refactoring (#585)
This commit is contained in:
+1
-1
@@ -169,7 +169,7 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
||||
}
|
||||
|
||||
|
||||
if (name == "__gnuc_va_list" || name == "va_list") {
|
||||
if (name == "__gnuc_va_list" || name == "va_list" || name == "__va_list") {
|
||||
// TODO: fix GNUC varargs support.
|
||||
return UnsupportedType
|
||||
}
|
||||
|
||||
+69
-66
@@ -26,10 +26,9 @@ import kotlin.reflect.KFunction
|
||||
fun main(args: Array<String>) {
|
||||
val konanHome = File(System.getProperty("konan.home")).absolutePath
|
||||
|
||||
// TODO: remove OSX defaults.
|
||||
val substitutions = mapOf(
|
||||
"arch" to (System.getenv("TARGET_ARCH") ?: "x86-64"),
|
||||
"os" to (System.getenv("TARGET_OS") ?: detectHost())
|
||||
"os" to (System.getenv("TARGET_OS") ?: host)
|
||||
)
|
||||
|
||||
processLib(konanHome, substitutions, parseArgs(args))
|
||||
@@ -37,46 +36,54 @@ fun main(args: Array<String>) {
|
||||
|
||||
private fun parseArgs(args: Array<String>): Map<String, List<String>> {
|
||||
val commandLine = mutableMapOf<String, MutableList<String>>()
|
||||
for(index in 0..args.size-1 step 2) {
|
||||
for (index in 0..args.size - 1 step 2) {
|
||||
val key = args[index]
|
||||
if (key[0] != '-') {
|
||||
throw IllegalArgumentException("Expected a flag with initial dash: $key")
|
||||
}
|
||||
if (index+1 == args.size) {
|
||||
if (index + 1 == args.size) {
|
||||
throw IllegalArgumentException("Expected an value after $key")
|
||||
}
|
||||
val value = args[index+1]
|
||||
commandLine[key] ?. add(value) ?: commandLine.put(key, mutableListOf(value))
|
||||
val value = args[index + 1]
|
||||
commandLine[key]?.add(value) ?: commandLine.put(key, mutableListOf(value))
|
||||
}
|
||||
return commandLine
|
||||
}
|
||||
|
||||
private fun detectHost(): String {
|
||||
private val host: String by lazy {
|
||||
val os = System.getProperty("os.name")
|
||||
when (os) {
|
||||
"Linux" -> return "linux"
|
||||
"Windows" -> return "win"
|
||||
"Mac OS X" -> return "osx"
|
||||
"FreeBSD" -> return "freebsd"
|
||||
"Linux" -> "linux"
|
||||
"Windows" -> "win"
|
||||
"Mac OS X" -> "osx"
|
||||
"FreeBSD" -> "freebsd"
|
||||
else -> {
|
||||
throw IllegalArgumentException("we don't know ${os} value")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun defaultTarget() = detectHost()
|
||||
private val defaultTarget: String by lazy {
|
||||
host
|
||||
}
|
||||
|
||||
// TODO: share KonanTarget class here.
|
||||
private val knownTargets = mapOf(
|
||||
"host" to defaultTarget(),
|
||||
"linux" to "linux",
|
||||
"macbook" to "osx",
|
||||
"iphone" to "osx-ios",
|
||||
"iphone_sim" to "osx-ios-sim",
|
||||
"raspberrypi" to "linux-raspberrypi")
|
||||
"host" to host,
|
||||
"linux" to "linux",
|
||||
"macbook" to "osx",
|
||||
"osx" to "osx",
|
||||
"iphone" to "ios",
|
||||
"ios" to "ios",
|
||||
"iphone_sim" to "ios_sim",
|
||||
"ios_sim" to "ios_sim",
|
||||
"raspberrypi" to "raspberrypi",
|
||||
"android_arm32" to "android_arm32"
|
||||
)
|
||||
|
||||
|
||||
private fun String.targetSuffix(): String =
|
||||
knownTargets[this] ?: error("Unsupported target $this.")
|
||||
knownTargets[this] ?: error("Unsupported target $this.")
|
||||
|
||||
// Performs substitution similar to:
|
||||
// foo = ${foo} ${foo.${arch}} ${foo.${os}}
|
||||
@@ -118,11 +125,17 @@ private fun String.matchesToGlob(glob: String): Boolean =
|
||||
java.nio.file.FileSystems.getDefault()
|
||||
.getPathMatcher("glob:$glob").matches(java.nio.file.Paths.get(this))
|
||||
|
||||
private fun Properties.getOsSpecific(name: String,
|
||||
host: String = detectHost()): String? {
|
||||
private fun Properties.getHostSpecific(
|
||||
name: String) = getProperty("$name.$host")
|
||||
|
||||
return this.getProperty("$name.$host")
|
||||
}
|
||||
private fun Properties.getTargetSpecific(
|
||||
name: String, target: String) = getProperty("$name.$target")
|
||||
|
||||
private fun Properties.getHostTargetSpecific(
|
||||
name: String, target: String) = if (host != target)
|
||||
getProperty("$name.$host-$target")
|
||||
else
|
||||
getProperty("$name.$host")
|
||||
|
||||
private fun List<String>?.isTrue(): Boolean {
|
||||
// The rightmost wins, null != "true".
|
||||
@@ -176,51 +189,41 @@ private fun maybeExecuteHelper(dependenciesRoot: String, properties: Properties,
|
||||
}
|
||||
|
||||
private fun Properties.defaultCompilerOpts(target: String, dependencies: String): List<String> {
|
||||
|
||||
val arch = this.getOsSpecific("arch", target)!!
|
||||
val hostSysRootDir = this.getOsSpecific("sysRoot")!!
|
||||
val hostSysRoot = "$dependencies/$hostSysRootDir"
|
||||
val targetSysRootDir = this.getOsSpecific("targetSysRoot", target) ?: hostSysRootDir
|
||||
val targetToolchainDir = getHostTargetSpecific("targetToolchain", target)!!
|
||||
val targetToolchain = "$dependencies/$targetToolchainDir"
|
||||
val targetSysRootDir = getTargetSpecific("targetSysRoot", target)!!
|
||||
val targetSysRoot = "$dependencies/$targetSysRootDir"
|
||||
val sysRoot = targetSysRoot
|
||||
val llvmHomeDir = this.getOsSpecific("llvmHome")!!
|
||||
val llvmHomeDir = getHostSpecific("llvmHome")!!
|
||||
val llvmHome = "$dependencies/$llvmHomeDir"
|
||||
|
||||
System.load("$llvmHome/lib/${System.mapLibraryName("clang")}")
|
||||
|
||||
val llvmVersion = this.getProperty("llvmVersion")!!
|
||||
val llvmVersion = getProperty("llvmVersion")!!
|
||||
|
||||
// StubGenerator passes the arguments to libclang which
|
||||
// works not exactly the same way as the clang binary and
|
||||
// StubGenerator passes the arguments to libclang which
|
||||
// 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 isystem = "$llvmHome/lib/clang/$llvmVersion/include"
|
||||
|
||||
when (detectHost()) {
|
||||
val quadruple = getTargetSpecific("quadruple", target)
|
||||
val arch = getTargetSpecific("arch", target)
|
||||
val archSelector = if (quadruple != null)
|
||||
listOf("-target", quadruple) else listOf("-arch", arch!!)
|
||||
val commonArgs = listOf("-isystem", isystem, "--sysroot=$targetSysRoot")
|
||||
when (host) {
|
||||
"osx" -> {
|
||||
val osVersionMinFlag = this.getOsSpecific("osVersionMinFlagClang", target)!!
|
||||
val osVersionMinValue = this.getOsSpecific("osVersionMin", target)!!
|
||||
|
||||
return listOf(
|
||||
"-arch", arch,
|
||||
"-isystem", isystem,
|
||||
"-B$hostSysRoot/usr/bin",
|
||||
"--sysroot=$sysRoot",
|
||||
"$osVersionMinFlag=$osVersionMinValue")
|
||||
val osVersionMinFlag = getTargetSpecific("osVersionMinFlagClang", target)
|
||||
val osVersionMinValue = getTargetSpecific("osVersionMin", target)
|
||||
return archSelector + commonArgs + listOf("-B$targetToolchain/bin") +
|
||||
(if (osVersionMinFlag != null && osVersionMinValue != null)
|
||||
listOf("$osVersionMinFlag=$osVersionMinValue") else emptyList())
|
||||
}
|
||||
"linux" -> {
|
||||
val gccToolChainDir = this.getOsSpecific("gccToolChain", target)!!
|
||||
val gccToolChain= "$dependencies/$gccToolChainDir"
|
||||
val quadruple = this.getOsSpecific("quadruple", target)!!
|
||||
|
||||
return listOf(
|
||||
"-target", quadruple,
|
||||
"-isystem", isystem,
|
||||
"--gcc-toolchain=$gccToolChain",
|
||||
"-L$llvmHome/lib",
|
||||
"-B$hostSysRoot/../bin",
|
||||
"--sysroot=$sysRoot")
|
||||
val libGcc = getTargetSpecific("libGcc", target)
|
||||
val binDir = "$targetSysRoot/${libGcc ?: "bin"}"
|
||||
return archSelector + commonArgs + listOf(
|
||||
"-B$binDir", "--gcc-toolchain=$targetToolchain")
|
||||
}
|
||||
else -> error("Unexpected target: ${target}")
|
||||
}
|
||||
@@ -280,7 +283,7 @@ Following flags are supported:
|
||||
}
|
||||
|
||||
private fun downloadDependencies(dependenciesRoot: String, target: String, konanProperties: Properties) {
|
||||
val dependencyList = konanProperties.getOsSpecific("dependencies", target)?.split(' ') ?: listOf<String>()
|
||||
val dependencyList = konanProperties.getHostTargetSpecific("dependencies", target)?.split(' ') ?: listOf<String>()
|
||||
maybeExecuteHelper(dependenciesRoot, konanProperties, dependencyList)
|
||||
}
|
||||
|
||||
@@ -293,7 +296,7 @@ private fun processLib(konanHome: String,
|
||||
val nativeLibsDir = args["-natives"]?.single() ?: userDir
|
||||
val flavorName = args["-flavor"]?.single() ?: "jvm"
|
||||
val flavor = KotlinPlatform.values().single { it.name.equals(flavorName, ignoreCase = true) }
|
||||
val target = args["-target"]?.single()?.targetSuffix() ?: defaultTarget()
|
||||
val target = args["-target"]?.single()?.targetSuffix() ?: defaultTarget
|
||||
val defFile = args["-def"]?.single()?.let { File(it) }
|
||||
|
||||
if (defFile == null && args["-pkg"] == null) {
|
||||
@@ -304,14 +307,14 @@ private fun processLib(konanHome: String,
|
||||
val (config, defHeaderLines) = parseDefFile(defFile, substitutions)
|
||||
|
||||
val konanFileName = args["-properties"]?.single() ?:
|
||||
"${konanHome}/konan/konan.properties"
|
||||
"${konanHome}/konan/konan.properties"
|
||||
val konanFile = File(konanFileName)
|
||||
val konanProperties = loadProperties(konanFile, mapOf())
|
||||
val dependencies = "$konanHome/dependencies"
|
||||
val dependencies = "$konanHome/dependencies"
|
||||
downloadDependencies(dependencies, target, konanProperties)
|
||||
|
||||
// TODO: We can provide a set of flags to find the components in the absence of 'dist' or 'dist/dependencies'.
|
||||
val llvmHome = konanProperties.getOsSpecific("llvmHome")!!
|
||||
val llvmHome = konanProperties.getHostSpecific("llvmHome")!!
|
||||
val llvmInstallPath = "$dependencies/$llvmHome"
|
||||
val additionalHeaders = args["-h"].orEmpty()
|
||||
val additionalCompilerOpts = args["-copt"].orEmpty()
|
||||
@@ -321,18 +324,18 @@ private fun processLib(konanHome: String,
|
||||
|
||||
val defaultOpts = konanProperties.defaultCompilerOpts(target, dependencies)
|
||||
val headerFiles = config.getSpaceSeparated("headers") + additionalHeaders
|
||||
val compilerOpts =
|
||||
config.getSpaceSeparated("compilerOpts") +
|
||||
defaultOpts + additionalCompilerOpts
|
||||
val compilerOpts =
|
||||
config.getSpaceSeparated("compilerOpts") +
|
||||
defaultOpts + additionalCompilerOpts
|
||||
val compiler = "clang"
|
||||
val language = Language.C
|
||||
val excludeSystemLibs = config.getProperty("excludeSystemLibs")?.toBoolean() ?: false
|
||||
val excludeDependentModules = config.getProperty("excludeDependentModules")?.toBoolean() ?: false
|
||||
|
||||
val entryPoint = config.getSpaceSeparated("entryPoint").atMostOne()
|
||||
val linkerOpts =
|
||||
config.getSpaceSeparated("linkerOpts").toTypedArray() +
|
||||
defaultOpts + additionalLinkerOpts
|
||||
val linkerOpts =
|
||||
config.getSpaceSeparated("linkerOpts").toTypedArray() +
|
||||
defaultOpts + additionalLinkerOpts
|
||||
val linker = args["-linker"]?.atMostOne() ?: config.getProperty("linker") ?: "clang"
|
||||
val excludedFunctions = config.getSpaceSeparated("excludedFunctions").toSet()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user