Moved clang flags out of the root build.gardle.

Collected clang args in ClangArgs.kt
Switched dependencies/build.gradle to KonanTarget.
Introduced KonanProperties to take care of target specific properties.
This commit is contained in:
Alexander Gorshenev
2017-07-06 12:39:02 +03:00
committed by alexander-gorshenev
parent 1d532729a8
commit 55c4966203
30 changed files with 432 additions and 343 deletions
+2 -1
View File
@@ -35,7 +35,8 @@ model {
include '**/*.c' include '**/*.c'
} }
binaries.all { binaries.all {
def host = rootProject.ext.host def host = rootProject.ext.hostName
def hostLibffiDir = rootProject.ext.get("${host}LibffiDir") def hostLibffiDir = rootProject.ext.get("${host}LibffiDir")
cCompiler.args hostCompilerArgsForJni cCompiler.args hostCompilerArgsForJni
+3 -3
View File
@@ -106,7 +106,7 @@ kotlinNativeInterop {
compilerOpts '-fPIC' compilerOpts '-fPIC'
linkerOpts '-fPIC' linkerOpts '-fPIC'
linker 'clang++' linker 'clang++'
linkOutputs ":common:${host}Hash" linkOutputs ":common:${hostName}Hash"
headers fileTree('../common/src/hash/headers') { headers fileTree('../common/src/hash/headers') {
include '**/*.h' include '**/*.h'
@@ -148,8 +148,8 @@ build.dependsOn 'compilerClasses','cli_bcClasses','bc_frontendClasses'
// These are just a couple of aliases // These are just a couple of aliases
task stdlib(dependsOn: "${host}Stdlib") task stdlib(dependsOn: "${hostName}Stdlib")
task start(dependsOn: "${host}Start") task start(dependsOn: "${hostName}Start")
// These files are built before the 'dist' is complete, // These files are built before the 'dist' is complete,
// so we provide custom values for // so we provide custom values for
@@ -17,7 +17,8 @@
package org.jetbrains.kotlin.backend.konan package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.target.*
import org.jetbrains.kotlin.backend.konan.util.* import org.jetbrains.kotlin.konan.file.*
import org.jetbrains.kotlin.konan.properties.*
class Distribution(val targetManager: TargetManager, class Distribution(val targetManager: TargetManager,
val propertyFileOverride: String? = null, val propertyFileOverride: String? = null,
@@ -25,7 +26,8 @@ class Distribution(val targetManager: TargetManager,
val target = targetManager.target val target = targetManager.target
val targetName = targetManager.targetName val targetName = targetManager.targetName
val hostSuffix = targetManager.hostSuffix val host = TargetManager.host
val hostSuffix = TargetManager.hostSuffix
val hostTargetSuffix = targetManager.hostTargetSuffix val hostTargetSuffix = targetManager.hostTargetSuffix
val targetSuffix = targetManager.targetSuffix val targetSuffix = targetManager.targetSuffix
@@ -42,23 +44,23 @@ class Distribution(val targetManager: TargetManager,
val properties = File(propertyFileName).loadProperties() val properties = File(propertyFileName).loadProperties()
val klib = "$konanHome/klib" val klib = "$konanHome/klib"
val dependenciesDir = "$konanHome/dependencies"
val dependencies = properties.propertyList("dependencies.$hostTargetSuffix")
val stdlib = "$klib/stdlib" val stdlib = "$klib/stdlib"
val runtime = runtimeFileOverride ?: "$stdlib/targets/${targetName}/native/runtime.bc" val runtime = runtimeFileOverride ?: "$stdlib/targets/${targetName}/native/runtime.bc"
val llvmHome = "$dependenciesDir/${properties.propertyString("llvmHome.$hostSuffix")}" val dependenciesDir = "$konanHome/dependencies"
val hostSysRoot = "$dependenciesDir/${properties.propertyString("targetSysRoot.$hostSuffix")}"
val targetSysRoot = "$dependenciesDir/${properties.propertyString("targetSysRoot.$targetSuffix")}"
val targetToolchain = "$dependenciesDir/${properties.propertyString("targetToolchain.$hostTargetSuffix")}"
val libffi =
"$dependenciesDir/${properties.propertyString("libffiDir.$targetSuffix")}/lib/libffi.a"
val targetProperties = KonanProperties(target, properties, dependenciesDir)
val hostProperties = if (target == host) {
targetProperties
} else {
KonanProperties(host, properties, dependenciesDir)
}
val dependencies = targetProperties.hostTargetList("dependencies")
val llvmHome = hostProperties.absoluteLlvmHome
val hostSysRoot = hostProperties.absoluteTargetSysRoot
val llvmBin = "$llvmHome/bin" val llvmBin = "$llvmHome/bin"
val llvmLib = "$llvmHome/lib" val llvmLib = "$llvmHome/lib"
val llvmLto = "$llvmBin/llvm-lto" val llvmLto = "$llvmBin/llvm-lto"
private val libLTODir = when (TargetManager.host) { private val libLTODir = when (TargetManager.host) {
@@ -20,7 +20,6 @@ import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
import org.jetbrains.kotlin.backend.konan.library.KonanLibrarySearchPathResolver import org.jetbrains.kotlin.backend.konan.library.KonanLibrarySearchPathResolver
import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl
import org.jetbrains.kotlin.backend.konan.util.File
import org.jetbrains.kotlin.backend.konan.util.profile import org.jetbrains.kotlin.backend.konan.util.profile
import org.jetbrains.kotlin.backend.konan.util.removeSuffixIfPresent import org.jetbrains.kotlin.backend.konan.util.removeSuffixIfPresent
import org.jetbrains.kotlin.backend.konan.util.suffixIfNot import org.jetbrains.kotlin.backend.konan.util.suffixIfNot
@@ -30,6 +29,7 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
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.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.target.*
import org.jetbrains.kotlin.konan.target.TargetManager.* import org.jetbrains.kotlin.konan.target.TargetManager.*
import org.jetbrains.kotlin.konan.target.CompilerOutputKind.* import org.jetbrains.kotlin.konan.target.CompilerOutputKind.*
@@ -16,11 +16,11 @@
package org.jetbrains.kotlin.backend.konan package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.util.bufferedReader
import java.lang.ProcessBuilder import java.lang.ProcessBuilder
import java.lang.ProcessBuilder.Redirect import java.lang.ProcessBuilder.Redirect
import org.jetbrains.kotlin.konan.file.*
import org.jetbrains.kotlin.konan.properties.*
import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.target.*
import org.jetbrains.kotlin.backend.konan.util.*
typealias BitcodeFile = String typealias BitcodeFile = String
typealias ObjectFile = String typealias ObjectFile = String
@@ -28,46 +28,39 @@ typealias ExecutableFile = String
// Use "clang -v -save-temps" to write linkCommand() method // Use "clang -v -save-temps" to write linkCommand() method
// for another implementation of this class. // for another implementation of this class.
internal abstract class PlatformFlags(val distribution: Distribution) { internal abstract class PlatformFlags(val properties: KonanProperties) {
val properties = distribution.properties val llvmLtoNooptFlags = properties.llvmLtoNooptFlags
val llvmLtoOptFlags = properties.llvmLtoOptFlags
val target = distribution.target val llvmLtoFlags = properties.llvmLtoFlags
val entrySelector = properties.entrySelector
open val llvmLtoNooptFlags val linkerOptimizationFlags = properties.linkerOptimizationFlags
= propertyTargetList("llvmLtoNooptFlags") val linkerKonanFlags = properties.linkerKonanFlags
open val llvmLtoOptFlags val linkerDebugFlags = properties.linkerDebugFlags
= propertyTargetList("llvmLtoOptFlags") val llvmDebugOptFlags = properties.llvmDebugOptFlags
open val llvmLtoFlags
= propertyTargetList("llvmLtoFlags")
open val entrySelector
= propertyTargetList("entrySelector")
open val linkerOptimizationFlags
= propertyTargetList("linkerOptimizationFlags")
open val linkerKonanFlags
= propertyTargetList("linkerKonanFlags")
open val linkerDebugFlags
= propertyTargetList("linkerDebugFlags")
open val llvmDebugOptFlags
= propertyTargetList("llvmDebugOptFlags")
open val useCompilerDriverAsLinker: Boolean get() = false // TODO: refactor. open val useCompilerDriverAsLinker: Boolean get() = false // TODO: refactor.
abstract fun linkCommand(objectFiles: List<ObjectFile>, abstract fun linkCommand(objectFiles: List<ObjectFile>,
executable: ExecutableFile, optimize: Boolean, debug: Boolean): List<String> executable: ExecutableFile, optimize: Boolean, debug: Boolean): List<String>
val targetLibffiDir = properties.absoluteLibffiDir
val targetLibffi = "$targetLibffiDir/lib/libffi.a"
val targetToolchain = properties.absoluteTargetToolchain
val targetSysRoot = properties.absoluteTargetSysRoot
open fun linkCommandSuffix(): List<String> = emptyList() open fun linkCommandSuffix(): List<String> = emptyList()
protected fun propertyTargetString(name: String) protected fun propertyTargetString(name: String)
= properties.targetString(name, target)!! = properties.targetString(name)!!
protected fun propertyTargetList(name: String) protected fun propertyTargetList(name: String)
= properties.targetList(name, target) = properties.targetList(name)
} }
internal open class AndroidPlatform(distribution: Distribution) internal open class AndroidPlatform(distribution: Distribution)
: PlatformFlags(distribution) { : PlatformFlags(distribution.targetProperties) {
private val prefix = "${distribution.targetToolchain}/bin/" private val prefix = "$targetToolchain/bin/"
private val clang = "$prefix/clang" private val clang = "$prefix/clang"
override val useCompilerDriverAsLinker: Boolean get() = true override val useCompilerDriverAsLinker: Boolean get() = true
@@ -87,11 +80,12 @@ internal open class AndroidPlatform(distribution: Distribution)
} }
internal open class MacOSBasedPlatform(distribution: Distribution) internal open class MacOSBasedPlatform(distribution: Distribution)
: PlatformFlags(distribution) { : PlatformFlags(distribution.targetProperties) {
// TODO: move 'ld' out of the host sysroot, as it doesn't belong here. // TODO: move 'ld' out of the host sysroot, as it doesn't belong here.
private val linker = "${distribution.hostSysRoot}/usr/bin/ld" private val linker = "${distribution.hostSysRoot}/usr/bin/ld"
internal val dsymutil = "${distribution.llvmBin}/llvm-dsymutil" internal val dsymutil = "${distribution.llvmBin}/llvm-dsymutil"
internal val libLTO = distribution.libLTO
open val osVersionMin by lazy { open val osVersionMin by lazy {
listOf( listOf(
@@ -102,10 +96,10 @@ internal open class MacOSBasedPlatform(distribution: Distribution)
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean): List<String> { override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean): List<String> {
return mutableListOf(linker).apply { return mutableListOf(linker).apply {
add("-demangle") add("-demangle")
addAll(listOf("-object_path_lto", "temporary.o", "-lto_library", distribution.libLTO)) addAll(listOf("-object_path_lto", "temporary.o", "-lto_library", libLTO))
addAll(listOf("-dynamic", "-arch", propertyTargetString("arch"))) addAll(listOf("-dynamic", "-arch", propertyTargetString("arch")))
addAll(osVersionMin) addAll(osVersionMin)
addAll(listOf("-syslibroot", distribution.targetSysRoot, "-o", executable)) addAll(listOf("-syslibroot", targetSysRoot, "-o", executable))
addAll(objectFiles) addAll(objectFiles)
if (optimize) addAll(linkerOptimizationFlags) if (optimize) addAll(linkerOptimizationFlags)
if (!debug) addAll(linkerDebugFlags) if (!debug) addAll(linkerDebugFlags)
@@ -121,12 +115,11 @@ internal open class MacOSBasedPlatform(distribution: Distribution)
} }
internal open class LinuxBasedPlatform(distribution: Distribution) internal open class LinuxBasedPlatform(distribution: Distribution)
: PlatformFlags(distribution) { : PlatformFlags(distribution.targetProperties) {
private val targetSysRoot = distribution.targetSysRoot
private val llvmLib = distribution.llvmLib private val llvmLib = distribution.llvmLib
private val libGcc = "$targetSysRoot/${propertyTargetString("libGcc")!!}" private val libGcc = "$targetSysRoot/${propertyTargetString("libGcc")!!}"
private val linker = "${distribution.targetToolchain}/bin/ld.gold" private val linker = "$targetToolchain/bin/ld.gold"
private val pluginOptimizationFlags = propertyTargetList("pluginOptimizationFlags") private val pluginOptimizationFlags = propertyTargetList("pluginOptimizationFlags")
private val specificLibs private val specificLibs
= propertyTargetList("abiSpecificLibraries").map{it -> "-L${targetSysRoot}/$it"} = propertyTargetList("abiSpecificLibraries").map{it -> "-L${targetSysRoot}/$it"}
@@ -158,9 +151,9 @@ internal open class LinuxBasedPlatform(distribution: Distribution)
} }
internal open class MingwPlatform(distribution: Distribution) internal open class MingwPlatform(distribution: Distribution)
: PlatformFlags(distribution) { : PlatformFlags(distribution.targetProperties) {
private val linker = "${distribution.targetToolchain}/bin/clang++" private val linker = "$targetToolchain/bin/clang++"
override val useCompilerDriverAsLinker: Boolean get() = true override val useCompilerDriverAsLinker: Boolean get() = true
@@ -250,7 +243,7 @@ internal class LinkStage(val context: Context) {
private fun link(objectFiles: List<ObjectFile>, libraryProvidedLinkerFlags: List<String>): ExecutableFile { private fun link(objectFiles: List<ObjectFile>, libraryProvidedLinkerFlags: List<String>): ExecutableFile {
val executable = context.config.outputFile val executable = context.config.outputFile
val linkCommand = platform.linkCommand(objectFiles, executable, optimize, debug) + val linkCommand = platform.linkCommand(objectFiles, executable, optimize, debug) +
distribution.libffi + platform.targetLibffi +
asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) + asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) +
entryPointSelector + entryPointSelector +
platform.linkCommandSuffix() + platform.linkCommandSuffix() +
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.backend.konan.ir package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.backend.konan.util.File
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
@@ -38,6 +37,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrBindableSymbolBase import org.jetbrains.kotlin.ir.symbols.impl.IrBindableSymbolBase
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.konan.file.*
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
//-----------------------------------------------------------------------------// //-----------------------------------------------------------------------------//
@@ -235,4 +235,4 @@ class IrSuspendableExpressionImpl(startOffset: Int, endOffset: Int, type: Kotlin
suspensionPointId = suspensionPointId.transform(transformer, data) suspensionPointId = suspensionPointId.transform(transformer, data)
result = result.transform(transformer, data) result = result.transform(transformer, data)
} }
} }
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.backend.konan.library package org.jetbrains.kotlin.backend.konan.library
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.backend.konan.util.File import org.jetbrains.kotlin.konan.file.File
// This scheme describes the Konan Library (klib) layout. // This scheme describes the Konan Library (klib) layout.
interface KonanLibraryLayout { interface KonanLibraryLayout {
@@ -16,9 +16,9 @@
package org.jetbrains.kotlin.backend.konan.library package org.jetbrains.kotlin.backend.konan.library
import org.jetbrains.kotlin.backend.konan.util.File
import org.jetbrains.kotlin.backend.konan.util.removeSuffixIfPresent import org.jetbrains.kotlin.backend.konan.util.removeSuffixIfPresent
import org.jetbrains.kotlin.backend.konan.util.suffixIfNot import org.jetbrains.kotlin.backend.konan.util.suffixIfNot
import org.jetbrains.kotlin.konan.file.File
interface SearchPathResolver { interface SearchPathResolver {
val searchRoots: List<File> val searchRoots: List<File>
@@ -17,7 +17,8 @@
package org.jetbrains.kotlin.backend.konan.library.impl package org.jetbrains.kotlin.backend.konan.library.impl
import org.jetbrains.kotlin.backend.konan.library.KonanLibrary import org.jetbrains.kotlin.backend.konan.library.KonanLibrary
import org.jetbrains.kotlin.backend.konan.util.* import org.jetbrains.kotlin.backend.konan.util.removeSuffixIfPresent
import org.jetbrains.kotlin.konan.file.*
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
open class ZippedKonanLibrary(val klibFile: File, override val target: KonanTarget? = null): KonanLibrary { open class ZippedKonanLibrary(val klibFile: File, override val target: KonanTarget? = null): KonanLibrary {
@@ -18,10 +18,8 @@ package org.jetbrains.kotlin.backend.konan.library.impl
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
import org.jetbrains.kotlin.backend.konan.serialization.deserializeModule import org.jetbrains.kotlin.backend.konan.serialization.deserializeModule
import org.jetbrains.kotlin.backend.konan.util.File import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.backend.konan.util.Properties import org.jetbrains.kotlin.konan.properties.*
import org.jetbrains.kotlin.backend.konan.util.loadProperties
import org.jetbrains.kotlin.backend.konan.util.propertyList
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
@@ -21,7 +21,8 @@ import llvm.LLVMWriteBitcodeToFile
import org.jetbrains.kotlin.backend.konan.library.KonanLibrary import org.jetbrains.kotlin.backend.konan.library.KonanLibrary
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter
import org.jetbrains.kotlin.backend.konan.library.LinkData import org.jetbrains.kotlin.backend.konan.library.LinkData
import org.jetbrains.kotlin.backend.konan.util.* import org.jetbrains.kotlin.konan.file.*
import org.jetbrains.kotlin.konan.properties.*
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
abstract class FileBasedLibraryWriter ( abstract class FileBasedLibraryWriter (
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.backend.konan.library.impl
import org.jetbrains.kotlin.backend.konan.library.KonanLibrary import org.jetbrains.kotlin.backend.konan.library.KonanLibrary
import org.jetbrains.kotlin.backend.konan.library.LinkData import org.jetbrains.kotlin.backend.konan.library.LinkData
import org.jetbrains.kotlin.backend.konan.util.File import org.jetbrains.kotlin.konan.file.File
internal class MetadataWriterImpl(library: KonanLibrary): KonanLibrary by library { internal class MetadataWriterImpl(library: KonanLibrary): KonanLibrary by library {
@@ -22,13 +22,13 @@ import llvm.*
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.backend.konan.KonanVersion import org.jetbrains.kotlin.backend.konan.KonanVersion
import org.jetbrains.kotlin.backend.konan.util.File
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.SourceManager.FileEntry import org.jetbrains.kotlin.ir.SourceManager.FileEntry
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
+1
View File
@@ -89,6 +89,7 @@ osVersionMin.ios_sim = 8.0
# Linux x86-64. # Linux x86-64.
llvmVersion.linux = 3.9.0 llvmVersion.linux = 3.9.0
llvmHome.linux = clang-llvm-3.9.0-linux-x86-64 llvmHome.linux = clang-llvm-3.9.0-linux-x86-64
gccToolchain.linux = target-gcc-toolchain-3-linux-x86-64
targetToolchain.linux = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu targetToolchain.linux = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu
quadruple.linux = x86_64-unknown-linux-gnu quadruple.linux = x86_64-unknown-linux-gnu
+27 -134
View File
@@ -14,13 +14,21 @@
* limitations under the License. * limitations under the License.
*/ */
import groovy.io.FileType import groovy.io.FileType
import org.jetbrains.kotlin.konan.target.*
//ant.importBuild 'backend.native/kotlin-ir/build.xml' import org.jetbrains.kotlin.konan.properties.*
defaultTasks 'clean', 'dist' defaultTasks 'clean', 'dist'
convention.plugins.platformInfo = new PlatformInfo() convention.plugins.platformInfo = new PlatformInfo()
ext {
konanPropertiesFile = project(':backend.native').file('konan.properties')
konanProperties = PropertiesKt.loadProperties(konanPropertiesFile.absolutePath)
dependenciesDir = rootProject.file("dist/dependencies")
clangManager = new ClangManager(konanProperties, dependenciesDir.absolutePath)
}
allprojects { allprojects {
if (path != ":dependencies") { if (path != ":dependencies") {
evaluationDependsOn(":dependencies") evaluationDependsOn(":dependencies")
@@ -33,14 +41,20 @@ allprojects {
} }
} }
setupHostAndTarget()
loadCommandLineProperties() loadCommandLineProperties()
loadLocalProperties() loadLocalProperties()
setupCompilationFlags()
setupClang(project) setupClang(project)
} }
void setupHostAndTarget() {
ext.hostName = TargetManager.hostName
ext.targetList = TargetManager.enabled*.userName as List
}
void setupClang(Project project) { void setupClang(Project project) {
project.convention.plugins.clangManager = project.rootProject.ext.clangManager
project.convention.plugins.execClang = new org.jetbrains.kotlin.ExecClang(project) project.convention.plugins.execClang = new org.jetbrains.kotlin.ExecClang(project)
project.plugins.withType(NativeComponentPlugin) { project.plugins.withType(NativeComponentPlugin) {
@@ -67,13 +81,13 @@ void setupClang(Project project) {
toolChains { toolChains {
clang(Clang) { clang(Clang) {
clangPath.each { hostClang.hostClangPath.each {
path it path it
} }
eachPlatform { // TODO: will not work when cross-compiling eachPlatform { // TODO: will not work when cross-compiling
[cCompiler, cppCompiler, linker].each { [cCompiler, cppCompiler, linker].each {
it.withArguments { it.addAll(hostClangArgs) } it.withArguments { it.addAll(project.hostClangArgs) }
} }
} }
@@ -84,98 +98,6 @@ void setupClang(Project project) {
} }
} }
String getTargetArg(String target) {
def result = konanProperties.getProperty("quadruple.$target")
if (result == null) {
throw IllegalArgumentException("konan.properties has no LLVM target args for target: $target")
}
return result
}
void setupCompilationFlags() {
ext.clangPath = ["$llvmDir/bin"]
ext.clangArgs = []
ext.targetArgs = [:]
final String binDir
if (isLinux()) {
ext.host = "linux"
ext.targetArgs <<
[(ext.host):
["--sysroot=${gccToolchainDir}/${gnuTriplet}/sysroot",
"-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=64"],
"raspberrypi":
["-target", getTargetArg("raspberrypi"),
"-mfpu=vfp", "-mfloat-abi=hard",
"-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=32",
"--sysroot=$raspberrypiSysrootDir",
// TODO: those two are hacks.
"-I$raspberrypiSysrootDir/usr/include/c++/4.8.3",
"-I$raspberrypiSysrootDir/usr/include/c++/4.8.3/arm-linux-gnueabihf"]
]
} else if (isWindows()) {
ext.host = "mingw"
ext.targetArgs <<
[(ext.host):
["-target", "x86_64-w64-mingw32", "--sysroot=${mingwWithLlvmDir}",
"-DUSE_GCC_UNWIND=1", "-DUSE_PE_COFF_SYMBOLS=1", "-DKONAN_WINDOWS=1"]]
} else {
ext.host = "macbook"
ext.targetArgs <<
[(ext.host):
["--sysroot=$macbookSysrootDir", "-mmacosx-version-min=10.11"],
"iphone":
["-stdlib=libc++", "-arch", "arm64", "-isysroot", "$iphoneSysrootDir",
"-miphoneos-version-min=8.0.0"]
// TODO: re-enable after simulator sysroot is available in the dependencies
// "iphone_sim":
// ["-stdlib=libc++", "-isysroot", "$iphoneSimSysrootDir", "-miphoneos-version-min=8.0.0"],
]
}
if (isLinux() || isMac()) {
ext.targetArgs << [
"android_arm32":
["-target", getTargetArg("android_arm32"),
"--sysroot=$android_arm32SysrootDir",
"-D__ANDROID__", "-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=32", "-DKONAN_ANDROID",
// HACKS!
"-I$android_arm32SysrootDir/usr/include/c++/4.9.x",
"-I$android_arm32SysrootDir/usr/include/c++/4.9.x/arm-linux-androideabi"],
"android_arm64":
["-target", getTargetArg("android_arm64"),
"--sysroot=$android_arm64SysrootDir",
"-D__ANDROID__", "-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=64", "-DKONAN_ANDROID",
// HACKS!
"-I$android_arm64SysrootDir/usr/include/c++/4.9.x",
"-I$android_arm64SysrootDir/usr/include/c++/4.9.x/aarch64-linux-android"]
]
}
ext.targetList = ext.targetArgs.keySet() as List
if (isLinux()) {
binDir = "$gccToolchainDir/$gnuTriplet/bin"
ext.clangArgs.addAll([
"--gcc-toolchain=$gccToolchainDir"
])
} else if (isWindows()) {
binDir = "$mingwWithLlvmDir/bin"
} else {
binDir = "$macbookSysrootDir/usr/bin"
}
ext.clangArgs << "-B$binDir"
ext.hostClangArgs = ext.clangArgs.clone()
ext.hostClangArgs.addAll(ext.targetArgs[host])
ext.clangPath << binDir
ext.jvmArgs = ["-ea"]
File jdkHome = new File(System.getProperty('java.home')).absoluteFile.parentFile
ext.hostCompilerArgsForJni = ["", jniHostPlatformIncludeDir()].collect { "-I$jdkHome/include/$it" } as String[]
}
void loadLocalProperties() { void loadLocalProperties() {
if (new File("$project.rootDir/local.properties").exists()) { if (new File("$project.rootDir/local.properties").exists()) {
Properties props = new Properties() Properties props = new Properties()
@@ -197,50 +119,20 @@ void loadCommandLineProperties() {
} }
class PlatformInfo { class PlatformInfo {
private final String osName = System.properties['os.name']
private final String osArch = System.properties['os.arch']
boolean isMac() { boolean isMac() {
return osName == 'Mac OS X' return TargetManager.host == KonanTarget.MACBOOK
} }
boolean isWindows() { boolean isWindows() {
return osName.startsWith('Windows'); return TargetManager.host == KonanTarget.MINGW
} }
boolean isLinux() { boolean isLinux() {
return osName == 'Linux' return TargetManager.host == KonanTarget.LINUX
}
boolean isAmd64() {
return osArch in ['x86_64', 'amd64']
}
String getGnuTriplet() {
if (isLinux() && isAmd64()) {
return "x86_64-unknown-linux-gnu"
} else {
throw unsupportedPlatformException()
}
}
String simpleOsName() {
if (isMac()) return 'macos'
if (isLinux()) return 'linux'
if (isWindows()) return 'windows'
throw unsupportedPlatformException()
}
String jniHostPlatformIncludeDir() {
if (isMac()) return "darwin"
if (isLinux()) return "linux"
if (isWindows()) return "win32"
throw unsupportedPlatformException()
} }
Throwable unsupportedPlatformException() { Throwable unsupportedPlatformException() {
return new Error("unsupported platform: $osName/$osArch") return new TargetSupportException()
} }
} }
@@ -323,7 +215,7 @@ task listDist(type: Exec) {
} }
task distRuntime(type: Copy) { task distRuntime(type: Copy) {
dependsOn "${host}CrossDistRuntime" dependsOn "${hostName}CrossDistRuntime"
dependsOn('commonDistRuntime') dependsOn('commonDistRuntime')
} }
@@ -331,7 +223,7 @@ task commonDistRuntime(type: Copy) {
destinationDir file('dist') destinationDir file('dist')
// Target independant common part. // Target independant common part.
from(project(':runtime').file("build/${host}Stdlib")) { from(project(':runtime').file("build/${hostName}Stdlib")) {
include('**') include('**')
into('klib/stdlib') into('klib/stdlib')
} }
@@ -375,7 +267,8 @@ task crossDist {
task bundle(type: (isWindows()) ? Zip : Tar) { task bundle(type: (isWindows()) ? Zip : Tar) {
dependsOn('crossDist') dependsOn('crossDist')
baseName = "kotlin-native-${simpleOsName()}-${project.konanVersion}" def simpleOsName = TargetManager.simpleOsName()
baseName = "kotlin-native-$simpleOsName-${project.konanVersion}"
from("$project.rootDir/dist") { from("$project.rootDir/dist") {
include '**' include '**'
exclude 'dependencies' exclude 'dependencies'
@@ -22,52 +22,7 @@ import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskAction
class CompilePerTarget extends CompileCppToBitcode { import org.jetbrains.kotlin.konan.target.KonanTarget
private List<String> targetList = []
private Map<String, List<String>> targetArgs = null
private Map<String, List<String>> targetLinkerArgs = null
void targetList(List<String> list) {
targetList.addAll(list)
}
void targetArgs(Map<String, List<String>> map) {
targetArgs = map
}
private Map<String, List<String>> getTargetArgs() {
return targetArgs
}
void targetLinkerArgs(Map<String, List<String>> map) {
targetLinkerArgs = map
}
private Map<String, List<String>> getTargetLinkerArgs() {
return targetLinkerArgs
}
@TaskAction
void compile() {
def targetList = this.targetList
def targetArgs = getTargetArgs()
def targetLinkerArgs = getTargetLinkerArgs()
def commonCompilerArgs = getCompilerArgs().clone()
def commonLinkerArgs = getLinkerArgs().clone()
targetList.each {
this.compilerArgs = []
this.linkerArgs = []
target(it)
compilerArgs(commonCompilerArgs)
if (targetArgs != null)
compilerArgs(targetArgs[it])
linkerArgs(commonLinkerArgs)
if (targetLinkerArgs != null)
linkerArgs(targetLinkerArgs[it])
super.compile()
}
}
}
class CompileCppToBitcode extends DefaultTask { class CompileCppToBitcode extends DefaultTask {
private String name = "main" private String name = "main"
@@ -123,6 +78,10 @@ class CompileCppToBitcode extends DefaultTask {
return linkerArgs return linkerArgs
} }
protected String getTarget() {
return target
}
void compilerArgs(String... args) { void compilerArgs(String... args) {
compilerArgs.addAll(args) compilerArgs.addAll(args)
} }
@@ -139,6 +98,11 @@ class CompileCppToBitcode extends DefaultTask {
linkerArgs.addAll(args) linkerArgs.addAll(args)
} }
List<String> targetArgs(String target) {
def result = project.rootProject.targetClangArgs(KonanTarget.valueOf(target.toUpperCase()))
return result
}
@TaskAction @TaskAction
void compile() { void compile() {
// the strange code below seems to be required due to some Gradle (Groovy?) behaviour // the strange code below seems to be required due to some Gradle (Groovy?) behaviour
@@ -154,6 +118,7 @@ class CompileCppToBitcode extends DefaultTask {
executable "clang++" executable "clang++"
args '-std=c++11' args '-std=c++11'
args targetArgs(this.target)
args compilerArgs args compilerArgs
args "-I$headersDir" args "-I$headersDir"
@@ -53,12 +53,9 @@ class ExecClang {
throw new GradleException("unsupported clang executable: $executable") throw new GradleException("unsupported clang executable: $executable")
} }
environment["PATH"] = project.files(project.clangPath).asPath + environment["PATH"] = project.files(project.hostClang.hostClangPath).asPath +
File.pathSeparator + environment["PATH"] File.pathSeparator + environment["PATH"]
args project.clangArgs
} }
} }
} }
return project.exec(extendedAction) return project.exec(extendedAction)
@@ -228,7 +228,7 @@ class NamedNativeInteropConfig implements Named {
} }
// TODO: the interop plugin should probably be reworked to execute clang from build scripts directly // TODO: the interop plugin should probably be reworked to execute clang from build scripts directly
environment['PATH'] = project.files(project.clangPath).asPath + environment['PATH'] = project.files(project.hostClang.hostClangPath).asPath +
File.pathSeparator + environment['PATH'] File.pathSeparator + environment['PATH']
args compilerOpts.collectMany { ['-copt', it] } args compilerOpts.collectMany { ['-copt', it] }
+1 -2
View File
@@ -22,12 +22,11 @@ targetList.each { targetName ->
task ("${targetName}Hash", type: CompileCppToBitcode) { task ("${targetName}Hash", type: CompileCppToBitcode) {
name 'hash' name 'hash'
target targetName target targetName
compilerArgs targetArgs[targetName]
} }
} }
task build { task build {
dependsOn "${host}Hash" dependsOn "${hostName}Hash"
} }
task clean { task clean {
+28 -50
View File
@@ -15,6 +15,10 @@
*/ */
import static DependencyTaskKind.* import static DependencyTaskKind.*
import org.jetbrains.kotlin.konan.target.*
import static org.jetbrains.kotlin.konan.target.KonanTarget.*
import org.jetbrains.kotlin.konan.properties.KonanProperties
import org.jetbrains.kotlin.konan.properties.*
buildscript { buildscript {
repositories { repositories {
@@ -30,10 +34,6 @@ buildscript {
apply plugin: 'com.jfrog.bintray' apply plugin: 'com.jfrog.bintray'
rootProject.ext.konanPropertiesFile = project(':backend.native').file('konan.properties')
rootProject.ext.konanProperties = new Properties()
rootProject.konanProperties.load(new FileInputStream(rootProject.konanPropertiesFile))
configurations { configurations {
kotlin_compiler_jar kotlin_compiler_jar
kotlin_compiler_pom kotlin_compiler_pom
@@ -106,20 +106,7 @@ task update_kotlin_compiler(type: DefaultTask) {
} }
abstract class NativeDep extends DefaultTask { abstract class NativeDep extends DefaultTask {
protected final String hostSystem = TargetManager.longerSystemName();
private String getCurrentHostTarget() {
if (project.isMac() && project.isAmd64()) {
return 'darwin-macos'
} else if (project.isLinux() && project.isAmd64()) {
return 'linux-x86-64'
} else if (project.isWindows() && project.isAmd64()) {
return 'windows-x86-64'
} else {
throw project.unsupportedPlatformException()
}
}
protected final String host = getCurrentHostTarget();
String baseUrl = "https://jetbrains.bintray.com/kotlin-native-dependencies" String baseUrl = "https://jetbrains.bintray.com/kotlin-native-dependencies"
@Input @Input
@@ -130,7 +117,7 @@ abstract class NativeDep extends DefaultTask {
} }
protected File getBaseOutDir() { protected File getBaseOutDir() {
final File res = project.rootProject.file("dist/dependencies") final File res = project.rootProject.ext.dependenciesDir
res.mkdirs() res.mkdirs()
return res return res
} }
@@ -193,15 +180,6 @@ class HelperNativeDep extends TgzNativeDep {
} }
} }
static String substituteName(String name) {
switch (name) {
case "macbook": return "osx"
case "iphone": return "ios"
case "iphoneSim": return "ios_sim"
}
return name
}
enum DependencyTaskKind { enum DependencyTaskKind {
LIBFFI("Libffi"), SYSROOT("Sysroot") LIBFFI("Libffi"), SYSROOT("Sysroot")
@@ -213,22 +191,23 @@ enum DependencyTaskKind {
String toString() { return name } String toString() { return name }
} }
void dependencyTask(String target, DependencyTaskKind kind) { void dependencyTask(KonanTarget target, DependencyTaskKind kind) {
String dependencyBaseName String dependencyBaseName
def properties = rootProject.konanProperties def properties = rootProject.ext.konanProperties
def dirs = new KonanProperties(target, properties, null)
switch (kind) { switch (kind) {
case LIBFFI: case LIBFFI:
dependencyBaseName = properties.getProperty("libffiDir.${substituteName(target)}") dependencyBaseName = dirs.libffiDir
break break
case SYSROOT: case SYSROOT:
dependencyBaseName = properties.getProperty("targetSysRoot.${substituteName(target)}") dependencyBaseName = dirs.targetSysRoot
break break
} }
if (dependencyBaseName == null) { if (dependencyBaseName == null) {
throw project.unsupportedPlatformException() throw project.unsupportedPlatformException()
} }
task "${target}${kind}"(type: HelperNativeDep) { task "${target.userName}${kind}"(type: HelperNativeDep) {
baseName = dependencyBaseName baseName = dependencyBaseName
} }
} }
@@ -236,37 +215,36 @@ void dependencyTask(String target, DependencyTaskKind kind) {
if (isLinux()) { if (isLinux()) {
// The gcc toolchain contains the sysroot for linux platform. // The gcc toolchain contains the sysroot for linux platform.
task gccToolchain(type: HelperNativeDep) { task gccToolchain(type: HelperNativeDep) {
baseName = "target-gcc-toolchain-3-$host" baseName = "target-gcc-toolchain-3-$hostSystem"
} }
dependencyTask("linux", LIBFFI) dependencyTask(LINUX, LIBFFI)
dependencyTask("raspberrypi", SYSROOT) dependencyTask(RASPBERRYPI, SYSROOT)
dependencyTask("raspberrypi", LIBFFI) dependencyTask(RASPBERRYPI, LIBFFI)
} else if (isWindows()) { } else if (isWindows()) {
task mingwWithLlvm(type: HelperNativeDep) { task mingwWithLlvm(type: HelperNativeDep) {
baseName = "msys2-mingw-w64-x86_64-gcc-6.3.0-clang-llvm-3.9.1-$host" baseName = "msys2-mingw-w64-x86_64-gcc-6.3.0-clang-llvm-3.9.1-$hostSystem"
} }
dependencyTask("mingw", LIBFFI) dependencyTask(MINGW, LIBFFI)
} else { } else {
dependencyTask("macbook", SYSROOT) dependencyTask(MACBOOK, SYSROOT)
dependencyTask("macbook", LIBFFI) dependencyTask(MACBOOK, LIBFFI)
dependencyTask("iphone", SYSROOT) dependencyTask(IPHONE, SYSROOT)
dependencyTask("iphone", LIBFFI) dependencyTask(IPHONE, LIBFFI)
// TODO: re-enable when we known how to bring the simulator sysroot to dependencies. // TODO: re-enable when we known how to bring the simulator sysroot to dependencies.
// dependencyTask("iphoneSim", SYSROOT) // dependencyTask(IPHONE_SIM, SYSROOT)
} }
if (isLinux() || isMac()) { if (isLinux() || isMac()) {
task llvm(type: HelperNativeDep) { task llvm(type: HelperNativeDep) {
baseName = "clang-llvm-$llvmVersion-$host" baseName = "clang-llvm-$llvmVersion-$hostSystem"
} }
dependencyTask("android_arm32", SYSROOT) dependencyTask(ANDROID_ARM32, SYSROOT)
dependencyTask("android_arm32", LIBFFI) dependencyTask(ANDROID_ARM32, LIBFFI)
dependencyTask("android_arm64", SYSROOT) dependencyTask(ANDROID_ARM64, SYSROOT)
dependencyTask("android_arm64", LIBFFI) dependencyTask(ANDROID_ARM64, LIBFFI)
} }
task update(type: Copy) { task update(type: Copy) {
@@ -22,7 +22,7 @@ import java.util.Properties
import org.jetbrains.kotlin.backend.konan.library.impl.* import org.jetbrains.kotlin.backend.konan.library.impl.*
import org.jetbrains.kotlin.backend.konan.library.KonanLibrary import org.jetbrains.kotlin.backend.konan.library.KonanLibrary
import org.jetbrains.kotlin.backend.konan.library.KonanLibrarySearchPathResolver import org.jetbrains.kotlin.backend.konan.library.KonanLibrarySearchPathResolver
import org.jetbrains.kotlin.backend.konan.util.File import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.target.TargetManager import org.jetbrains.kotlin.konan.target.TargetManager
fun printUsage() { fun printUsage() {
+1 -3
View File
@@ -25,7 +25,6 @@ targetList.each { targetName ->
dependsOn ":common:${targetName}Hash" dependsOn ":common:${targetName}Hash"
dependsOn "${targetName}Launcher" dependsOn "${targetName}Launcher"
target targetName target targetName
compilerArgs targetArgs[targetName]
compilerArgs '-g' compilerArgs '-g'
compilerArgs '-I' + project.file('../common/src/hash/headers') compilerArgs '-I' + project.file('../common/src/hash/headers')
compilerArgs '-I' + project.file(rootProject.ext.get("${targetName}LibffiDir") + "/include") compilerArgs '-I' + project.file(rootProject.ext.get("${targetName}LibffiDir") + "/include")
@@ -38,14 +37,13 @@ targetList.each { targetName ->
name "launcher" name "launcher"
srcRoot file('src/launcher') srcRoot file('src/launcher')
target targetName target targetName
compilerArgs targetArgs[targetName]
compilerArgs '-g' compilerArgs '-g'
compilerArgs '-I' + project.file('../common/src/hash/headers') compilerArgs '-I' + project.file('../common/src/hash/headers')
compilerArgs '-I' + project.file('src/main/cpp') compilerArgs '-I' + project.file('src/main/cpp')
} }
} }
task hostRuntime(dependsOn: "${rootProject.ext.host}Runtime") task hostRuntime(dependsOn: "${hostName}Runtime")
task clean { task clean {
doLast { doLast {
@@ -0,0 +1,103 @@
/*
* 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.KonanProperties
import org.jetbrains.kotlin.konan.file.File
class ClangTarget(val target: KonanTarget, val konanProperties: KonanProperties) {
val sysRoot = konanProperties.absoluteTargetSysRoot!!
val targetArg = konanProperties.targetArg
val specificClangArgs: List<String> get() {
return when (target) {
KonanTarget.LINUX ->
listOf("--sysroot=$sysRoot",
"-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=64")
KonanTarget.RASPBERRYPI ->
listOf("-target", targetArg!!,
"-mfpu=vfp", "-mfloat-abi=hard",
"-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=32",
"--sysroot=$sysRoot",
// TODO: those two are hacks.
"-I$sysRoot/usr/include/c++/4.8.3",
"-I$sysRoot/usr/include/c++/4.8.3/arm-linux-gnueabihf")
KonanTarget.MINGW ->
listOf("-target", targetArg!!, "--sysroot=$sysRoot",
"-DUSE_GCC_UNWIND=1", "-DUSE_PE_COFF_SYMBOLS=1", "-DKONAN_WINDOWS=1")
KonanTarget.MACBOOK ->
listOf("--sysroot=$sysRoot", "-mmacosx-version-min=10.11")
KonanTarget.IPHONE ->
listOf("-stdlib=libc++", "-arch", "arm64", "-isysroot", "$sysRoot", "-miphoneos-version-min=8.0.0")
KonanTarget.IPHONE_SIM ->
listOf("-stdlib=libc++", "-isysroot", "$sysRoot", "-miphoneos-version-min=8.0.0")
KonanTarget.ANDROID_ARM32 ->
listOf("-target", targetArg!!,
"--sysroot=$sysRoot",
"-D__ANDROID__", "-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=32", "-DKONAN_ANDROID",
// HACKS!
"-I$sysRoot/usr/include/c++/4.9.x",
"-I$sysRoot/usr/include/c++/4.9.x/arm-linux-androideabi")
KonanTarget.ANDROID_ARM64 ->
listOf("-target", targetArg!!,
"--sysroot=$sysRoot",
"-D__ANDROID__", "-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=64", "-DKONAN_ANDROID",
// HACKS!
"-I$sysRoot/usr/include/c++/4.9.x",
"-I$sysRoot/usr/include/c++/4.9.x/aarch64-linux-android")
}
}
}
class ClangHost(val hostProperties: KonanProperties) {
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 -> "$sysRoot/usr/bin"
else -> throw TargetSupportException("Unexpected host platform")
}
private val extraHostClangArgs =
if (TargetManager.host == KonanTarget.LINUX) {
listOf("--gcc-toolchain=$gccToolchain")
} else {
emptyList()
}
val commonClangArgs = listOf("-B$binDir") + extraHostClangArgs
val hostClangPath = listOf("$llvmDir/bin", binDir)
private val jdkHome = File.jdkHome.absoluteFile.parent
val hostCompilerArgsForJni = listOf("", TargetManager.jniHostPlatformIncludeDir).map { "-I$jdkHome/include/$it" }
}
@@ -0,0 +1,43 @@
/*
* 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 targetClangs = enabledTargets.map {
it to ClangTarget(it, konanProperties[it]!!)
}.toMap()
private val hostClang = ClangHost(konanProperties[host]!!)
// These are converted to arrays to be convenient
// in groovy plugins.
val hostClangArgs = (hostClang.commonClangArgs + targetClangs[host]!!.specificClangArgs).toTypedArray()
fun targetClangArgs(target: KonanTarget)
= (hostClang.commonClangArgs + targetClangs[target]!!.specificClangArgs).toTypedArray()
val hostCompilerArgsForJni = hostClang.hostCompilerArgsForJni.toTypedArray()
}
@@ -0,0 +1,72 @@
/*
* 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.properties
import org.jetbrains.kotlin.konan.file.*
import org.jetbrains.kotlin.konan.target.*
class KonanProperties(val target: KonanTarget, val properties: Properties, val baseDir: String? = null) {
fun targetString(key: String): String?
= properties.targetString(key, target)
fun targetList(key: String): List<String>
= properties.targetList(key, target)
fun hostString(key: String): String?
= properties.hostString(key)
fun hostList(key: String): List<String>
= properties.hostList(key)
fun hostTargetString(key: String): String?
= properties.hostTargetString(key, target)
fun hostTargetList(key: String): List<String>
= properties.hostTargetList(key, target)
// TODO: Delegate to a map?
val llvmLtoNooptFlags get() = targetList("llvmLtoNooptFlags")
val llvmLtoOptFlags get() = targetList("llvmLtoOptFlags")
val llvmLtoFlags get() = targetList("llvmLtoFlags")
val entrySelector get() = targetList("entrySelector")
val linkerOptimizationFlags get() = targetList("linkerOptimizationFlags")
val linkerKonanFlags get() = targetList("linkerKonanFlags")
val linkerDebugFlags get() = targetList("linkerDebugFlags")
val llvmDebugOptFlags get() = targetList("llvmDebugOptFlags")
val targetSysRoot get() = targetString("targetSysRoot")
val libffiDir get() = targetString("libffiDir")
val gccToolchain get() = targetString("gccToolchain")
val targetArg get() = targetString("quadruple")
val llvmHome get() = targetString("llvmHome")
// Notice: this one is host-target.
val targetToolchain get() = hostTargetString("targetToolchain")
fun absolute(value: String?) = "${baseDir!!}/${value!!}"
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")
}
}
@@ -24,9 +24,13 @@ enum class KonanTarget(val targetSuffix: String, val programSuffix: String, var
LINUX("linux", "kexe"), LINUX("linux", "kexe"),
MINGW("mingw", "exe"), MINGW("mingw", "exe"),
MACBOOK("osx", "kexe"), MACBOOK("osx", "kexe"),
RASPBERRYPI("raspberrypi", "kexe") RASPBERRYPI("raspberrypi", "kexe");
val userName get() = name.toLowerCase()
} }
fun hostTargetSuffix(host: KonanTarget, target: KonanTarget) =
if (target == host) host.targetSuffix else "${host.targetSuffix}-${target.targetSuffix}"
enum class CompilerOutputKind { enum class CompilerOutputKind {
PROGRAM { PROGRAM {
override fun suffix(target: KonanTarget?) = ".${target!!.programSuffix}" override fun suffix(target: KonanTarget?) = ".${target!!.programSuffix}"
@@ -42,37 +46,15 @@ enum class CompilerOutputKind {
} }
class TargetManager(val userRequest: String? = null) { class TargetManager(val userRequest: String? = null) {
val targets = KonanTarget.values().associate{ it.name.toLowerCase() to it } val targets = KonanTarget.values().associate{ it.userName to it }
val target = determineCurrent() val target = determineCurrent()
val targetName val targetName
get() = target.name.toLowerCase() get() = target.name.toLowerCase()
init {
when (host) {
KonanTarget.LINUX -> {
KonanTarget.LINUX.enabled = true
KonanTarget.RASPBERRYPI.enabled = true
KonanTarget.ANDROID_ARM32.enabled = true
KonanTarget.ANDROID_ARM64.enabled = true
}
KonanTarget.MINGW -> {
KonanTarget.MINGW.enabled = true
}
KonanTarget.MACBOOK -> {
KonanTarget.MACBOOK.enabled = true
KonanTarget.IPHONE.enabled = true
KonanTarget.IPHONE_SIM.enabled = true
KonanTarget.ANDROID_ARM32.enabled = true
KonanTarget.ANDROID_ARM64.enabled = true
}
else ->
error("Unknown host platform: $host")
}
}
fun known(name: String): String { fun known(name: String): String {
if (targets[name] == null) { if (targets[name] == null) {
error("Unknown target: $name. Use -list_targets to see the list of available targets") throw TargetSupportException("Unknown target: $name. Use -list_targets to see the list of available targets")
} }
return name return name
} }
@@ -94,36 +76,52 @@ class TargetManager(val userRequest: String? = null) {
} }
} }
val hostSuffix get() = host.targetSuffix val hostTargetSuffix get() = hostTargetSuffix(host, target)
val hostTargetSuffix get() =
if (target == host) host.targetSuffix else "${host.targetSuffix}-${target.targetSuffix}"
val targetSuffix get() = target.targetSuffix val targetSuffix get() = target.targetSuffix
val programSuffix get() = CompilerOutputKind.PROGRAM.suffix(target) val programSuffix get() = CompilerOutputKind.PROGRAM.suffix(target)
companion object { companion object {
fun host_os(): String { fun host_os(): String {
val javaOsName = System.getProperty("os.name") val javaOsName = System.getProperty("os.name")
return when { return when {
javaOsName == "Mac OS X" -> "osx" javaOsName == "Mac OS X" -> "osx"
javaOsName == "Linux" -> "linux" javaOsName == "Linux" -> "linux"
javaOsName.startsWith("Windows") -> "windows" javaOsName.startsWith("Windows") -> "windows"
else -> error("Unknown operating system: ${javaOsName}") else -> throw TargetSupportException("Unknown operating system: ${javaOsName}")
} }
} }
@JvmStatic
fun simpleOsName(): String { fun simpleOsName(): String {
val hostOs = host_os() val hostOs = host_os()
return if (hostOs == "osx") "macos" else hostOs return if (hostOs == "osx") "macos" else hostOs
} }
@JvmStatic
fun longerSystemName(): String = when (host) {
KonanTarget.MACBOOK -> "darwin-macos"
KonanTarget.LINUX -> "linux-x86-64"
KonanTarget.MINGW -> "windows-x86-64"
else -> throw TargetSupportException("Unknown host: $host")
}
val jniHostPlatformIncludeDir: String
get() = when(host) {
KonanTarget.MACBOOK -> "darwin"
KonanTarget.LINUX -> "linux"
KonanTarget.MINGW ->"win32"
else -> throw TargetSupportException("Unknown host: $host.")
}
fun host_arch(): String { fun host_arch(): String {
val javaArch = System.getProperty("os.arch") val javaArch = System.getProperty("os.arch")
return when (javaArch) { return when (javaArch) {
"x86_64" -> "x86_64" "x86_64" -> "x86_64"
"amd64" -> "x86_64" "amd64" -> "x86_64"
"arm64" -> "arm64" "arm64" -> "arm64"
else -> error("Unknown hardware platform: ${javaArch}") else -> throw TargetSupportException("Unknown hardware platform: ${javaArch}")
} }
} }
@@ -131,8 +129,41 @@ class TargetManager(val userRequest: String? = null) {
"osx" -> KonanTarget.MACBOOK "osx" -> KonanTarget.MACBOOK
"linux" -> KonanTarget.LINUX "linux" -> KonanTarget.LINUX
"windows" -> KonanTarget.MINGW "windows" -> KonanTarget.MINGW
else -> error("Unknown host target: ${host_os()} ${host_arch()}") else -> throw TargetSupportException("Unknown host target: ${host_os()} ${host_arch()}")
} }
val hostSuffix get() = host.targetSuffix
@JvmStatic
val hostName get() = host.name.toLowerCase()
init {
when (host) {
KonanTarget.LINUX -> {
KonanTarget.LINUX.enabled = true
KonanTarget.RASPBERRYPI.enabled = true
KonanTarget.ANDROID_ARM32.enabled = true
KonanTarget.ANDROID_ARM64.enabled = true
}
KonanTarget.MINGW -> {
KonanTarget.MINGW.enabled = true
}
KonanTarget.MACBOOK -> {
KonanTarget.MACBOOK.enabled = true
KonanTarget.IPHONE.enabled = true
//KonanTarget.IPHONE_SIM.enabled = true
KonanTarget.ANDROID_ARM32.enabled = true
KonanTarget.ANDROID_ARM64.enabled = true
}
else ->
throw TargetSupportException("Unknown host platform: $host")
}
}
@JvmStatic
val enabled: List<KonanTarget>
get() = KonanTarget.values().asList().filter { it.enabled }
} }
} }
class TargetSupportException (message: String = "", cause: Throwable? = null) : Exception(message, cause)
@@ -14,7 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.backend.konan.util package org.jetbrains.kotlin.konan.properties
import org.jetbrains.kotlin.konan.file.*
typealias Properties = java.util.Properties typealias Properties = java.util.Properties
@@ -26,6 +28,8 @@ fun File.loadProperties(): Properties {
return properties return properties
} }
fun loadProperties(path: String): Properties = File(path).loadProperties()
fun File.saveProperties(properties: Properties) { fun File.saveProperties(properties: Properties) {
this.outputStream().use { this.outputStream().use {
properties.store(it, null) properties.store(it, null)
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.backend.konan.util package org.jetbrains.kotlin.konan.properties
import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.target.*
@@ -29,3 +29,9 @@ fun Properties.targetString(name: String, target: KonanTarget): String?
fun Properties.targetList(name: String, target: KonanTarget): List<String> fun Properties.targetList(name: String, target: KonanTarget): List<String>
= this.propertyList(name, target.targetSuffix) = this.propertyList(name, target.targetSuffix)
fun Properties.hostTargetString(name: String, target: KonanTarget): String?
= this.propertyString(name, hostTargetSuffix(TargetManager.host, target))
fun Properties.hostTargetList(name: String, target: KonanTarget): List<String>
= this.propertyList(name, hostTargetSuffix(TargetManager.host, target))
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.backend.konan.util package org.jetbrains.kotlin.konan.file
import java.io.BufferedReader import java.io.BufferedReader
import java.io.InputStream import java.io.InputStream
@@ -128,6 +128,9 @@ class File constructor(internal val javaPath: Path) {
val userHome val userHome
get() = File(System.getProperty("user.home")) get() = File(System.getProperty("user.home"))
val jdkHome
get() = File(System.getProperty("java.home"))
} }
} }
@@ -1,6 +1,6 @@
package org.jetbrains.kotlin.cli.utilities package org.jetbrains.kotlin.cli.utilities
import org.jetbrains.kotlin.backend.konan.util.File import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.cli.bc.main as konancMain import org.jetbrains.kotlin.cli.bc.main as konancMain
import org.jetbrains.kotlin.native.interop.gen.jvm.main as cinteropMain import org.jetbrains.kotlin.native.interop.gen.jvm.main as cinteropMain
import org.jetbrains.kotlin.cli.klib.main as klibMain import org.jetbrains.kotlin.cli.klib.main as klibMain