Android NDK support and build system refactoring (#585)

This commit is contained in:
Nikolay Igotti
2017-05-24 00:20:19 +03:00
committed by GitHub
parent 48742b7f3f
commit 42197a2bec
26 changed files with 404 additions and 232 deletions
@@ -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. // TODO: fix GNUC varargs support.
return UnsupportedType return UnsupportedType
} }
@@ -26,10 +26,9 @@ import kotlin.reflect.KFunction
fun main(args: Array<String>) { fun main(args: Array<String>) {
val konanHome = File(System.getProperty("konan.home")).absolutePath val konanHome = File(System.getProperty("konan.home")).absolutePath
// TODO: remove OSX defaults.
val substitutions = mapOf( val substitutions = mapOf(
"arch" to (System.getenv("TARGET_ARCH") ?: "x86-64"), "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)) processLib(konanHome, substitutions, parseArgs(args))
@@ -37,46 +36,54 @@ fun main(args: Array<String>) {
private fun parseArgs(args: Array<String>): Map<String, List<String>> { private fun parseArgs(args: Array<String>): Map<String, List<String>> {
val commandLine = mutableMapOf<String, MutableList<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] val key = args[index]
if (key[0] != '-') { if (key[0] != '-') {
throw IllegalArgumentException("Expected a flag with initial dash: $key") 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") throw IllegalArgumentException("Expected an value after $key")
} }
val value = args[index+1] val value = args[index + 1]
commandLine[key] ?. add(value) ?: commandLine.put(key, mutableListOf(value)) commandLine[key]?.add(value) ?: commandLine.put(key, mutableListOf(value))
} }
return commandLine return commandLine
} }
private fun detectHost(): String { private val host: String by lazy {
val os = System.getProperty("os.name") val os = System.getProperty("os.name")
when (os) { when (os) {
"Linux" -> return "linux" "Linux" -> "linux"
"Windows" -> return "win" "Windows" -> "win"
"Mac OS X" -> return "osx" "Mac OS X" -> "osx"
"FreeBSD" -> return "freebsd" "FreeBSD" -> "freebsd"
else -> { else -> {
throw IllegalArgumentException("we don't know ${os} value") 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( private val knownTargets = mapOf(
"host" to defaultTarget(), "host" to host,
"linux" to "linux", "linux" to "linux",
"macbook" to "osx", "macbook" to "osx",
"iphone" to "osx-ios", "osx" to "osx",
"iphone_sim" to "osx-ios-sim", "iphone" to "ios",
"raspberrypi" to "linux-raspberrypi") "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 = private fun String.targetSuffix(): String =
knownTargets[this] ?: error("Unsupported target $this.") knownTargets[this] ?: error("Unsupported target $this.")
// Performs substitution similar to: // Performs substitution similar to:
// foo = ${foo} ${foo.${arch}} ${foo.${os}} // foo = ${foo} ${foo.${arch}} ${foo.${os}}
@@ -118,11 +125,17 @@ private fun String.matchesToGlob(glob: String): Boolean =
java.nio.file.FileSystems.getDefault() java.nio.file.FileSystems.getDefault()
.getPathMatcher("glob:$glob").matches(java.nio.file.Paths.get(this)) .getPathMatcher("glob:$glob").matches(java.nio.file.Paths.get(this))
private fun Properties.getOsSpecific(name: String, private fun Properties.getHostSpecific(
host: String = detectHost()): String? { 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 { private fun List<String>?.isTrue(): Boolean {
// The rightmost wins, null != "true". // 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> { private fun Properties.defaultCompilerOpts(target: String, dependencies: String): List<String> {
val targetToolchainDir = getHostTargetSpecific("targetToolchain", target)!!
val arch = this.getOsSpecific("arch", target)!! val targetToolchain = "$dependencies/$targetToolchainDir"
val hostSysRootDir = this.getOsSpecific("sysRoot")!! val targetSysRootDir = getTargetSpecific("targetSysRoot", target)!!
val hostSysRoot = "$dependencies/$hostSysRootDir"
val targetSysRootDir = this.getOsSpecific("targetSysRoot", target) ?: hostSysRootDir
val targetSysRoot = "$dependencies/$targetSysRootDir" val targetSysRoot = "$dependencies/$targetSysRootDir"
val sysRoot = targetSysRoot val llvmHomeDir = getHostSpecific("llvmHome")!!
val llvmHomeDir = this.getOsSpecific("llvmHome")!!
val llvmHome = "$dependencies/$llvmHomeDir" val llvmHome = "$dependencies/$llvmHomeDir"
System.load("$llvmHome/lib/${System.mapLibraryName("clang")}") System.load("$llvmHome/lib/${System.mapLibraryName("clang")}")
val llvmVersion = this.getProperty("llvmVersion")!! val llvmVersion = getProperty("llvmVersion")!!
// StubGenerator passes the arguments to libclang which // StubGenerator passes the arguments to libclang which
// works not exactly the same way as the clang binary and // works not exactly the same way as the clang binary and
// (in particular) uses different default header search path. // (in particular) uses different default header search path.
// See e.g. http://lists.llvm.org/pipermail/cfe-dev/2013-November/033680.html // See e.g. http://lists.llvm.org/pipermail/cfe-dev/2013-November/033680.html
// We workaround the problem with -isystem flag below. // We workaround the problem with -isystem flag below.
val isystem = "$llvmHome/lib/clang/$llvmVersion/include" val isystem = "$llvmHome/lib/clang/$llvmVersion/include"
val quadruple = getTargetSpecific("quadruple", target)
when (detectHost()) { 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" -> { "osx" -> {
val osVersionMinFlag = this.getOsSpecific("osVersionMinFlagClang", target)!! val osVersionMinFlag = getTargetSpecific("osVersionMinFlagClang", target)
val osVersionMinValue = this.getOsSpecific("osVersionMin", target)!! val osVersionMinValue = getTargetSpecific("osVersionMin", target)
return archSelector + commonArgs + listOf("-B$targetToolchain/bin") +
return listOf( (if (osVersionMinFlag != null && osVersionMinValue != null)
"-arch", arch, listOf("$osVersionMinFlag=$osVersionMinValue") else emptyList())
"-isystem", isystem,
"-B$hostSysRoot/usr/bin",
"--sysroot=$sysRoot",
"$osVersionMinFlag=$osVersionMinValue")
} }
"linux" -> { "linux" -> {
val gccToolChainDir = this.getOsSpecific("gccToolChain", target)!! val libGcc = getTargetSpecific("libGcc", target)
val gccToolChain= "$dependencies/$gccToolChainDir" val binDir = "$targetSysRoot/${libGcc ?: "bin"}"
val quadruple = this.getOsSpecific("quadruple", target)!! return archSelector + commonArgs + listOf(
"-B$binDir", "--gcc-toolchain=$targetToolchain")
return listOf(
"-target", quadruple,
"-isystem", isystem,
"--gcc-toolchain=$gccToolChain",
"-L$llvmHome/lib",
"-B$hostSysRoot/../bin",
"--sysroot=$sysRoot")
} }
else -> error("Unexpected target: ${target}") else -> error("Unexpected target: ${target}")
} }
@@ -280,7 +283,7 @@ Following flags are supported:
} }
private fun downloadDependencies(dependenciesRoot: String, target: String, konanProperties: Properties) { 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) maybeExecuteHelper(dependenciesRoot, konanProperties, dependencyList)
} }
@@ -293,7 +296,7 @@ private fun processLib(konanHome: String,
val nativeLibsDir = args["-natives"]?.single() ?: userDir val nativeLibsDir = args["-natives"]?.single() ?: userDir
val flavorName = args["-flavor"]?.single() ?: "jvm" val flavorName = args["-flavor"]?.single() ?: "jvm"
val flavor = KotlinPlatform.values().single { it.name.equals(flavorName, ignoreCase = true) } 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) } val defFile = args["-def"]?.single()?.let { File(it) }
if (defFile == null && args["-pkg"] == null) { if (defFile == null && args["-pkg"] == null) {
@@ -304,14 +307,14 @@ private fun processLib(konanHome: String,
val (config, defHeaderLines) = parseDefFile(defFile, substitutions) val (config, defHeaderLines) = parseDefFile(defFile, substitutions)
val konanFileName = args["-properties"]?.single() ?: val konanFileName = args["-properties"]?.single() ?:
"${konanHome}/konan/konan.properties" "${konanHome}/konan/konan.properties"
val konanFile = File(konanFileName) val konanFile = File(konanFileName)
val konanProperties = loadProperties(konanFile, mapOf()) val konanProperties = loadProperties(konanFile, mapOf())
val dependencies = "$konanHome/dependencies" val dependencies = "$konanHome/dependencies"
downloadDependencies(dependencies, target, konanProperties) downloadDependencies(dependencies, target, konanProperties)
// TODO: We can provide a set of flags to find the components in the absence of 'dist' or 'dist/dependencies'. // 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 llvmInstallPath = "$dependencies/$llvmHome"
val additionalHeaders = args["-h"].orEmpty() val additionalHeaders = args["-h"].orEmpty()
val additionalCompilerOpts = args["-copt"].orEmpty() val additionalCompilerOpts = args["-copt"].orEmpty()
@@ -321,18 +324,18 @@ private fun processLib(konanHome: String,
val defaultOpts = konanProperties.defaultCompilerOpts(target, dependencies) val defaultOpts = konanProperties.defaultCompilerOpts(target, dependencies)
val headerFiles = config.getSpaceSeparated("headers") + additionalHeaders val headerFiles = config.getSpaceSeparated("headers") + additionalHeaders
val compilerOpts = val compilerOpts =
config.getSpaceSeparated("compilerOpts") + config.getSpaceSeparated("compilerOpts") +
defaultOpts + additionalCompilerOpts defaultOpts + additionalCompilerOpts
val compiler = "clang" val compiler = "clang"
val language = Language.C val language = Language.C
val excludeSystemLibs = config.getProperty("excludeSystemLibs")?.toBoolean() ?: false val excludeSystemLibs = config.getProperty("excludeSystemLibs")?.toBoolean() ?: false
val excludeDependentModules = config.getProperty("excludeDependentModules")?.toBoolean() ?: false val excludeDependentModules = config.getProperty("excludeDependentModules")?.toBoolean() ?: false
val entryPoint = config.getSpaceSeparated("entryPoint").atMostOne() val entryPoint = config.getSpaceSeparated("entryPoint").atMostOne()
val linkerOpts = val linkerOpts =
config.getSpaceSeparated("linkerOpts").toTypedArray() + config.getSpaceSeparated("linkerOpts").toTypedArray() +
defaultOpts + additionalLinkerOpts defaultOpts + additionalLinkerOpts
val linker = args["-linker"]?.atMostOne() ?: config.getProperty("linker") ?: "clang" val linker = args["-linker"]?.atMostOne() ?: config.getProperty("linker") ?: "clang"
val excludedFunctions = config.getSpaceSeparated("excludedFunctions").toSet() val excludedFunctions = config.getSpaceSeparated("excludedFunctions").toSet()
@@ -49,8 +49,10 @@ private fun maybeExecuteHelper(configuration: CompilerConfiguration) {
} }
} }
class K2Native : CLICompiler<K2NativeCompilerArguments>() { private fun suffixIfNot(name: String, suffix: String) =
if (name.endsWith(suffix)) name else "$name$suffix"
class K2Native : CLICompiler<K2NativeCompilerArguments>() {
override fun doExecute(arguments : K2NativeCompilerArguments, override fun doExecute(arguments : K2NativeCompilerArguments,
configuration : CompilerConfiguration, configuration : CompilerConfiguration,
@@ -109,11 +111,11 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
val library = arguments.outputFile ?: "library" val library = arguments.outputFile ?: "library"
if (arguments.nolink) if (arguments.nolink)
put(LIBRARY_NAME, library) put(LIBRARY_NAME, library)
put(LIBRARY_FILE, "${library}.klib") put(LIBRARY_FILE, suffixIfNot(library, ".klib"))
val program = arguments.outputFile ?: "program" val program = arguments.outputFile ?: "program"
if (!arguments.nolink) { if (!arguments.nolink) {
put(PROGRAM_NAME,program) put(PROGRAM_NAME, program)
put(EXECUTABLE_FILE,"${program}.kexe") put(EXECUTABLE_FILE, suffixIfNot(program, ".kexe"))
} }
// This is a decision we could change // This is a decision we could change
val module = if (arguments.nolink) library else program val module = if (arguments.nolink) library else program
@@ -23,9 +23,9 @@ class Distribution(val config: CompilerConfiguration) {
val targetManager = TargetManager(config) val targetManager = TargetManager(config)
val target = targetManager.currentName val target = targetManager.currentName
val suffix = targetManager.currentSuffix() val hostSuffix = targetManager.hostSuffix()
val hostSuffix = TargetManager.host.suffix val hostTargetSuffix = targetManager.hostTargetSuffix()
init { if (!targetManager.crossCompile) assert(suffix == hostSuffix) } val targetSuffix = targetManager.targetSuffix()
private fun findUserHome() = File(System.getProperty("user.home")).absolutePath private fun findUserHome() = File(System.getProperty("user.home")).absolutePath
val userHome = findUserHome() val userHome = findUserHome()
@@ -45,32 +45,23 @@ class Distribution(val config: CompilerConfiguration) {
val klib = "$konanHome/klib" val klib = "$konanHome/klib"
val dependenciesDir = "$konanHome/dependencies" val dependenciesDir = "$konanHome/dependencies"
val dependencies = properties.propertyList("dependencies.$suffix") val dependencies = properties.propertyList("dependencies.$hostTargetSuffix")
val stdlib = "$klib/stdlib" val stdlib = "$klib/stdlib"
val runtime = config.get(KonanConfigKeys.RUNTIME_FILE) val runtime = config.get(KonanConfigKeys.RUNTIME_FILE)
?: "$stdlib/$target/native/runtime.bc" ?: "$stdlib/$target/native/runtime.bc"
val llvmHome = "$dependenciesDir/${properties.propertyString("llvmHome.$hostSuffix")}" val llvmHome = "$dependenciesDir/${properties.propertyString("llvmHome.$hostSuffix")}"
val sysRoot = "$dependenciesDir/${properties.propertyString("sysRoot.$hostSuffix")}" val hostSysRoot = "$dependenciesDir/${properties.propertyString("targetSysRoot.$hostSuffix")}"
val targetSysRoot = "$dependenciesDir/${properties.propertyString("targetSysRoot.$targetSuffix")}"
val libGcc = "$dependenciesDir/${properties.propertyString("libGcc.$suffix")}" val targetToolchain = "$dependenciesDir/${properties.propertyString("targetToolchain.$hostTargetSuffix")}"
val targetSysRoot = if (properties.hasProperty("targetSysRoot.$suffix")) { val libffi =
"$dependenciesDir/${properties.propertyString("targetSysRoot.$suffix")}" "$dependenciesDir/${properties.propertyString("libffiDir.$targetSuffix")}/lib/libffi.a"
} else {
sysRoot
}
val libffi = "$dependenciesDir/${properties.propertyString("libffiDir.$suffix")}/lib/libffi.a"
val llvmBin = "$llvmHome/bin" val llvmBin = "$llvmHome/bin"
val llvmLib = "$llvmHome/lib" val llvmLib = "$llvmHome/lib"
val llvmOpt = "$llvmBin/opt"
val llvmLlc = "$llvmBin/llc"
val llvmLto = "$llvmBin/llvm-lto" val llvmLto = "$llvmBin/llvm-lto"
val llvmLink = "$llvmBin/llvm-link"
val libCppAbi = "$llvmLib/libc++abi.a"
val libLTO = when (TargetManager.host) { val libLTO = when (TargetManager.host) {
KonanTarget.MACBOOK -> "$llvmLib/libLTO.dylib" KonanTarget.MACBOOK -> "$llvmLib/libLTO.dylib"
KonanTarget.LINUX -> "$llvmLib/libLTO.so" KonanTarget.LINUX -> "$llvmLib/libLTO.so"
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.backend.konan.library.KonanLibrarySearchPathResolver
import org.jetbrains.kotlin.backend.konan.util.profile import org.jetbrains.kotlin.backend.konan.util.profile
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.backend.konan.util.File import org.jetbrains.kotlin.backend.konan.util.File
@@ -39,7 +39,7 @@ public class KonanProperties(val propertyFile: String) {
fun propertyList(key: String, suffix: String? = null): List<String> { fun propertyList(key: String, suffix: String? = null): List<String> {
val value = properties.getProperty(key.suffix(suffix)) val value = properties.getProperty(key.suffix(suffix))
return value?.split(' ') ?: listOf<String>() return value?.split(' ') ?: emptyList()
} }
fun hasProperty(key: String, suffix: String? = null): Boolean fun hasProperty(key: String, suffix: String? = null): Boolean
@@ -16,12 +16,12 @@
package org.jetbrains.kotlin.backend.konan package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
enum class KonanTarget(val suffix: String, var enabled: Boolean = false) { enum class KonanTarget(val suffix: String, var enabled: Boolean = false) {
ANDROID_ARM32("android_arm32"),
IPHONE("ios"), IPHONE("ios"),
IPHONE_SIM("ios-sim"), IPHONE_SIM("ios_sim"),
LINUX("linux"), LINUX("linux"),
MACBOOK("osx"), MACBOOK("osx"),
RASPBERRYPI("raspberrypi") RASPBERRYPI("raspberrypi")
@@ -38,11 +38,13 @@ class TargetManager(val config: CompilerConfiguration) {
KonanTarget.LINUX -> { KonanTarget.LINUX -> {
KonanTarget.LINUX.enabled = true KonanTarget.LINUX.enabled = true
KonanTarget.RASPBERRYPI.enabled = true KonanTarget.RASPBERRYPI.enabled = true
KonanTarget.ANDROID_ARM32.enabled = true
} }
KonanTarget.MACBOOK -> { KonanTarget.MACBOOK -> {
KonanTarget.MACBOOK.enabled = true KonanTarget.MACBOOK.enabled = true
KonanTarget.IPHONE.enabled = true KonanTarget.IPHONE.enabled = true
KonanTarget.IPHONE_SIM.enabled = true KonanTarget.IPHONE_SIM.enabled = true
KonanTarget.ANDROID_ARM32.enabled = true
} }
else -> else ->
error("Unknown host platform: $host") error("Unknown host platform: $host")
@@ -78,10 +80,10 @@ class TargetManager(val config: CompilerConfiguration) {
} }
} }
fun currentSuffix(): String { fun hostSuffix() = host.suffix
return host.suffix + fun hostTargetSuffix() =
if (host != current) "-${current.suffix}" else "" if (current == host) host.suffix else "${host.suffix}-${current.suffix}"
} fun targetSuffix() = current.suffix
companion object { companion object {
fun host_os(): String { fun host_os(): String {
@@ -109,7 +111,5 @@ class TargetManager(val config: CompilerConfiguration) {
else -> error("Unknown host target: ${host_os()} ${host_arch()}") else -> error("Unknown host target: ${host_os()} ${host_arch()}")
} }
} }
val crossCompile = (host != current)
} }
@@ -29,67 +29,72 @@ typealias ExecutableFile = String
internal abstract class PlatformFlags(val distribution: Distribution) { internal abstract class PlatformFlags(val distribution: Distribution) {
val properties = distribution.properties val properties = distribution.properties
val hostSuffix = TargetManager.host.suffix val hostSuffix = distribution.hostTargetSuffix
val targetSuffix = distribution.suffix val targetSuffix = distribution.targetSuffix
val arch = propertyTargetString("arch")
open val llvmLtoNooptFlags open val llvmLtoNooptFlags
= propertyHostList("llvmLtoNooptFlags") = propertyTargetList("llvmLtoNooptFlags")
open val llvmLtoOptFlags open val llvmLtoOptFlags
= propertyHostList("llvmLtoOptFlags") = propertyTargetList("llvmLtoOptFlags")
open val llvmLtoFlags open val llvmLtoFlags
= propertyHostList("llvmLtoFlags") = propertyTargetList("llvmLtoFlags")
open val entrySelector open val entrySelector
= propertyHostList("entrySelector") = propertyTargetList("entrySelector")
open val linkerOptimizationFlags open val linkerOptimizationFlags
= propertyHostList("linkerOptimizationFlags") = propertyTargetList("linkerOptimizationFlags")
open val linkerKonanFlags open val linkerKonanFlags
= propertyHostList("linkerKonanFlags") = propertyTargetList("linkerKonanFlags")
abstract val linker: String abstract fun linkCommand(objectFiles: List<ObjectFile>,
abstract fun linkCommand(objectFiles: List<ObjectFile>,
executable: ExecutableFile, optimize: Boolean): List<String> executable: ExecutableFile, optimize: Boolean): List<String>
protected fun propertyHostString(name: String) protected fun propertyHostString(name: String)
= properties.propertyString(name, hostSuffix)!! = properties.propertyString(name, hostSuffix)!!
protected fun propertyHostList(name: String) protected fun propertyHostList(name: String)
= properties.propertyList(name, hostSuffix) = properties.propertyList(name, hostSuffix)
protected fun propertyTargetString(name: String) protected fun propertyTargetString(name: String)
= properties.propertyString(name, targetSuffix)!! = properties.propertyString(name, targetSuffix)!!
protected fun propertyTargetList(name: String) protected fun propertyTargetList(name: String)
= properties.propertyList(name, targetSuffix) = properties.propertyList(name, targetSuffix)
protected fun propertyCommonString(name: String) }
= properties.propertyString(name, null)!!
protected fun propertyCommonList(name: String)
= properties.propertyList(name, null) internal open class AndroidPlatform(distribution: Distribution)
: PlatformFlags(distribution) {
private val prefix = "${distribution.targetToolchain}/bin/"
private val clang = "$prefix/clang"
override fun linkCommand(objectFiles: List<String>, executable: String, optimize: Boolean): List<String> {
return mutableListOf<String>(clang, "-o", executable, "-fPIC", "-shared") +
objectFiles +
(if (optimize) linkerOptimizationFlags else emptyList()) +
linkerKonanFlags
}
} }
internal open class MacOSBasedPlatform(distribution: Distribution) internal open class MacOSBasedPlatform(distribution: Distribution)
: PlatformFlags(distribution) { : PlatformFlags(distribution) {
override val linker = "${distribution.sysRoot}/usr/bin/ld" // TODO: move 'ld' out of the host sysroot, as it doesn't belong here.
private val linker = "${distribution.hostSysRoot}/usr/bin/ld"
private val dsymutil = "${distribution.llvmBin}/llvm-dsymutil" private val dsymutil = "${distribution.llvmBin}/llvm-dsymutil"
open val osVersionMin = listOf( open val osVersionMin by lazy {
propertyTargetString("osVersionMinFlagLd"), listOf(
propertyTargetString("osVersionMin")+".0") propertyTargetString("osVersionMinFlagLd"),
propertyTargetString("osVersionMin") + ".0")
open val sysRoot = distribution.sysRoot }
open val targetSysRoot = distribution.targetSysRoot
override fun linkCommand(objectFiles: List<String>, executable: String, optimize: Boolean): List<String> { override fun linkCommand(objectFiles: List<String>, executable: String, optimize: Boolean): List<String> {
return mutableListOf(linker, "-demangle") +
return mutableListOf<String>(linker, "-demangle") + listOf("-object_path_lto", "temporary.o", "-lto_library", distribution.libLTO) +
listOf("-object_path_lto", "temporary.o", "-lto_library", distribution.libLTO) + listOf("-dynamic", "-arch", propertyTargetString("arch")) +
listOf( "-dynamic", "-arch", arch) + osVersionMin +
osVersionMin + listOf("-syslibroot", distribution.targetSysRoot, "-o", executable) +
listOf("-syslibroot", "$targetSysRoot", objectFiles +
"-o", executable) + (if (optimize) linkerOptimizationFlags else emptyList()) +
objectFiles + linkerKonanFlags + listOf("-lSystem")
if (optimize) linkerOptimizationFlags else {listOf<String>()} +
linkerKonanFlags +
listOf("-lSystem")
} }
open fun dsymutilCommand(executable: ExecutableFile): List<String> { open fun dsymutilCommand(executable: ExecutableFile): List<String> {
@@ -104,29 +109,21 @@ internal open class MacOSBasedPlatform(distribution: Distribution)
internal open class LinuxBasedPlatform(distribution: Distribution) internal open class LinuxBasedPlatform(distribution: Distribution)
: PlatformFlags(distribution) { : PlatformFlags(distribution) {
open val sysRoot = distribution.sysRoot val targetSysRoot = distribution.targetSysRoot
open val targetSysRoot = distribution.targetSysRoot
val llvmLib = distribution.llvmLib val llvmLib = distribution.llvmLib
val libGcc = distribution.libGcc val libGcc = "$targetSysRoot/${propertyTargetString("libGcc")!!}"
val linker = "${distribution.targetToolchain}/bin/ld.gold"
override val linker = "${distribution.sysRoot}/../bin/ld.gold" val pluginOptimizationFlags = propertyTargetList("pluginOptimizationFlags")
val specificLibs
open val pluginOptimizationFlags =
propertyHostList("pluginOptimizationFlags")
open val dynamicLinker =
propertyTargetString("dynamicLinker")
open val specificLibs
= propertyTargetList("abiSpecificLibraries").map{it -> "-L${targetSysRoot}/$it"} = propertyTargetList("abiSpecificLibraries").map{it -> "-L${targetSysRoot}/$it"}
override fun linkCommand(objectFiles: List<String>, executable: String, optimize: Boolean): List<String> { override fun linkCommand(objectFiles: List<String>, executable: String, optimize: Boolean): List<String> {
// TODO: Can we extract more to the konan.properties? // TODO: Can we extract more to the konan.properties?
return mutableListOf<String>("$linker", return mutableListOf(linker,
"--sysroot=${targetSysRoot}", "--sysroot=${targetSysRoot}",
"-export-dynamic", "-z", "relro", "--hash-style=gnu", "-export-dynamic", "-z", "relro", "--hash-style=gnu",
"--build-id", "--eh-frame-hdr", // "-m", "elf_x86_64", "--build-id", "--eh-frame-hdr", // "-m", "elf_x86_64",
"-dynamic-linker", dynamicLinker, "-dynamic-linker", propertyTargetString("dynamicLinker"),
"-o", executable, "-o", executable,
"${targetSysRoot}/usr/lib64/crt1.o", "${targetSysRoot}/usr/lib64/crti.o", "${libGcc}/crtbegin.o", "${targetSysRoot}/usr/lib64/crt1.o", "${targetSysRoot}/usr/lib64/crti.o", "${libGcc}/crtbegin.o",
"-L${llvmLib}", "-L${libGcc}") + "-L${llvmLib}", "-L${libGcc}") +
@@ -147,22 +144,19 @@ internal class LinkStage(val context: Context) {
val config = context.config.configuration val config = context.config.configuration
val targetManager = context.config.targetManager private val distribution = context.config.distribution
private val distribution =
context.config.distribution
private val properties = distribution.properties
val platform = when (TargetManager.host) { val platform = when (context.config.targetManager.current) {
KonanTarget.LINUX -> KonanTarget.LINUX, KonanTarget.RASPBERRYPI ->
LinuxBasedPlatform(distribution) LinuxBasedPlatform(distribution)
KonanTarget.MACBOOK -> KonanTarget.MACBOOK, KonanTarget.IPHONE, KonanTarget.IPHONE_SIM ->
MacOSBasedPlatform(distribution) MacOSBasedPlatform(distribution)
KonanTarget.ANDROID_ARM32 ->
AndroidPlatform(distribution)
else -> else ->
error("Unexpected host platform") error("Unexpected target platform: ${context.config.targetManager.current}")
} }
val suffix = targetManager.currentSuffix()
val optimize = config.get(KonanConfigKeys.OPTIMIZATION) ?: false val optimize = config.get(KonanConfigKeys.OPTIMIZATION) ?: false
val nomain = config.get(KonanConfigKeys.NOMAIN) ?: false val nomain = config.get(KonanConfigKeys.NOMAIN) ?: false
val emitted = context.bitcodeFileName val emitted = context.bitcodeFileName
@@ -187,18 +181,6 @@ internal class LinkStage(val context: Context) {
return combined return combined
} }
fun llvmLlc(file: BitcodeFile): ObjectFile {
val tmpObjectFile = File.createTempFile(File(file).name, ".o")
tmpObjectFile.deleteOnExit()
val objectFile = tmpObjectFile.absolutePath
val command = listOf(distribution.llvmLlc, "-o", objectFile, "-filetype=obj") +
properties.propertyList("llvmLlcFlags.$suffix") + listOf(file)
runTool(*command.toTypedArray())
return objectFile
}
fun asLinkerArgs(args: List<String>): List<String> { fun asLinkerArgs(args: List<String>): List<String> {
val result = mutableListOf<String>() val result = mutableListOf<String>()
for (arg in args) { for (arg in args) {
@@ -220,8 +202,7 @@ internal class LinkStage(val context: Context) {
// So we stick to "-alias _main _konan_main" on Mac. // So we stick to "-alias _main _konan_main" on Mac.
// And just do the same on Linux. // And just do the same on Linux.
val entryPointSelector: List<String> val entryPointSelector: List<String>
get() = if (nomain) listOf() get() = if (nomain) emptyList() else platform.entrySelector
else platform.entrySelector
fun link(objectFiles: List<ObjectFile>): ExecutableFile { fun link(objectFiles: List<ObjectFile>): ExecutableFile {
val executable = config.get(KonanConfigKeys.EXECUTABLE_FILE)!! val executable = config.get(KonanConfigKeys.EXECUTABLE_FILE)!!
@@ -265,7 +246,7 @@ internal class LinkStage(val context: Context) {
fun linkStage() { fun linkStage() {
context.log{"# Compiler root: ${distribution.konanHome}"} context.log{"# Compiler root: ${distribution.konanHome}"}
val bitcodeFiles = listOf<BitcodeFile>(emitted) + val bitcodeFiles = listOf(emitted) +
libraries.map{it -> it.bitcodePaths}.flatten() libraries.map{it -> it.bitcodePaths}.flatten()
var objectFiles: List<String> = listOf() var objectFiles: List<String> = listOf()
@@ -187,7 +187,7 @@ internal fun ContextUtils.addGlobal(name: String, type: LLVMTypeRef,
assert(LLVMGetNamedGlobal(context.llvmModule, name) == null) assert(LLVMGetNamedGlobal(context.llvmModule, name) == null)
val result = LLVMAddGlobal(context.llvmModule, type, name)!! val result = LLVMAddGlobal(context.llvmModule, type, name)!!
if (threadLocal) if (threadLocal)
LLVMSetThreadLocalMode(result, LLVMThreadLocalMode.LLVMLocalExecTLSModel) LLVMSetThreadLocalMode(result, runtime.tlsMode)
return result return result
} }
@@ -198,12 +198,12 @@ internal fun ContextUtils.importGlobal(name: String, type: LLVMTypeRef,
assert (getGlobalType(found) == type) assert (getGlobalType(found) == type)
assert (LLVMGetInitializer(found) == null) assert (LLVMGetInitializer(found) == null)
if (threadLocal) if (threadLocal)
assert(LLVMGetThreadLocalMode(found) == LLVMThreadLocalMode.LLVMLocalExecTLSModel) assert(LLVMGetThreadLocalMode(found) == runtime.tlsMode)
return found return found
} else { } else {
val result = LLVMAddGlobal(context.llvmModule, type, name)!! val result = LLVMAddGlobal(context.llvmModule, type, name)!!
if (threadLocal) if (threadLocal)
LLVMSetThreadLocalMode(result, LLVMThreadLocalMode.LLVMLocalExecTLSModel) LLVMSetThreadLocalMode(result, runtime.tlsMode)
return result return result
} }
} }
@@ -42,6 +42,10 @@ class Runtime(bitcodeFile: String) {
val target = LLVMGetTarget(llvmModule)!!.toKString() val target = LLVMGetTarget(llvmModule)!!.toKString()
// TODO: deduce TLS model from explicit config parameter.
val tlsMode = if (target.indexOf("android") != -1)
LLVMThreadLocalMode.LLVMGeneralDynamicTLSModel else LLVMThreadLocalMode.LLVMLocalExecTLSModel
val dataLayout = LLVMGetDataLayout(llvmModule)!!.toKString() val dataLayout = LLVMGetDataLayout(llvmModule)!!.toKString()
val targetData = LLVMCreateTargetData(dataLayout)!! val targetData = LLVMCreateTargetData(dataLayout)!!
+90 -43
View File
@@ -1,4 +1,3 @@
# #
# Copyright 2010-2017 JetBrains s.r.o. # Copyright 2010-2017 JetBrains s.r.o.
# #
@@ -19,11 +18,13 @@
llvmVersion = 3.9.0 llvmVersion = 3.9.0
dependenciesUrl = http://download.jetbrains.com/kotlin/native dependenciesUrl = http://download.jetbrains.com/kotlin/native
# macbook # Mac OS X.
arch.osx = x86_64
sysRoot.osx = target-sysroot-1-darwin-macos
libffiDir.osx = libffi-3.2.1-2-darwin-macos
llvmHome.osx = clang-llvm-3.9.0-darwin-macos llvmHome.osx = clang-llvm-3.9.0-darwin-macos
targetToolchain.osx = clang-llvm-3.9.0-darwin-macos
arch.osx = x86_64
targetSysRoot.osx = target-sysroot-1-darwin-macos
libffiDir.osx = libffi-3.2.1-2-darwin-macos
llvmLtoFlags.osx = -exported-symbol=_Konan_main llvmLtoFlags.osx = -exported-symbol=_Konan_main
llvmLtoOptFlags.osx = -O3 -function-sections llvmLtoOptFlags.osx = -O3 -function-sections
llvmLtoNooptFlags.osx = -O1 llvmLtoNooptFlags.osx = -O1
@@ -37,38 +38,55 @@ dependencies.osx = target-sysroot-1-darwin-macos \
libffi-3.2.1-2-darwin-macos \ libffi-3.2.1-2-darwin-macos \
clang-llvm-3.9.0-darwin-macos clang-llvm-3.9.0-darwin-macos
# iphone # Apple iOS.
arch.osx-ios = arm64 targetToolchain.osx-ios = clang-llvm-3.9.0-darwin-macos
targetSysRoot.osx-ios = target-sysroot-2-darwin-ios
libffiDir.osx-ios = libffi-3.2.1-2-darwin-ios
osVersionMinFlagLd.osx-ios = -iphoneos_version_min
osVersionMinFlagClang.osx-ios = -miphoneos-version-min
osVersionMin.osx-ios = 8.0
dependencies.osx-ios = target-sysroot-1-darwin-macos \ dependencies.osx-ios = target-sysroot-1-darwin-macos \
libffi-3.2.1-2-darwin-ios \ libffi-3.2.1-2-darwin-ios \
clang-llvm-3.9.0-darwin-macos \ clang-llvm-3.9.0-darwin-macos \
target-sysroot-2-darwin-ios target-sysroot-2-darwin-ios
# iphone_sim arch.ios = arm64
arch.osx-ios-sim = x86_64 entrySelector.ios = -alias _Konan_main _main
targetSysRoot.osx-ios-sim = target-sysroot-1-darwin-ios-sim targetSysRoot.ios = target-sysroot-2-darwin-ios
libffiDir.osx-ios-sim = libffi-3.2.1-2-darwin-ios-sim libffiDir.ios = libffi-3.2.1-2-darwin-ios
osVersionMinFlagLd.osx-ios-sim = -ios_simulator_version_min llvmLtoFlags.ios = -exported-symbol=_Konan_main
osVersionMinFlagClang.osx-ios-sim = -mios-simulator-version-min llvmLtoOptFlags.ios = -O3 -function-sections
osVersionMin.osx-ios-sim = 8.0 llvmLtoNooptFlags.ios = -O1
dependencies.osx-ios-sim = target-sysroot-1-darwin-macos \ linkerKonanFlags.ios = -lc++
libffi-3.2.1-2-darwin-ios-sim \ linkerOptimizationFlags.ios = -dead_strip
clang-llvm-3.9.0-darwin-macos \ osVersionMinFlagLd.ios = -iphoneos_version_min
target-sysroot-1-darwin-ios-sim osVersionMinFlagClang.ios = -miphoneos-version-min
osVersionMin.ios = 8.0
# linux # Apple iOS simulator.
arch.linux = x86_64 targetToolchain.osx-ios_sim = clang-llvm-3.9.0-darwin-macos
quadruple.linux = x86_64-unknown-linux-gnu dependencies.osx-ios_sim = target-sysroot-1-darwin-macos \
sysRoot.linux = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu/sysroot libffi-3.2.1-2-darwin-ios_sim \
libffiDir.linux = libffi-3.2.1-2-linux-x86-64 clang-llvm-3.9.0-darwin-macos \
target-sysroot-1-darwin-ios_sim
arch.ios_sim = x86_64
entrySelector.ios_sim = -alias _Konan_main _main
targetSysRoot.ios_sim = target-sysroot-1-darwin-ios-sim
libffiDir.ios_sim = libffi-3.2.1-2-darwin-ios-sim
llvmLtoFlags.ios_sim = -exported-symbol=_Konan_main
llvmLtoOptFlags.ios_sim = -O3 -function-sections
llvmLtoNooptFlags.ios_sim = -O1
linkerKonanFlags.ios_sim = -lc++
linkerOptimizationFlags.ios_sim = -dead_strip
osVersionMinFlagLd.ios_sim = -ios_simulator_version_min
osVersionMinFlagClang.ios_sim = -mios-simulator-version-min
osVersionMin.ios_sim = 8.0
# Linux x86-64.
llvmHome.linux = clang-llvm-3.9.0-linux-x86-64 llvmHome.linux = clang-llvm-3.9.0-linux-x86-64
libGcc.linux = target-gcc-toolchain-3-linux-x86-64/lib/gcc/x86_64-unknown-linux-gnu/4.8.5 targetToolchain.linux = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu
gccToolChain.linux = target-gcc-toolchain-3-linux-x86-64
quadruple.linux = x86_64-unknown-linux-gnu
targetSysRoot.linux = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu/sysroot
libffiDir.linux = libffi-3.2.1-2-linux-x86-64
# targetSysroot-relative.
libGcc.linux = ../../lib/gcc/x86_64-unknown-linux-gnu/4.8.5
llvmLtoFlags.linux = -exported-symbol=Konan_main llvmLtoFlags.linux = -exported-symbol=Konan_main
llvmLtoOptFlags.linux = -O3 -function-sections llvmLtoOptFlags.linux = -O3 -function-sections
llvmLtoNooptFlags.linux = -O1 llvmLtoNooptFlags.linux = -O1
@@ -79,28 +97,57 @@ pluginOptimizationFlags.linux = -plugin-opt=mcpu=x86-64 -plugin-opt=O3
dynamicLinker.linux = /lib64/ld-linux-x86-64.so.2 dynamicLinker.linux = /lib64/ld-linux-x86-64.so.2
entrySelector.linux = --defsym main=Konan_main entrySelector.linux = --defsym main=Konan_main
# targetSysRoot relative # targetSysRoot relative
abiSpecificLibraries = ../lib64 lib64 usr/lib64 abiSpecificLibraries.linux = ../lib64 lib64 usr/lib64
dependencies.linux = \ dependencies.linux = \
clang-llvm-3.9.0-linux-x86-64 \ clang-llvm-3.9.0-linux-x86-64 \
target-gcc-toolchain-3-linux-x86-64 \ target-gcc-toolchain-3-linux-x86-64 \
libffi-3.2.1-2-linux-x86-64 libffi-3.2.1-2-linux-x86-64
# Raspberry Pi # Raspberry Pi
arch.linux-raspberrypi = armv6 targetToolchain.linux-raspberrypi = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu
quadruple.linux-raspberrypi = armv6-unknown-linux-gnueabihf
targetSysRoot.linux-raspberrypi = target-sysroot-1-raspberrypi
libffiDir.linux-raspberrypi = libffi-3.2.1-2-raspberrypi
libGcc.linux-raspberrypi = target-sysroot-1-raspberrypi/lib/gcc/arm-linux-gnueabihf/4.8.3/
gccToolChain.linux-raspberrypi = target-gcc-toolchain-3-linux-x86-64
dynamicLinker.linux-raspberrypi = /lib/ld-linux-armhf.so.3
# targetSysRoot relative
abiSpecificLibraries = \
../lib/arm-linux-gnueabihf \
lib/arm-linux-gnueabihf \
usr/lib/arm-linux-gnueabihf
dependencies.linux-raspberrypi = \ dependencies.linux-raspberrypi = \
clang-llvm-3.9.0-linux-x86-64 \ clang-llvm-3.9.0-linux-x86-64 \
target-gcc-toolchain-3-linux-x86-64 \ target-gcc-toolchain-3-linux-x86-64 \
target-sysroot-1-raspberrypi \ target-sysroot-1-raspberrypi \
libffi-3.2.1-2-linux-x86-64 \ libffi-3.2.1-2-linux-x86-64 \
libffi-3.2.1-2-raspberrypi libffi-3.2.1-2-raspberrypi
quadruple.raspberrypi = armv6-unknown-linux-gnueabihf
entrySelector.raspberrypi = --defsym main=Konan_main
linkerOptimizationFlags.raspberrypi = --gc-sections
targetSysRoot.raspberrypi = target-sysroot-1-raspberrypi
# We could reuse host toolchain here.
libffiDir.raspberrypi = libffi-3.2.1-2-raspberrypi
linkerKonanFlags.raspberrypi = -Bstatic -lstdc++ -Bdynamic -ldl -lm -lpthread
# targetSysroot-relative.
libGcc.raspberrypi = lib/gcc/arm-linux-gnueabihf/4.8.3
llvmLtoFlags.raspberrypi = -exported-symbol=Konan_main
dynamicLinker.raspberrypi = /lib/ld-linux-armhf.so.3
llvmLtoFlags.linux = -exported-symbol=Konan_main
# targetSysRoot relative
abiSpecificLibraries.raspberrypi = \
../lib/arm-linux-gnueabihf \
lib/arm-linux-gnueabihf \
usr/lib/arm-linux-gnueabihf
# Android ARM32, based on NDK for android-21.
targetToolchain.osx-android_arm32 = target-toolchain-21-osx-android_arm32
# TODO: split dependencies to host-dependent and host-independent parts.
dependencies.osx-android_arm32 = \
clang-llvm-3.9.0-darwin-macos \
target-sysroot-21-android_arm32 \
target-toolchain-21-osx-android_arm32 \
libffi-3.2.1-2-android_arm32
targetToolchain.linux-android_arm32 = target-toolchain-21-linux-android_arm32
dependencies.linux-android_arm32 = \
clang-llvm-3.9.0-linux-x86-64 \
target-sysroot-21-android_arm32 \
target-toolchain-21-linux-android_arm32 \
libffi-3.2.1-2-android_arm32
quadruple.android_arm32 = arm-linux-androideabi
entrySelector.android_arm32 = -Wl,--defsym -Wl,main=Konan_main
llvmLtoFlags.android_arm32 = -exported-symbol=Konan_main -emulated-tls
targetSysRoot.android_arm32 = target-sysroot-21-android_arm32
libffiDir.android_arm32 = libffi-3.2.1-2-android_arm32
linkerKonanFlags.android_arm32 = -lm -latomic -lstdc++
+10
View File
@@ -92,6 +92,16 @@ void setupCompilationFlags() {
// ["-stdlib=libc++", "-isysroot", "$iphoneSimSysrootDir", "-miphoneos-version-min=8.0.0"], // ["-stdlib=libc++", "-isysroot", "$iphoneSimSysrootDir", "-miphoneos-version-min=8.0.0"],
] ]
} }
ext.targetArgs << [
"android_arm32":
["-target", "arm-linux-androideabi",
"--sysroot=$android_arm32SysrootDir",
// HACKS!
/*"-D_LIBCPP_HAS_MUSL_LIBC",*/ "-DOMIT_BACKTRACE", "-D__ANDROID__",
"-I$android_arm32SysrootDir/usr/include/c++/4.9.x",
"-I$android_arm32SysrootDir/usr/include/c++/4.9.x/arm-linux-androideabi"
]
]
ext.targetList = ext.targetArgs.keySet() as List ext.targetList = ext.targetArgs.keySet() as List
if (isLinux()) { if (isLinux()) {
+15
View File
@@ -1,3 +1,18 @@
/*
* 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.
*/
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
+15
View File
@@ -1,3 +1,18 @@
/*
* 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.
*/
#include "City.h" #include "City.h"
#include <string.h> #include <string.h>
+15
View File
@@ -1,3 +1,18 @@
/*
* 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.
*/
#include <cassert> #include <cassert>
#include "Names.h" #include "Names.h"
+15
View File
@@ -1,3 +1,18 @@
/*
* 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.
*/
/* /*
SHA-1 in C SHA-1 in C
By Steve Reid <steve@edmweb.com> By Steve Reid <steve@edmweb.com>
+15
View File
@@ -1,3 +1,18 @@
/*
* 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.
*/
#ifndef COMMON_BASE64_H #ifndef COMMON_BASE64_H
#define COMMON_BASE64_H #define COMMON_BASE64_H
+15
View File
@@ -1,3 +1,18 @@
/*
* 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.
*/
#ifndef COMMON_CITY_H #ifndef COMMON_CITY_H
#define COMMON_CITY_H #define COMMON_CITY_H
+15
View File
@@ -1,3 +1,18 @@
/*
* 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.
*/
#ifndef COMMON_NAMES_H #ifndef COMMON_NAMES_H
#define COMMON_NAMES_H #define COMMON_NAMES_H
+15
View File
@@ -1,3 +1,18 @@
/*
* 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.
*/
#ifndef COMMON_SHA1_H #ifndef COMMON_SHA1_H
#define COMMON_SHA1_H #define COMMON_SHA1_H
+7
View File
@@ -221,6 +221,13 @@ if (isLinux()) {
// } // }
} }
task android_arm32Sysroot(type: HelperNativeDep) {
baseName = "target-sysroot-21-android_arm32"
}
task android_arm32Libffi(type: HelperNativeDep) {
baseName = "libffi-3.2.1-2-android_arm32"
}
task update(type: Copy) { task update(type: Copy) {
dependsOn tasks.withType(NativeDep) dependsOn tasks.withType(NativeDep)
+9 -1
View File
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#ifndef OMIT_BACKTRACE
#include <execinfo.h> #include <execinfo.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -59,6 +60,12 @@ extern "C" {
// TODO: this implementation is just a hack, e.g. the result is inexact; // TODO: this implementation is just a hack, e.g. the result is inexact;
// however it is better to have an inexact stacktrace than not to have any. // however it is better to have an inexact stacktrace than not to have any.
OBJ_GETTER0(GetCurrentStackTrace) { OBJ_GETTER0(GetCurrentStackTrace) {
#if OMIT_BACKTRACE
ObjHeader* result = AllocArrayInstance(theArrayTypeInfo, 1, OBJ_RESULT);
ArrayHeader* array = result->array();
CreateStringFromCString("<UNIMPLEMENTED>", ArrayAddressOfElementAt(array, 0));
return result;
#else
const int maxSize = 32; const int maxSize = 32;
void* buffer[maxSize]; void* buffer[maxSize];
@@ -74,6 +81,7 @@ OBJ_GETTER0(GetCurrentStackTrace) {
symbols[index], ArrayAddressOfElementAt(array, index)); symbols[index], ArrayAddressOfElementAt(array, index));
} }
return result; return result;
#endif
} }
void ThrowException(KRef exception) { void ThrowException(KRef exception) {
+1
View File
@@ -1,6 +1,7 @@
# HTTP client # HTTP client
This example shows how to communicate with libcurl, HTTP/HTTPS/FTP/etc client library. This example shows how to communicate with libcurl, HTTP/HTTPS/FTP/etc client library.
Debian-like distros may need to `apt-get install libcurl4-openssl-dev`.
To build use `./build.sh` script without arguments (or specify `TARGET` variable if cross-compiling). To build use `./build.sh` script without arguments (or specify `TARGET` variable if cross-compiling).
You also may use Gradle to build this sample: `../gradlew build`. You also may use Gradle to build this sample: `../gradlew build`.
+2 -2
View File
@@ -4,7 +4,7 @@ PATH=../../dist/bin:../../bin:$PATH
DIR=. DIR=.
CFLAGS_macbook=-I/opt/local/include CFLAGS_macbook=-I/opt/local/include
CFLAGS_linux=-I/usr/include CFLAGS_linux=-I/usr/include/x86_64-linux-gnu
LINKER_ARGS_macbook="-L/opt/local/lib -lcurl" LINKER_ARGS_macbook="-L/opt/local/lib -lcurl"
LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lcurl" LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lcurl"
@@ -23,5 +23,5 @@ LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET} var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build. COMPILER_ARGS=${!var} # add -opt for an optimized build.
cinterop -copt "$CFLAGS" -copt -I. -def $DIR/libcurl.def -target $TARGET -o libcurl.bc || exit 1 cinterop -copt "$CFLAGS" -copt -I. -copt -I/usr/include -def $DIR/libcurl.def -target $TARGET -o libcurl.bc || exit 1
konanc -target $TARGET src -library libcurl.bc -linkerArgs "$LINKER_ARGS" -o Curl.kexe || exit 1 konanc -target $TARGET src -library libcurl.bc -linkerArgs "$LINKER_ARGS" -o Curl.kexe || exit 1
+2 -2
View File
@@ -54,7 +54,7 @@ fun main(args: Array<String>) {
val length = read(commFd, buffer, bufferLength) val length = read(commFd, buffer, bufferLength)
.ensureUnixCallResult { it >= 0 } .ensureUnixCallResult { it >= 0 }
if (length == 0L) { if (length.toInt() == 0) {
break break
} }
@@ -81,4 +81,4 @@ inline fun Long.ensureUnixCallResult(predicate: (Long) -> Boolean): Long {
throw Error(strerror(errno)!!.toKString()) throw Error(strerror(errno)!!.toKString())
} }
return this return this
} }
@@ -37,11 +37,10 @@ class DependencyDownloader(dependenciesRoot: File, val dependenciesUrl: String,
class DependencyFile(directory: File, fileName: String) { class DependencyFile(directory: File, fileName: String) {
val file = File(directory, fileName).apply { createNewFile() } val file = File(directory, fileName).apply { createNewFile() }
private val dependencies_ = file.readLines().toMutableSet() private val dependencies = file.readLines().toMutableSet()
val dependencies = dependencies_.toSet()
fun contains(dependency: String) = dependencies_.contains(dependency) fun contains(dependency: String) = dependencies.contains(dependency)
fun add(dependency: String) = dependencies_.add(dependency) fun add(dependency: String) = dependencies.add(dependency)
fun addWithSave(dependency: String) { fun addWithSave(dependency: String) {
add(dependency) add(dependency)
save() save()
@@ -50,7 +49,7 @@ class DependencyDownloader(dependenciesRoot: File, val dependenciesUrl: String,
fun save() { fun save() {
val writer = file.writer() val writer = file.writer()
writer.use { writer.use {
dependencies_.forEach { dependencies.forEach {
writer.write(it) writer.write(it)
writer.write("\n") writer.write("\n")
} }