Introduced -target and -list_targets flags.

Use it like

    $ konanc hello.kt -target iphone
This commit is contained in:
Alexander Gorshenev
2017-01-13 16:38:40 +03:00
committed by alexander-gorshenev
parent d31b44135a
commit afaa50ce34
21 changed files with 458 additions and 250 deletions
+38 -27
View File
@@ -182,47 +182,58 @@ dependencies {
build.dependsOn 'compilerClasses','cli_bcClasses','bc_frontendClasses'
// These are just a couple of aliases
task stdlib(dependsOn: 'hostStdlib')
task start(dependsOn: 'hostStart')
// These files are built before the 'dist' is complete,
// so we provide custom values for
// -runtime, -properties, -library and -Djava.library.path
task stdlib(type: JavaExec) {
main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt'
classpath = project.configurations.cli_bc
jvmArgs "-ea",
"-Dkonan.home=${project.parent.file('dist')}",
"-Djava.library.path=${project.buildDir}/nativelibs"
args('-output', project(':runtime').file('build/stdlib.kt.bc'),
'-nolink', '-nostdlib',
'-runtime', project(':runtime').file('build/runtime.bc'),
'-properties', project(':backend.native').file('konan.properties'),
targetList.each { platformName ->
task("${platformName}Stdlib", type: JavaExec) {
main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt'
classpath = project.configurations.cli_bc
jvmArgs "-ea",
"-Dkonan.home=${project.parent.file('dist')}",
"-Djava.library.path=${project.buildDir}/nativelibs"
args('-output', project(':runtime').file("build/${platformName}/stdlib.kt.bc"),
'-nolink', '-nostdlib',
'-target', platformName,
'-runtime', project(':runtime').file("build/${platformName}/runtime.bc"),
'-properties', project(':backend.native').file('konan.properties'),
project(':runtime').file('src/main/kotlin'),
*project.globalArgs)
inputs.dir(project(':runtime').file('src/main/kotlin'))
outputs.file(project(':runtime').file('build/stdlib.kt.bc'))
inputs.dir(project(':runtime').file('src/main/kotlin'))
outputs.file(project(':runtime').file("build/${platformName}/stdlib.kt.bc"))
dependsOn ':runtime:build'
dependsOn ":runtime:build"
}
}
task start(type: JavaExec) {
main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt'
classpath = project.configurations.cli_bc
jvmArgs "-ea",
"-Dkonan.home=${project.parent.file('dist')}",
"-Djava.library.path=${project.buildDir}/nativelibs"
args('-output', project(':runtime').file('build/start.kt.bc'),
'-nolink', '-nostdlib',
'-library', project(':runtime').file('build/stdlib.kt.bc'),
'-runtime', project(':runtime').file('build/runtime.bc'),
'-properties', project(':backend.native').file('konan.properties'),
targetList.each { platformName ->
task("${platformName}Start", type: JavaExec) {
main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt'
classpath = project.configurations.cli_bc
jvmArgs "-ea",
"-Dkonan.home=${project.parent.file('dist')}",
"-Djava.library.path=${project.buildDir}/nativelibs"
args('-output', project(':runtime').file("build/${platformName}/start.kt.bc"),
'-nolink', '-nostdlib',
'-target', platformName,
'-library', project(':runtime').file("build/${platformName}/stdlib.kt.bc"),
'-runtime', project(':runtime').file("build/${platformName}/runtime.bc"),
'-properties', project(':backend.native').file('konan.properties'),
project(':runtime').file('src/launcher/kotlin'),
*project.globalArgs)
inputs.dir(project(':runtime').file('src/launcher/kotlin'))
outputs.file(project(':runtime').file('build/start.kt.bc'))
inputs.dir(project(':runtime').file('src/launcher/kotlin'))
outputs.file(project(':runtime').file("build/${platformName}/start.kt.bc"))
dependsOn ':runtime:build', 'stdlib'
dependsOn ":runtime:build", "${platformName}Stdlib"
}
}
task run {
@@ -77,11 +77,13 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
put(EXECUTABLE_FILE,
arguments.outputFile ?: "program.kexe")
put(RUNTIME_FILE,
arguments.runtimeFile ?: Distribution.runtime)
put(PROPERTY_FILE,
arguments.propertyFile ?: Distribution.propertyFile)
if (arguments.runtimeFile != null)
put(RUNTIME_FILE, arguments.runtimeFile)
if (arguments.propertyFile != null)
put(PROPERTY_FILE, arguments.propertyFile)
if (arguments.target != null)
put(TARGET, arguments.target)
put(LIST_TARGETS, arguments.listTargets)
put(OPTIMIZATION, arguments.optimization)
put(PRINT_IR, arguments.printIr)
@@ -30,6 +30,13 @@ public class K2NativeCompilerArguments extends CommonCompilerArguments {
@Argument(value = "opt", description = "Enable optimizations during compilation")
public boolean optimization;
@Argument(value = "target", description = "Set hardware target")
@ValueDescription("<target>")
public String target;
@Argument(value = "list_targets", description = "List available hardware targets")
public boolean listTargets;
@Argument(value = "print_ir", description = "Print IR")
public boolean printIr;
@@ -1,36 +1,42 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.config.CompilerConfiguration
import java.io.File
import java.util.Properties
public class Distribution(val properties: KonanProperties,
val os: String, val target: String) {
public class Distribution(val config: CompilerConfiguration) {
companion object {
val targetManager = TargetManager(config)
val target =
if (!targetManager.crossCompile) "host"
else targetManager.current.name.toLowerCase()
val suffix = targetManager.currentSuffix()
private fun findKonanHome(): String {
val value = System.getProperty("konan.home", "dist")
val path = File(value).absolutePath
return path
}
val konanHome = findKonanHome()
val propertyFile = "$konanHome/konan/konan.properties"
val lib = "$konanHome/lib"
// TODO: Pack all needed things to dist.
val dependencies = "$konanHome/../dependencies/all"
val start = "$lib/start.kt.bc"
val stdlib = "$lib/stdlib.kt.bc"
val runtime = "$lib/runtime.bc"
val launcher = "$lib/launcher.bc"
private fun findKonanHome(): String {
val value = System.getProperty("konan.home", "dist")
val path = File(value).absolutePath
return path
}
val llvmHome = "$dependencies/${properties.propertyString("llvmHome.$os")}"
val sysRoot = "$dependencies/${properties.propertyString("sysRoot.$os")}"
val libGcc = "$dependencies/${properties.propertyString("libGcc.$os")}"
val konanHome = findKonanHome()
val propertyFile = config.get(KonanConfigKeys.PROPERTY_FILE)
?: "$konanHome/konan/konan.properties"
val properties = KonanProperties(propertyFile)
val lib = "$konanHome/lib/$target"
// TODO: Pack all needed things to dist.
val dependencies = "$konanHome/../dependencies/all"
val stdlib = "$lib/stdlib.kt.bc"
val start = "$lib/start.kt.bc"
val launcher = "$lib/launcher.bc"
val runtime = config.get(KonanConfigKeys.RUNTIME_FILE)
?: "$lib/runtime.bc"
val llvmHome = "$dependencies/${properties.propertyString("llvmHome.$suffix")}"
val sysRoot = "$dependencies/${properties.propertyString("sysRoot.$suffix")}"
val libGcc = "$dependencies/${properties.propertyString("libGcc.$suffix")}"
val llvmBin = "$llvmHome/bin"
val llvmLib = "$llvmHome/lib"
@@ -40,9 +46,9 @@ public class Distribution(val properties: KonanProperties,
val llvmLto = "$llvmBin/llvm-lto"
val llvmLink = "$llvmBin/llvm-link"
val libCppAbi = "$llvmLib/libc++abi.a"
val libLTO = when (os) {
"osx" -> "$llvmLib/libLTO.dylib"
"linux" -> "$llvmLib/libLTO.so"
else -> error("Don't know libLTO location for the platform.")
val libLTO = when (TargetManager.host) {
KonanTarget.MACBOOK -> "$llvmLib/libLTO.dylib"
KonanTarget.LINUX -> "$llvmLib/libLTO.so"
else -> error("Don't know libLTO location for this platform.")
}
}
@@ -16,13 +16,15 @@ import java.io.File
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
internal val distribution = Distribution(configuration)
internal val libraries: List<String>
get() {
val fromCommandLine = configuration.getList(KonanConfigKeys.LIBRARY_FILES)
if (configuration.get(KonanConfigKeys.NOSTDLIB) ?: false) {
return fromCommandLine
}
return fromCommandLine + Distribution.stdlib
return fromCommandLine + distribution.stdlib
}
private val loadedDescriptors = loadLibMetadata(libraries)
@@ -1,60 +1,64 @@
package org.jetbrains.kotlin.backend.konan;
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.config.CompilerConfigurationKey;
import org.jetbrains.kotlin.serialization.js.ModuleKind;
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.serialization.js.ModuleKind
class KonanConfigKeys {
companion object {
val LIBRARY_FILES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("library file paths");
= CompilerConfigurationKey.create("library file paths")
val BITCODE_FILE: CompilerConfigurationKey<String>
= CompilerConfigurationKey.create("emitted bitcode file path");
= CompilerConfigurationKey.create("emitted bitcode file path")
val EXECUTABLE_FILE: CompilerConfigurationKey<String>
= CompilerConfigurationKey.create("final executable file path");
= CompilerConfigurationKey.create("final executable file path")
val RUNTIME_FILE: CompilerConfigurationKey<String?>
= CompilerConfigurationKey.create("override default runtime file path");
= CompilerConfigurationKey.create("override default runtime file path")
val PROPERTY_FILE: CompilerConfigurationKey<String?>
= CompilerConfigurationKey.create("override default property file path");
= CompilerConfigurationKey.create("override default property file path")
val ABI_VERSION: CompilerConfigurationKey<Int>
= CompilerConfigurationKey.create("current abi version");
= CompilerConfigurationKey.create("current abi version")
val OPTIMIZATION: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("optimized compilation");
= CompilerConfigurationKey.create("optimized compilation")
val NOSTDLIB: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("don't link with stdlib");
= CompilerConfigurationKey.create("don't link with stdlib")
val NOLINK: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("don't link, only produce a bitcode file ");
= CompilerConfigurationKey.create("don't link, only produce a bitcode file ")
val TARGET: CompilerConfigurationKey<String?>
= CompilerConfigurationKey.create("target we compile for")
val LIST_TARGETS: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("list available targets")
val SOURCE_MAP: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("generate source map");
= CompilerConfigurationKey.create("generate source map")
val META_INFO: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("generate metadata");
= CompilerConfigurationKey.create("generate metadata")
val MODULE_KIND: CompilerConfigurationKey<ModuleKind>
= CompilerConfigurationKey.create("module kind");
= CompilerConfigurationKey.create("module kind")
val VERIFY_IR: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("verify ir");
= CompilerConfigurationKey.create("verify ir")
val VERIFY_DESCRIPTORS: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("verify descriptors");
= CompilerConfigurationKey.create("verify descriptors")
val VERIFY_BITCODE: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("verify bitcode");
= CompilerConfigurationKey.create("verify bitcode")
val PRINT_IR: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("print ir");
= CompilerConfigurationKey.create("print ir")
val PRINT_DESCRIPTORS: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("print descriptors");
= CompilerConfigurationKey.create("print descriptors")
val PRINT_BITCODE: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("print bitcode");
= CompilerConfigurationKey.create("print bitcode")
val ENABLED_PHASES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("enable backend phases");
= CompilerConfigurationKey.create("enable backend phases")
val DISABLED_PHASES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("disable backend phases");
= CompilerConfigurationKey.create("disable backend phases")
val VERBOSE_PHASES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("verbose backend phases");
= CompilerConfigurationKey.create("verbose backend phases")
val LIST_PHASES: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("list backend phases");
= CompilerConfigurationKey.create("list backend phases")
val TIME_PHASES: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("time backend phases");
= CompilerConfigurationKey.create("time backend phases")
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.kotlinSourceRoots
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
@@ -35,11 +36,18 @@ public fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEn
val config = konanConfig.configuration
val targets = TargetManager(config)
if (config.get(KonanConfigKeys.LIST_TARGETS) ?: false) {
targets.list()
}
KonanPhases.config(konanConfig)
if (config.get(KonanConfigKeys.LIST_PHASES) ?: false) {
KonanPhases.list()
}
if (config.kotlinSourceRoots.isEmpty()) return
val collector = config.getNotNull(
CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
@@ -1,15 +1,14 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.config.CompilerConfiguration
import java.io.File
import java.util.Properties
public class KonanProperties(config: CompilerConfiguration) {
public class KonanProperties(val propertyFile: String) {
val properties = Properties()
init {
val file = File(config.get(KonanConfigKeys.PROPERTY_FILE))
val file = File(propertyFile)
file.bufferedReader()?.use { reader ->
properties.load(reader)
}
@@ -0,0 +1,104 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
enum class KonanTarget(var enabled: Boolean = false) {
IPHONE(),
IPHONE_SIM(),
LINUX(),
MACBOOK()
}
class TargetManager(val config: CompilerConfiguration) {
val targets = KonanTarget.values().associate{ it.name.toLowerCase() to it }
val current = determineCurrent()
init {
when (host) {
KonanTarget.MACBOOK -> KonanTarget.MACBOOK.enabled = true
KonanTarget.LINUX -> KonanTarget.LINUX.enabled = true
}
KonanTarget.IPHONE.enabled = true
KonanTarget.IPHONE_SIM.enabled = true
if (!current.enabled) {
error("Target $current is not available on the current host")
}
}
fun known(name: String): String {
if (targets[name] == null) {
error("Unknown target: $name. Use -list_targets to see the list of available targets")
}
return name!!
}
fun list() {
targets.forEach { key, target ->
if (target.enabled) {
val isDefault = if (target == current) "(default)" else ""
println(String.format("%1$-30s%2$-10s", "$key:", "$isDefault"))
}
}
}
fun determineCurrent(): KonanTarget {
val userRequest = config.get(KonanConfigKeys.TARGET)
return if (userRequest == null || userRequest == "host") {
host
} else {
targets[known(userRequest)]!!
}
}
fun currentSuffix(): String {
if (host == KonanTarget.MACBOOK) {
when (current) {
KonanTarget.MACBOOK -> return("osx")
KonanTarget.IPHONE -> return("osx-ios")
KonanTarget.IPHONE_SIM -> return("osx-ios-sim")
else -> error("Impossible combination of $host and $current")
}
}
if (host == KonanTarget.LINUX) {
when (current) {
KonanTarget.LINUX -> return("linux")
KonanTarget.IPHONE -> return("linux-ios")
KonanTarget.IPHONE_SIM -> return("linux-ios-sim")
else -> error("Impossible combination of $host and $current")
}
}
error("Unknown host target $host)")
}
companion object {
fun host_os(): String {
val javaOsName = System.getProperty("os.name")
return when (javaOsName) {
"Mac OS X" -> "osx"
"Linux" -> "linux"
else -> error("Unknown operating system: ${javaOsName}")
}
}
fun host_arch(): String {
val javaArch = System.getProperty("os.arch")
return when (javaArch) {
"x86_64" -> "x86_64"
"amd64" -> "x86_64"
"arm64" -> "arm64"
else -> error("Unknown hardware platform: ${javaArch}")
}
}
val host: KonanTarget = when (host_os()) {
"osx" -> KonanTarget.MACBOOK
"linux" -> KonanTarget.LINUX
else -> error("Unknown host target: ${host_os()} ${host_arch()}")
}
}
val crossCompile = (host != current)
}
@@ -10,8 +10,8 @@ typealias ExecutableFile = String
// Use "clang -v -save-temps" to write linkCommand() method
// for another implementation of this class.
internal abstract class PlatformFlags(val distrib: Distribution,
val properties: KonanProperties) {
internal abstract class PlatformFlags(val distribution: Distribution) {
val properties = distribution.properties
abstract val llvmLtoFlags: List<String>
abstract val llvmLlcFlags: List<String>
@@ -25,8 +25,8 @@ internal abstract class PlatformFlags(val distrib: Distribution,
}
internal class MacOSPlatform(distrib: Distribution,
properties: KonanProperties) : PlatformFlags(distrib, properties) {
internal open class MacOSPlatform(distribution: Distribution)
: PlatformFlags(distribution) {
override val llvmLtoFlags = properties.propertyList("llvmLtoFlags.osx")
override val llvmLlcFlags = properties.propertyList("llvmLlcFlags.osx")
@@ -34,28 +34,41 @@ internal class MacOSPlatform(distrib: Distribution,
override val linkerOptimizationFlags =
properties.propertyList("linkerOptimizationFlags.osx")
override val linkerKonanFlags = properties.propertyList("linkerKonanFlags.osx")
override val linker = "${distrib.sysRoot}/usr/bin/ld"
override val linker = "${distribution.sysRoot}/usr/bin/ld"
open val arch = properties.propertyString("arch.osx")!!
open val osVersionMin = properties.propertyList("osVersionMin.osx")
open val sysRoot = distribution.sysRoot
open val targetSysRoot = sysRoot
open val llvmLib = distribution.llvmLib
override fun linkCommand(objectFiles: List<String>, executable: String, optimize: Boolean): List<String> {
val sysRoot = distrib.sysRoot
val llvmLib = distrib.llvmLib
return mutableListOf<String>(linker, "-demangle") +
if (optimize) listOf("-object_path_lto", "temporary.o", "-lto_library", distrib.libLTO) else {listOf<String>()} +
listOf( "-dynamic", "-arch", "x86_64", "-macosx_version_min") +
properties.propertyList("macosVersionMin.osx") +
listOf("-syslibroot", "$sysRoot",
if (optimize) listOf("-object_path_lto", "temporary.o", "-lto_library", distribution.libLTO) else {listOf<String>()} +
listOf( "-dynamic", "-arch", arch) +
osVersionMin +
listOf("-syslibroot", "$targetSysRoot",
"-o", executable) +
objectFiles +
if (optimize) linkerOptimizationFlags else {listOf<String>()} +
linkerKonanFlags +
listOf("-lSystem", "$llvmLib/clang/3.8.0/lib/darwin/libclang_rt.osx.a")
listOf("-lSystem")
}
}
internal class LinuxPlatform(distrib: Distribution,
properties: KonanProperties) : PlatformFlags(distrib, properties) {
internal class IPhoneOSfromMacOSPlatform(distribution: Distribution)
: MacOSPlatform(distribution) {
override val arch = properties.propertyString("arch.osx-ios")!!
override val osVersionMin = properties.propertyList("osVersionMin.osx-ios")
override val llvmLlcFlags = properties.propertyList("llvmLlcFlags.osx-ios")
override val targetSysRoot = "${distribution.dependencies}/${properties.propertyString("targetSysRoot.osx-ios")!!}"
}
internal class LinuxPlatform(distribution: Distribution)
: PlatformFlags(distribution) {
override val llvmLtoFlags = properties.propertyList("llvmLtoFlags.linux")
override val llvmLlcFlags = properties.propertyList("llvmLlcFlags.linux")
@@ -63,16 +76,16 @@ internal class LinuxPlatform(distrib: Distribution,
override val linkerOptimizationFlags =
properties.propertyList("linkerOptimizationFlags.linux")
override val linkerKonanFlags = properties.propertyList("linkerKonanFlags.linux")
override val linker = "${distrib.sysRoot}/../bin/ld.gold"
override val linker = "${distribution.sysRoot}/../bin/ld.gold"
val pluginOptimizationFlags =
properties.propertyList("pluginOptimizationFlags.linux")
override fun linkCommand(objectFiles: List<String>, executable: String, optimize: Boolean): List<String> {
val sysRoot = distrib.sysRoot
val llvmLib = distrib.llvmLib
val libGcc = distrib.libGcc
val sysRoot = distribution.sysRoot
val llvmLib = distribution.llvmLib
val libGcc = distribution.libGcc
// TODO: Can we extract more to the konan.properties?
return mutableListOf<String>("$linker",
@@ -97,31 +110,27 @@ internal class LinuxPlatform(distrib: Distribution,
internal class LinkStage(val context: Context) {
private val javaOsName = System.getProperty("os.name")
private val javaArch = System.getProperty("os.arch")
val os = when (javaOsName) {
"Mac OS X" -> "osx"
"Linux" -> "linux"
else -> error("Unknown operating system: ${javaOsName}")
}
val arch = when (javaArch) {
"x86_64" -> "x86_64"
"amd64" -> "x86_64"
else -> error("Unknown hardware platform: ${javaArch}")
}
private val properties = KonanProperties(context.config.configuration)
private val distrib = Distribution(properties, os, arch)
val platform: PlatformFlags = when (os) {
"linux" -> LinuxPlatform(distrib, properties)
"osx" -> MacOSPlatform(distrib, properties)
else -> error("Could not tell the current platform")
}
val config = context.config.configuration
val targetManager = TargetManager(config)
private val distribution =
Distribution(context.config.configuration)
private val properties = distribution.properties
val platform: PlatformFlags = when (TargetManager.host) {
KonanTarget.LINUX -> LinuxPlatform(distribution)
KonanTarget.MACBOOK -> when (targetManager.current) {
KonanTarget.IPHONE
-> IPhoneOSfromMacOSPlatform(distribution)
KonanTarget.MACBOOK
-> MacOSPlatform(distribution)
else -> TODO("Target not implemented yet.")
}
else -> TODO("Target not implemented yet")
}
val suffix = targetManager.currentSuffix()
val optimize = config.get(KonanConfigKeys.OPTIMIZATION) ?: false
val emitted = config.get(KonanConfigKeys.BITCODE_FILE)!!
val nostdlib = config.get(KonanConfigKeys.NOSTDLIB) ?: false
@@ -131,7 +140,7 @@ internal class LinkStage(val context: Context) {
// TODO: Make it a temporary file.
val combined = "combined.o"
val tool = distrib.llvmLto
val tool = distribution.llvmLto
val command = mutableListOf(tool, "-o", combined)
if (optimize) {
command.addAll(platform.llvmLtoFlags)
@@ -146,9 +155,9 @@ internal class LinkStage(val context: Context) {
// TODO: Make it a temporary file.
val objectFile = "$file.o"
val tool = distrib.llvmLlc
val command = listOf(distrib.llvmLlc, "-o", objectFile, "-filetype=obj") +
properties.propertyList("llvmLlcFlags.$os") + listOf(file)
val tool = distribution.llvmLlc
val command = listOf(distribution.llvmLlc, "-o", objectFile, "-filetype=obj") +
properties.propertyList("llvmLlcFlags.$suffix") + listOf(file)
runTool(*command.toTypedArray())
return objectFile
@@ -186,10 +195,10 @@ internal class LinkStage(val context: Context) {
}
fun linkStage() {
context.log("# Compiler root: ${Distribution.konanHome}")
context.log("# Compiler root: ${distribution.konanHome}")
val bitcodeFiles = listOf<BitcodeFile>(emitted, Distribution.start, Distribution.runtime,
Distribution.launcher) + libraries
val bitcodeFiles = listOf<BitcodeFile>(emitted, distribution.start, distribution.runtime,
distribution.launcher) + libraries
val objectFiles = if (optimize) {
listOf( llvmLto(bitcodeFiles ) )
@@ -250,7 +250,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
val staticData = StaticData(context)
val runtimeFile = context.config.configuration.get(KonanConfigKeys.RUNTIME_FILE)!!
val runtimeFile = context.config.distribution.runtime
val runtime = Runtime(runtimeFile) // TODO: dispose
init {
@@ -33,6 +33,11 @@ import org.jetbrains.kotlin.utils.addToStdlib.singletonList
internal fun emitLLVM(context: Context) {
val irModule = context.irModule!!
// Note that we don't set module target explicitly.
// It is determined by the target of runtime.bc
// (see Llvm class in ContextUtils)
// Which in turn is determined by the clang flags
// used to compile runtime.bc.
val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose
context.llvmModule = llvmModule
+15 -6
View File
@@ -1,19 +1,28 @@
// TODO: utilize substitution mechanism from interop.
arch.osx = x86_64
sysRoot.osx = target-sysroot-1-darwin-macos
llvmHome.osx = clang+llvm-3.8.0-darwin-macos
sysRoot.linux = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu/sysroot
llvmHome.linux = clang+llvm-3.8.0-linux-x86-64
libGcc.linux = target-gcc-toolchain-3-linux-x86-64/lib/gcc/x86_64-unknown-linux-gnu/4.8.5
llvmLtoFlags.osx = -O3 -function-sections -exported-symbol=_main
llvmLlcFlags.osx = -mtriple=x86_64-apple-macosx10.10.0
linkerKonanFlags.osx = -lc++
linkerOptimizationFlags.osx = -dead_strip
macosVersionMin.osx = 10.10.0
osVersionMin.osx = -macosx_version_min 10.10.0
arch.osx-ios = arm64
sysRoot.osx-ios = target-sysroot-1-darwin-macos
targetSysRoot.osx-ios = target-sysroot-1-darwin-ios
llvmHome.osx-ios = clang+llvm-3.8.0-darwin-macos
llvmLtoFlags.osx-ios = -O3 -function-sections -exported-symbol=_main
llvmLlcFlags.osx-ios = -mtriple=arm64-apple-ios5.0.0
linkerKonanFlags.osx-ios = -lc++
linkerOptimizationFlags.osx-ios = -dead_strip
osVersionMin.osx-ios = -iphoneos_version_min 5.0.0
sysRoot.linux = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu/sysroot
llvmHome.linux = clang+llvm-3.8.0-linux-x86-64
libGcc.linux = target-gcc-toolchain-3-linux-x86-64/lib/gcc/x86_64-unknown-linux-gnu/4.8.5
llvmLtoFlags.linux = -O3 -function-sections -exported-symbol=main
llvmLlcFlags.linux = -march=x86-64
linkerKonanFlags.linux = -Bstatic -lstdc++ -Bdynamic -ldl -lm -lpthread
+44 -67
View File
@@ -22,28 +22,43 @@ allprojects {
}
}
convention.plugins.clangFlags = new ClangFlags(new PlatformInfo(), "$llvmDir")
ext.clangPath = ["$llvmDir/bin"]
ext.clangArgs = []
ext.targetArgs = [:]
final String binDir
if (isLinux()) {
ext.targetArgs <<
["host": ["--sysroot=${gccToolchainDir}/${gnuTriplet}/sysroot"]]
} else {
ext.targetArgs <<
["host":
["--sysroot=$hostSysrootDir"],
"iphone":
["-stdlib=libc++", "-arch", "arm64", "-isysroot", "$iphoneSysrootDir"],
"iphone_sim":
["-stdlib=libc++"]
]
}
ext.targetList = ext.targetArgs.keySet() as List
if (isLinux()) {
binDir = "$gccToolchainDir/$gnuTriplet/bin"
ext.clangArgs.addAll([
"--sysroot=$gccToolchainDir/$gnuTriplet/sysroot",
"--gcc-toolchain=$gccToolchainDir",
"-L$llvmDir/lib"
])
} else {
binDir = "$sysrootDir/usr/bin"
ext.clangArgs << "--sysroot=$sysrootDir"
binDir = "$hostSysrootDir/usr/bin"
}
ext.clangArgs << "-B$binDir"
ext.hostClangArgs = ext.clangArgs.clone()
ext.hostClangArgs.addAll(ext.targetArgs['host'])
ext.clangPath << binDir
ext.jvmArgs = ["-ea"]
ext.clangLinkArgs = libLink()
ext.clangOptArgs = optArgs()
ext.globalArgs = project.hasProperty("konanc_flags") ? ext.konanc_flags.split(' ') : []
convention.plugins.execClang = new org.jetbrains.kotlin.ExecClang(project)
plugins.withType(NativeComponentPlugin) {
@@ -56,7 +71,7 @@ allprojects {
eachPlatform { // TODO: will not work when cross-compiling
[cCompiler, cppCompiler, linker].each {
it.withArguments { it.addAll(clangArgs) }
it.withArguments { it.addAll(hostClangArgs) }
}
}
@@ -66,56 +81,6 @@ allprojects {
}
}
class ClangFlags {
protected PlatformInfo platform
protected String llvmDir
private List<String> linkCppAbi, linkPlatform, optArgs
ClangFlags(platformInfo, llvm) {
platform = platformInfo
llvmDir = llvm
if (platform.isLinux()) {
linkCppAbi= ["-Wl,-Bstatic", "-lc++abi", "-Wl,-Bdynamic"]
linkPlatform= ["-ldl", "-lpthread", "-lm", "-rdynamic"]
optArgs = ["-O3", "-fuse-ld=gold", "-flto", "-ffunction-sections", "-Wl,--gc-sections"]
} else if (platform.isMac()) {
// Life is hard. MacOS linker is harder.
// This is how we force the linker to link statically.
linkCppAbi= ["${llvmDir}/lib/libc++abi.a"]
linkPlatform= []
optArgs = ["-O3", "-flto", "-Wl,-dead_strip"]
} else {
throw unsupportedPlatformException()
}
}
public List<String> linkCppAbi() {
return linkCppAbi
}
public List<String> linkPlatform() {
return linkPlatform
}
public List<String> optArgs() {
return optArgs
}
public List<String> libLink() {
def libs = []
libs.addAll(linkPlatform())
libs.addAll(linkCppAbi())
return libs
}
}
class PlatformInfo {
private final String osName = System.properties['os.name']
private final String osArch = System.properties['os.arch']
@@ -170,13 +135,6 @@ task dist_compiler(type: Copy) {
fileMode(0755)
include('konanc')
include('kotlinc-native')
def allClangArgs = "${clangArgs.join(' ')} ${clangLinkArgs.join(' ')}"
filter { line -> line.replaceAll("FILTER_CLANG_PLATFORM_ARGS", allClangArgs) }
filter { line -> line.replaceAll("FILTER_CLANG_PLATFORM_OPT", "${clangOptArgs.join(' ')}") }
filter { line -> line.replaceAll("FILTER_CLANG_BIN_PATH", "${project.llvmDir}/bin") }
into('bin')
}
@@ -190,12 +148,27 @@ task list_dist(type: Exec) {
}
task dist_runtime(type: Copy) {
dependsOn ':runtime:build', ':backend.native:stdlib', ':backend.native:start'
dependsOn ':runtime:build'
dependsOn ':backend.native:hostStdlib'
dependsOn ':backend.native:hostStart'
destinationDir file('dist')
from(project(':runtime').file('build')) {
include('*.bc')
include('*/*.bc')
into('lib')
}
}
task cross_dist_runtime(type: Copy) {
dependsOn ':runtime:build'
dependsOn.addAll(targetList.collect { ":backend.native:${it}Stdlib" })
dependsOn.addAll(targetList.collect { ":backend.native:${it}Start" })
destinationDir file('dist')
from(project(':runtime').file('build')) {
include('*/*.bc')
into('lib')
}
}
@@ -204,6 +177,10 @@ task dist {
dependsOn 'dist_compiler', 'dist_runtime'
}
task cross_dist {
dependsOn 'cross_dist_runtime', 'dist_compiler'
}
task demo(type: Exec) {
dependsOn 'dist'
@@ -1,16 +1,65 @@
package org.jetbrains.kotlin
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.*
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
class CompilePerTarget extends CompileCppToBitcode {
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 {
private String name = "main"
private String target = "host"
private File srcRoot;
private List<String> compilerArgs = []
private List<String> linkerArgs = []
protected List<String> compilerArgs = []
protected List<String> linkerArgs = []
@InputDirectory
File getSrcRoot() {
@@ -19,7 +68,7 @@ class CompileCppToBitcode extends DefaultTask {
@OutputFile
File getOutFile() {
return new File(project.buildDir, "${name}.bc")
return new File(getTargetDir(), "${name}.bc")
}
private File getSrcDir() {
@@ -30,23 +79,31 @@ class CompileCppToBitcode extends DefaultTask {
return new File(this.getSrcRoot(), "headers")
}
private File getTargetDir() {
return new File(project.buildDir, target)
}
private File getObjDir() {
return new File(project.buildDir, name)
return new File(getTargetDir(), name)
}
void name(String value) {
name = value
}
void target(String value) {
target = value
}
void srcRoot(File value) {
srcRoot = value
}
private List<String> getCompilerArgs() {
protected List<String> getCompilerArgs() {
return compilerArgs
}
private List<String> getLinkerArgs() {
protected List<String> getLinkerArgs() {
return linkerArgs
}
@@ -54,10 +111,18 @@ class CompileCppToBitcode extends DefaultTask {
compilerArgs.addAll(args)
}
void compilerArgs(List<String> args) {
compilerArgs.addAll(args)
}
void linkerArgs(String... args) {
linkerArgs.addAll(args)
}
void linkerArgs(List<String> args) {
linkerArgs.addAll(args)
}
@TaskAction
void compile() {
// the strange code below seems to be required due to some Gradle (Groovy?) behaviour
@@ -34,7 +34,7 @@ class ExecClang {
if (executable in ['clang', 'clang++']) {
executable = "${project.llvmDir}/bin/$executable"
} else {
throw new GradleException("unsupport clang executable: $executable")
throw new GradleException("unsupported clang executable: $executable")
}
environment["PATH"] = project.files(project.clangPath).asPath +
@@ -47,4 +47,4 @@ class ExecClang {
}
return project.exec(extendedAction)
}
}
}
@@ -12,7 +12,6 @@ abstract class KonanTest extends DefaultTask {
def backendNative = project.project(":backend.native")
def runtimeProject = project.project(":runtime")
def dist = project.rootProject.file("dist")
def llvmLlc = llvmTool("llc")
def runtimeBc = new File("${dist.canonicalPath}/lib/runtime.bc").absolutePath
def launcherBc = new File("${dist.canonicalPath}/lib/launcher.bc").absolutePath
def startKtBc = new File("${dist.canonicalPath}/lib/start.kt.bc").absolutePath
@@ -100,14 +99,6 @@ abstract class KonanTest extends DefaultTask {
if (goldValue != null && goldValue != out.toString())
throw new RuntimeException("test failed.")
}
private String llvmTool(String tool) {
return "${project.llvmDir}/bin/${tool}"
}
protected List<String> clangLinkArgs() {
return project.clangLinkArgs
}
}
class RunKonanTest extends KonanTest {
@@ -182,8 +182,8 @@ class NamedNativeInteropConfig implements Named {
environment['PATH'] = project.files(project.clangPath).asPath +
File.pathSeparator + environment['PATH']
compilerOpts += project.clangArgs
linkerOpts += project.clangArgs
compilerOpts += project.hostClangArgs
linkerOpts += project.hostClangArgs
args compilerOpts.collect { "-copt:$it" }
args linkerOpts.collect { "-lopt:$it" }
+4 -3
View File
@@ -1,10 +1,11 @@
import org.jetbrains.kotlin.CompileCppToBitcode
import org.jetbrains.kotlin.CompilePerTarget
// TODO: consider using some Gradle plugins to build and test
task compileHash(type: CompileCppToBitcode) {
task compileHash(type: CompilePerTarget) {
name 'hash'
targetList targetList
targetArgs targetArgs
}
task build {
+11 -8
View File
@@ -10,7 +10,7 @@ abstract class NativeDep extends DefaultTask {
}
}
protected final String target = getCurrentHostTarget();
protected final String host = getCurrentHostTarget();
@Input
abstract String getFileName()
@@ -27,7 +27,7 @@ abstract class NativeDep extends DefaultTask {
protected File download() {
File result = new File(baseOutDir, fileName)
if (!result.exists())
if (!result.exists())
ant.get(src: url, dest: result, usetimestamp: true)
return result
}
@@ -71,20 +71,23 @@ class TgzNativeDep extends NativeDep {
task libffi(type: TgzNativeDep) {
baseName = "libffi-3.2.1-2-$target"
baseName = "libffi-3.2.1-2-$host"
}
task llvm(type: TgzNativeDep) {
baseName = "clang+llvm-3.8.0-$target"
baseName = "clang+llvm-3.8.0-$host"
}
if (isLinux()) {
task gccToolchain(type: TgzNativeDep) {
baseName = "target-gcc-toolchain-3-$target"
baseName = "target-gcc-toolchain-3-$host"
}
} else {
task sysroot(type: TgzNativeDep) {
baseName = "target-sysroot-1-$target"
task hostSysroot(type: TgzNativeDep) {
baseName = "target-sysroot-1-$host"
}
task iphoneSysroot(type: TgzNativeDep) {
baseName = "target-sysroot-1-darwin-ios"
}
}
@@ -95,4 +98,4 @@ task update {
tasks.withType(TgzNativeDep) {
rootProject.ext.set("${name}Dir", outputDir.path)
}
}
+12 -7
View File
@@ -1,21 +1,26 @@
import org.jetbrains.kotlin.CompileCppToBitcode
import org.jetbrains.kotlin.CompilePerTarget
// TODO: consider using some Gradle plugins to build and test
task build(type: CompileCppToBitcode) {
task build(type: CompilePerTarget) {
name 'runtime'
srcRoot file('src/main')
dependsOn ':common:compileHash'
dependsOn 'launcher'
dependsOn ":common:compileHash"
dependsOn "launcher"
targetList targetList
targetArgs targetArgs
compilerArgs '-I' + project.file('../common/src/hash/headers') // TODO: copy-pasted from 'common'
linkerArgs project.file('../common/build/hash.bc').path
targetLinkerArgs targetList.collectEntries {
[it,[project.file("../common/build/$it/hash.bc")]]
}
}
task launcher(type: CompileCppToBitcode) {
task launcher(type: CompilePerTarget) {
name 'launcher'
srcRoot file('src/launcher')
targetList targetList
targetArgs targetArgs
compilerArgs '-I' + project.file('../common/src/hash/headers') // TODO: copy-pasted from 'common'
compilerArgs '-I' + project.file('src/main/cpp')
}