Move some classes used by Gradle plugin from K/N shared

This commit is contained in:
Ilya Matveev
2019-05-27 14:30:25 +03:00
parent b002d572fb
commit 5e66399284
8 changed files with 362 additions and 148 deletions
@@ -1,21 +1,27 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.konan.file
import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.io.RandomAccessFile
import java.lang.Exception
import java.net.URI
import java.nio.MappedByteBuffer
import java.nio.channels.FileChannel
import java.nio.file.*
import java.nio.file.attribute.BasicFileAttributes
data class File constructor(internal val javaPath: Path) {
constructor(parent: Path, child: String) : this(parent.resolve(child))
constructor(parent: File, child: String) : this(parent.javaPath.resolve(child))
constructor(path: String) : this(Paths.get(path))
constructor(parent: String, child: String) : this(Paths.get(parent, child))
constructor(parent: Path, child: String): this(parent.resolve(child))
constructor(parent: File, child: String): this(parent.javaPath.resolve(child))
constructor(path: String): this(Paths.get(path))
constructor(parent: String, child: String): this(Paths.get(parent, child))
val path: String
get() = javaPath.toString()
@@ -24,7 +30,7 @@ data class File constructor(internal val javaPath: Path) {
val absoluteFile: File
get() = File(absolutePath)
val name: String
get() = javaPath.fileName.toString()
get() = javaPath.fileName.toString().removeSuffixIfPresent("/") // https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8153248
val extension: String
get() = name.substringAfterLast('.', "")
val parent: String
@@ -59,13 +65,13 @@ data class File constructor(internal val javaPath: Path) {
fun mkdirs() = Files.createDirectories(javaPath)
fun delete() = Files.deleteIfExists(javaPath)
fun deleteRecursively() = postorder { Files.delete(it) }
fun deleteOnExitRecursively() = preorder { File(it).deleteOnExit() }
fun deleteRecursively() = postorder{Files.delete(it)}
fun deleteOnExitRecursively() = preorder{File(it).deleteOnExit()}
fun preorder(task: (Path) -> Unit) {
if (!this.exists) return
Files.walkFileTree(javaPath, object : SimpleFileVisitor<Path>() {
Files.walkFileTree(javaPath, object: SimpleFileVisitor<Path>() {
override fun visitFile(file: Path?, attrs: BasicFileAttributes?): FileVisitResult {
task(file!!)
return FileVisitResult.CONTINUE
@@ -82,7 +88,7 @@ data class File constructor(internal val javaPath: Path) {
fun postorder(task: (Path) -> Unit) {
if (!this.exists) return
Files.walkFileTree(javaPath, object : SimpleFileVisitor<Path>() {
Files.walkFileTree(javaPath, object: SimpleFileVisitor<Path>() {
override fun visitFile(file: Path?, attrs: BasicFileAttributes?): FileVisitResult {
task(file!!)
return FileVisitResult.CONTINUE
@@ -93,19 +99,27 @@ data class File constructor(internal val javaPath: Path) {
return FileVisitResult.CONTINUE
}
})
}
fun map(mode: FileChannel.MapMode = FileChannel.MapMode.READ_ONLY,
start: Long = 0, size: Long = -1): MappedByteBuffer {
val file = RandomAccessFile(path,
if (mode == FileChannel.MapMode.READ_ONLY) "r" else "rw")
val fileSize = if (mode == FileChannel.MapMode.READ_ONLY)
file.length() else size.also { assert(size != -1L) }
return file.channel.map(mode, start, fileSize) // Shall we .also { file.close() }?
}
fun deleteOnExit(): File {
// Works only on the default file system,
// Works only on the default file system,
// but that's okay for now.
javaPath.toFile().deleteOnExit()
return this // Allow streaming.
}
fun readBytes() = Files.readAllBytes(javaPath)
fun writeBytes(bytes: ByteArray) = Files.write(javaPath, bytes)
fun appendBytes(bytes: ByteArray) = Files.write(javaPath, bytes, StandardOpenOption.APPEND)
fun appendBytes(bytes: ByteArray)
= Files.write(javaPath, bytes, StandardOpenOption.APPEND)
fun writeLines(lines: Iterable<String>) {
Files.write(javaPath, lines)
@@ -131,7 +145,6 @@ data class File constructor(internal val javaPath: Path) {
// TODO: Consider removeing these after konanazing java.util.Properties.
fun bufferedReader() = Files.newBufferedReader(javaPath)
fun outputStream() = Files.newOutputStream(javaPath)
fun printWriter() = javaPath.toFile().printWriter()
@@ -145,9 +158,10 @@ data class File constructor(internal val javaPath: Path) {
val javaHome
get() = File(System.getProperty("java.home"))
val pathSeparator = java.io.File.pathSeparator
val separator = java.io.File.separator
}
fun readStrings() = mutableListOf<String>().also { list -> forEachLine { list.add(it) } }
fun readStrings() = mutableListOf<String>().also { list -> forEachLine{list.add(it)}}
override fun equals(other: Any?): Boolean {
val otherFile = other as? File ?: return false
@@ -160,16 +174,18 @@ data class File constructor(internal val javaPath: Path) {
fun String.File(): File = File(this)
fun Path.File(): File = File(this)
fun createTempFile(name: String, suffix: String? = null) = Files.createTempFile(name, suffix).File()
fun createTempDir(name: String): File = Files.createTempDirectory(name).File()
fun createTempFile(name: String, suffix: String? = null)
= Files.createTempFile(name, suffix).File()
fun createTempDir(name: String): File
= Files.createTempDirectory(name).File()
fun Path.recursiveCopyTo(destPath: Path) {
val sourcePath = this
Files.walk(sourcePath).forEach next@{ oldPath ->
Files.walk(sourcePath).forEach next@ { oldPath ->
val relative = sourcePath.relativize(oldPath)
val destFs = destPath.getFileSystem()
// We are copying files between file systems,
// We are copying files between file systems,
// so pass the relative path through the String.
val newPath = destFs.getPath(destPath.toString(), relative.toString())
@@ -1,11 +1,12 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.konan.properties
import org.jetbrains.kotlin.konan.file.*
import org.jetbrains.kotlin.konan.util.parseSpaceSeparatedArgs
typealias Properties = java.util.Properties
@@ -34,14 +35,28 @@ fun Properties.propertyString(key: String, suffix: String? = null): String? = ge
* functionality borrowed from def file parser and unified for interop tool
* and kotlin compiler.
*/
fun Properties.propertyList(key: String, suffix: String? = null): List<String> {
fun Properties.propertyList(key: String, suffix: String? = null, escapeInQuotes: Boolean = false): List<String> {
val value = this.getProperty(key.suffix(suffix)) ?: this.getProperty(key)
if (value?.isBlank() == true) return emptyList()
return value?.split(Regex("\\s+")) ?: emptyList()
return if (escapeInQuotes) value?.let { parseSpaceSeparatedArgs(it) } ?: emptyList()
else value?.split(Regex("\\s+")) ?: emptyList()
}
fun Properties.hasProperty(key: String, suffix: String? = null): Boolean = this.getProperty(key.suffix(suffix)) != null
fun Properties.hasProperty(key: String, suffix: String? = null): Boolean
= this.getProperty(key.suffix(suffix)) != null
fun String.suffix(suf: String?): String = if (suf == null) this else "${this}.$suf"
fun String.suffix(suf: String?): String =
if (suf == null) this
else "${this}.$suf"
fun Properties.keepOnlyDefaultProfiles() {
val DEPENDENCY_PROFILES_KEY = "dependencyProfiles"
val dependencyProfiles = this.getProperty(DEPENDENCY_PROFILES_KEY)
if (dependencyProfiles != "default alt")
error("unexpected $DEPENDENCY_PROFILES_KEY value: expected 'default alt', got '$dependencyProfiles'")
// Force build to use only 'default' profile:
this.setProperty(DEPENDENCY_PROFILES_KEY, "default")
// TODO: it actually affects only resolution made in :dependencies,
// that's why we assume that 'default' profile comes first (and check this above).
}
@@ -0,0 +1,83 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.konan.target
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.properties.keepOnlyDefaultProfiles
import org.jetbrains.kotlin.konan.properties.loadProperties
import org.jetbrains.kotlin.konan.util.DependencyDirectories
class Distribution(
private val onlyDefaultProfiles: Boolean = false,
private val konanHomeOverride: String? = null,
private val runtimeFileOverride: String? = null) {
val localKonanDir = DependencyDirectories.localKonanDir
private fun findKonanHome(): String {
if (konanHomeOverride != null) return konanHomeOverride
val value = System.getProperty("konan.home", "dist")
val path = File(value).absolutePath
return path
}
val konanHome = findKonanHome()
val konanSubdir = "$konanHome/konan"
val mainPropertyFileName = "$konanSubdir/konan.properties"
val experimentalEnabled by lazy {
File("$konanSubdir/experimentalTargetsEnabled").exists
}
private fun propertyFilesFromConfigDir(configDir: String, genericName: String): List<File> {
val directory = File(configDir, "platforms/$genericName")
return if (directory.exists && directory.isDirectory)
directory.listFiles
else
emptyList()
}
private fun preconfiguredPropertyFiles(genericName: String) =
propertyFilesFromConfigDir(konanSubdir, genericName)
private fun userPropertyFiles(genericName: String) =
propertyFilesFromConfigDir(localKonanDir.absolutePath, genericName)
fun additionalPropertyFiles(genericName: String) =
preconfiguredPropertyFiles(genericName) + userPropertyFiles(genericName)
val properties by lazy {
val loaded = File(mainPropertyFileName).loadProperties()
HostManager.knownTargetTemplates.forEach {
additionalPropertyFiles(it).forEach {
val additional = it.loadProperties()
loaded.putAll(additional)
}
}
if (onlyDefaultProfiles) {
loaded.keepOnlyDefaultProfiles()
}
loaded
}
val klib = "$konanHome/klib"
val stdlib = "$klib/common/stdlib"
fun defaultNatives(target: KonanTarget) = "$konanHome/konan/targets/${target.visibleName}/native"
fun runtime(target: KonanTarget) = runtimeFileOverride ?: "$stdlib/targets/${target.visibleName}/native/runtime.bc"
val launcherFiles = listOf("launcher.bc")
val dependenciesDir = DependencyDirectories.defaultDependenciesRoot.absolutePath
fun availableSubTarget(genericName: String) =
additionalPropertyFiles(genericName).map { it.name }
}
fun buildDistribution(konanHomeOverride: String? = null) = Distribution(true, konanHomeOverride, null)
fun customerDistribution(konanHomeOverride: String? = null) = Distribution(false, konanHomeOverride, null)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -7,18 +7,18 @@ package org.jetbrains.kotlin.konan.target
import org.jetbrains.kotlin.konan.target.KonanTarget.*
import org.jetbrains.kotlin.konan.util.Named
import java.io.Serializable
import java.lang.Exception
enum class Family(
val exeSuffix: String, val dynamicPrefix: String, val dynamicSuffix: String,
val staticPrefix: String, val staticSuffix: String
) {
OSX("kexe", "lib", "dylib", "lib", "a"),
IOS("kexe", "lib", "dylib", "lib", "a"),
LINUX("kexe", "lib", "so", "lib", "a"),
MINGW("exe", "", "dll", "lib", "a"),
ANDROID("so", "lib", "so", "lib", "a"),
WASM("wasm", "", "wasm", "", "wasm"),
ZEPHYR("o", "lib", "a", "lib", "a")
enum class Family(val exeSuffix:String, val dynamicPrefix: String, val dynamicSuffix: String,
val staticPrefix: String, val staticSuffix: String) {
OSX ("kexe", "lib", "dylib", "lib", "a"),
IOS ("kexe", "lib", "dylib", "lib", "a"),
LINUX ("kexe", "lib", "so" , "lib", "a"),
MINGW ("exe" , "" , "dll" , "lib", "a"),
ANDROID ("so" , "lib", "so" , "lib", "a"),
WASM ("wasm", "" , "wasm" , "", "wasm"),
ZEPHYR ("o" , "lib", "a" , "lib", "a")
}
enum class Architecture(val bitness: Int) {
@@ -32,44 +32,27 @@ enum class Architecture(val bitness: Int) {
}
sealed class KonanTarget(override val name: String, val family: Family, val architecture: Architecture) : Named {
object ANDROID_ARM32 : KonanTarget("android_arm32", Family.ANDROID, Architecture.ARM32)
object ANDROID_ARM64 : KonanTarget("android_arm64", Family.ANDROID, Architecture.ARM64)
object IOS_ARM32 : KonanTarget("ios_arm32", Family.IOS, Architecture.ARM32)
object IOS_ARM64 : KonanTarget("ios_arm64", Family.IOS, Architecture.ARM64)
object IOS_X64 : KonanTarget("ios_x64", Family.IOS, Architecture.X64)
object LINUX_X64 : KonanTarget("linux_x64", Family.LINUX, Architecture.X64)
object MINGW_X64 : KonanTarget("mingw_x64", Family.MINGW, Architecture.X64)
object MINGW_X86 : KonanTarget("mingw_x86", Family.MINGW, Architecture.X86)
object MACOS_X64 : KonanTarget("macos_x64", Family.OSX, Architecture.X64)
object LINUX_ARM32_HFP : KonanTarget("linux_arm32_hfp", Family.LINUX, Architecture.ARM32)
object LINUX_MIPS32 : KonanTarget("linux_mips32", Family.LINUX, Architecture.MIPS32)
object LINUX_MIPSEL32 : KonanTarget("linux_mipsel32", Family.LINUX, Architecture.MIPSEL32)
object WASM32 : KonanTarget("wasm32", Family.WASM, Architecture.WASM32)
object ANDROID_ARM32 : KonanTarget( "android_arm32", Family.ANDROID, Architecture.ARM32)
object ANDROID_ARM64 : KonanTarget( "android_arm64", Family.ANDROID, Architecture.ARM64)
object IOS_ARM32 : KonanTarget( "ios_arm32", Family.IOS, Architecture.ARM32)
object IOS_ARM64 : KonanTarget( "ios_arm64", Family.IOS, Architecture.ARM64)
object IOS_X64 : KonanTarget( "ios_x64", Family.IOS, Architecture.X64)
object LINUX_X64 : KonanTarget( "linux_x64", Family.LINUX, Architecture.X64)
object MINGW_X86 : KonanTarget( "mingw_x86", Family.MINGW, Architecture.X86)
object MINGW_X64 : KonanTarget( "mingw_x64", Family.MINGW, Architecture.X64)
object MACOS_X64 : KonanTarget( "macos_x64", Family.OSX, Architecture.X64)
object LINUX_ARM64 : KonanTarget( "linux_arm64", Family.LINUX, Architecture.ARM64)
object LINUX_ARM32_HFP :KonanTarget( "linux_arm32_hfp", Family.LINUX, Architecture.ARM32)
object LINUX_MIPS32 : KonanTarget( "linux_mips32", Family.LINUX, Architecture.MIPS32)
object LINUX_MIPSEL32 : KonanTarget( "linux_mipsel32", Family.LINUX, Architecture.MIPSEL32)
object WASM32 : KonanTarget( "wasm32", Family.WASM, Architecture.WASM32)
// Tunable targets
class ZEPHYR(val subName: String, val genericName: String = "zephyr") :
KonanTarget("${genericName}_$subName", Family.ZEPHYR, Architecture.ARM32)
class ZEPHYR(val subName: String, val genericName: String = "zephyr") : KonanTarget("${genericName}_$subName", Family.ZEPHYR, Architecture.ARM32)
override fun toString() = name
}
// TODO: need a better way to enumerated predefined targets.
object PredefinedKonanTargets {
val ALL = listOf(
ANDROID_ARM32, ANDROID_ARM64,
IOS_ARM32, IOS_ARM64, IOS_X64,
LINUX_X64, LINUX_ARM32_HFP, LINUX_MIPS32, LINUX_MIPSEL32,
MINGW_X64, MINGW_X86,
MACOS_X64,
KonanTarget.WASM32
)
private val ALL_BY_NAME = ALL.associate { it.name to it }
fun getByName(name: String) = ALL_BY_NAME[name]
}
fun hostTargetSuffix(host: KonanTarget, target: KonanTarget) =
if (target == host) host.name else "${host.name}-${target.name}"
@@ -79,11 +62,11 @@ enum class CompilerOutputKind {
},
DYNAMIC {
override fun suffix(target: KonanTarget?) = ".${target!!.family.dynamicSuffix}"
override fun prefix(target: KonanTarget?) = target!!.family.dynamicPrefix
override fun prefix(target: KonanTarget?) = "${target!!.family.dynamicPrefix}"
},
STATIC {
override fun suffix(target: KonanTarget?) = ".${target!!.family.staticSuffix}"
override fun prefix(target: KonanTarget?) = target!!.family.staticPrefix
override fun prefix(target: KonanTarget?) = "${target!!.family.staticPrefix}"
},
FRAMEWORK {
override fun suffix(target: KonanTarget?): String = ".framework"
@@ -101,21 +84,13 @@ enum class CompilerOutputKind {
interface TargetManager {
val target: KonanTarget
val targetName: String
fun list()
val targetName : String
fun list() : Unit
val hostTargetSuffix: String
val targetSuffix: String
}
interface SubTargetProvider {
fun availableSubTarget(genericName: String): List<String>
}
private class NoSubTargets : SubTargetProvider {
override fun availableSubTarget(genericName: String): List<String> = emptyList()
}
private class TargetManagerImpl(val userRequest: String?, val hostManager: HostManager) : TargetManager {
private class TargetManagerImpl(val userRequest: String?, val hostManager: HostManager): TargetManager {
override val target = determineCurrent()
override val targetName
get() = target.visibleName
@@ -141,19 +116,30 @@ private class TargetManagerImpl(val userRequest: String?, val hostManager: HostM
override val targetSuffix get() = target.name
}
open class HostManager(subtargetProvider: SubTargetProvider = NoSubTargets()) {
open class HostManager(protected val distribution: Distribution = Distribution(), experimental: Boolean = false) {
fun targetManager(userRequest: String? = null): TargetManager = TargetManagerImpl(userRequest, this)
private val zephyrSubtargets = subtargetProvider.availableSubTarget("zephyr").map { ZEPHYR(it) }
// TODO: need a better way to enumerated predefined targets.
private val predefinedTargets = listOf(
ANDROID_ARM32, ANDROID_ARM64,
IOS_ARM32, IOS_ARM64, IOS_X64,
LINUX_X64, LINUX_ARM32_HFP, LINUX_ARM64, LINUX_MIPS32, LINUX_MIPSEL32,
MINGW_X64, MINGW_X86,
MACOS_X64,
WASM32)
private val zephyrSubtargets = distribution.availableSubTarget("zephyr").map { ZEPHYR(it) }
private val experimentalEnabled = experimental || distribution.experimentalEnabled
private val configurableSubtargets = zephyrSubtargets
val targetValues: List<KonanTarget> by lazy {
PredefinedKonanTargets.ALL + configurableSubtargets
predefinedTargets + configurableSubtargets
}
val targets = targetValues.associate { it.visibleName to it }
val targets = targetValues.associate{ it.visibleName to it }
fun toKonanTargets(names: Iterable<String>): List<KonanTarget> {
return names.map {
@@ -171,44 +157,74 @@ open class HostManager(subtargetProvider: SubTargetProvider = NoSubTargets()) {
fun targetByName(name: String): KonanTarget {
if (name == "host") return host
return targets[resolveAlias(name)] ?: throw TargetSupportException("Unknown target name: $name")
val target = targets[resolveAlias(name)]
if (target == null) throw TargetSupportException("Unknown target name: $name")
return target
}
val enabled: List<KonanTarget> by lazy {
enabledTargetsByHost[host]?.toList() ?: throw TargetSupportException("Unknown host platform: $host")
}
val enabledTargetsByHost = mapOf(
KonanTarget.LINUX_X64 to setOf(
KonanTarget.LINUX_X64,
KonanTarget.LINUX_ARM32_HFP,
KonanTarget.LINUX_MIPS32,
KonanTarget.LINUX_MIPSEL32,
KonanTarget.ANDROID_ARM32,
KonanTarget.ANDROID_ARM64,
KonanTarget.WASM32
) + zephyrSubtargets,
KonanTarget.MINGW_X64 to setOf(
KonanTarget.MINGW_X64,
KonanTarget.MINGW_X86,
KonanTarget.WASM32,
KonanTarget.LINUX_X64,
KonanTarget.LINUX_ARM32_HFP,
KonanTarget.ANDROID_ARM32
) + zephyrSubtargets,
KonanTarget.MACOS_X64 to setOf(
KonanTarget.MACOS_X64,
KonanTarget.IOS_ARM32,
KonanTarget.IOS_ARM64,
KonanTarget.IOS_X64,
KonanTarget.LINUX_X64,
KonanTarget.LINUX_ARM32_HFP,
KonanTarget.ANDROID_ARM32,
KonanTarget.ANDROID_ARM64,
KonanTarget.WASM32
) + zephyrSubtargets
val enabledRegularByHost: Map<KonanTarget, Set<KonanTarget>> = mapOf(
LINUX_X64 to setOf(
LINUX_X64,
LINUX_ARM32_HFP,
LINUX_ARM64,
LINUX_MIPS32,
LINUX_MIPSEL32,
ANDROID_ARM32,
ANDROID_ARM64,
WASM32
),
MINGW_X64 to setOf(
MINGW_X64,
MINGW_X86,
LINUX_X64,
LINUX_ARM32_HFP,
LINUX_ARM64,
ANDROID_ARM32,
// TODO: toolchain to be fixed for that to work.
// ANDROID_ARM64,
WASM32
),
MACOS_X64 to setOf(
MACOS_X64,
IOS_ARM32,
IOS_ARM64,
IOS_X64,
LINUX_X64,
LINUX_ARM32_HFP,
LINUX_ARM64,
ANDROID_ARM32,
ANDROID_ARM64,
WASM32
)
)
val enabledExperimentalByHost: Map<KonanTarget, Set<KonanTarget>> = mapOf(
LINUX_X64 to setOf(MINGW_X86, MINGW_X64) + zephyrSubtargets,
MACOS_X64 to setOf(MINGW_X86, MINGW_X64) + zephyrSubtargets,
MINGW_X64 to setOf<KonanTarget>() + zephyrSubtargets
)
val enabledByHost: Map<KonanTarget, Set<KonanTarget>> by lazy {
val result = enabledRegularByHost.toMutableMap()
if (experimentalEnabled) {
enabledExperimentalByHost.forEach { (k, v) ->
result.merge(k, v) { old, new -> old + new }
}
}
result.toMap()
}
val enabledRegular: List<KonanTarget> by lazy {
enabledRegularByHost[host]?.toList() ?: throw TargetSupportException("Unknown host platform: $host")
}
val enabledExperimental: List<KonanTarget> by lazy {
enabledExperimentalByHost[host]?.toList() ?: throw TargetSupportException("Unknown host platform: $host")
}
val enabled : List<KonanTarget>
get() = if (experimentalEnabled) enabledRegular + enabledExperimental else enabledRegular
fun isEnabled(target: KonanTarget) = enabled.contains(target)
companion object {
@@ -218,7 +234,7 @@ open class HostManager(subtargetProvider: SubTargetProvider = NoSubTargets()) {
javaOsName == "Mac OS X" -> "osx"
javaOsName == "Linux" -> "linux"
javaOsName.startsWith("Windows") -> "windows"
else -> throw TargetSupportException("Unknown operating system: $javaOsName")
else -> throw TargetSupportException("Unknown operating system: ${javaOsName}")
}
}
@@ -229,10 +245,10 @@ open class HostManager(subtargetProvider: SubTargetProvider = NoSubTargets()) {
}
val jniHostPlatformIncludeDir: String
get() = when (host) {
get() = when(host) {
KonanTarget.MACOS_X64 -> "darwin"
KonanTarget.LINUX_X64 -> "linux"
KonanTarget.MINGW_X64 -> "win32"
KonanTarget.MINGW_X64 ->"win32"
else -> throw TargetSupportException("Unknown host: $host.")
}
@@ -240,48 +256,51 @@ open class HostManager(subtargetProvider: SubTargetProvider = NoSubTargets()) {
val javaArch = System.getProperty("os.arch")
return when (javaArch) {
"x86_64" -> "x86_64"
"amd64" -> "x86_64"
"arm64" -> "arm64"
else -> throw TargetSupportException("Unknown hardware platform: $javaArch")
"amd64" -> "x86_64"
"arm64" -> "arm64"
else -> throw TargetSupportException("Unknown hardware platform: ${javaArch}")
}
}
val host: KonanTarget = when (host_os()) {
"osx" -> KonanTarget.MACOS_X64
"osx" -> KonanTarget.MACOS_X64
"linux" -> KonanTarget.LINUX_X64
"windows" -> KonanTarget.MINGW_X64
else -> throw TargetSupportException("Unknown host target: ${host_os()} ${host_arch()}")
}
val hostIsMac = (host == KonanTarget.MACOS_X64)
val hostIsLinux = (host == KonanTarget.LINUX_X64)
val hostIsMingw = (host == KonanTarget.MINGW_X64)
// Note Hotspot-specific VM option enforcing C1-only, critical for decent compilation speed.
val defaultJvmArgs = listOf("-XX:TieredStopAtLevel=1", "-ea", "-Dfile.encoding=UTF-8")
val regularJvmArgs = defaultJvmArgs + "-Xmx3G"
val hostIsMac = (host.family == Family.OSX)
val hostIsLinux = (host.family == Family.LINUX)
val hostIsMingw = (host.family == Family.MINGW)
val hostSuffix get() = host.name
@JvmStatic
val hostName
get() = host.name
val hostName get() = host.name
val knownTargetTemplates = listOf("zephyr")
private val targetAliasResolutions = mapOf(
"linux" to "linux_x64",
"macbook" to "macos_x64",
"macos" to "macos_x64",
"imac" to "macos_x64",
"linux" to "linux_x64",
"macbook" to "macos_x64",
"macos" to "macos_x64",
"imac" to "macos_x64",
"raspberrypi" to "linux_arm32_hfp",
"iphone32" to "ios_arm32",
"iphone" to "ios_arm64",
"ipad" to "ios_arm64",
"ios" to "ios_arm64",
"iphone_sim" to "ios_x64",
"mingw" to "mingw_x64"
"iphone32" to "ios_arm32",
"iphone" to "ios_arm64",
"ipad" to "ios_arm64",
"ios" to "ios_arm64",
"iphone_sim" to "ios_x64",
"mingw" to "mingw_x64"
)
private val targetAliases: Map<String, List<String>> by lazy {
val result = mutableMapOf<String, MutableList<String>>()
targetAliasResolutions.entries.forEach {
result.getOrPut(it.value, { mutableListOf() }).add(it.key)
result.getOrPut(it.value, { mutableListOf() } ).add(it.key)
}
result
}
@@ -292,10 +311,13 @@ open class HostManager(subtargetProvider: SubTargetProvider = NoSubTargets()) {
}
}
/**
* Name of a preset used in the 'kotlin-multiplatform' Gradle plugin to represent this target.
*/
val KonanTarget.presetName: String
get() = when (this) {
KonanTarget.ANDROID_ARM32 -> "androidNativeArm32"
KonanTarget.ANDROID_ARM64 -> "androidNativeArm64"
ANDROID_ARM32 -> "androidNativeArm32"
ANDROID_ARM64 -> "androidNativeArm64"
else -> evaluatePresetName(this.name)
}
@@ -304,4 +326,4 @@ private fun evaluatePresetName(targetName: String): String {
return nameParts.asSequence().drop(1).joinToString("", nameParts.firstOrNull().orEmpty(), transform = String::capitalize)
}
class TargetSupportException(message: String = "", cause: Throwable? = null) : Exception(message, cause)
class TargetSupportException (message: String = "", cause: Throwable? = null) : Exception(message, cause)
@@ -0,0 +1,79 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.konan.util
import kotlin.system.measureTimeMillis
import org.jetbrains.kotlin.konan.file.*
import java.lang.StringBuilder
fun <T> printMillisec(message: String, body: () -> T): T {
var result: T? = null
val msec = measureTimeMillis{
result = body()
}
println("$message: $msec msec")
return result!!
}
fun profile(message: String, body: () -> Unit) = profileIf(
System.getProperty("konan.profile")?.equals("true") ?: false,
message, body)
fun profileIf(condition: Boolean, message: String, body: () -> Unit) =
if (condition) printMillisec(message, body) else body()
fun nTabs(amount: Int): String {
return String.format("%1$-${(amount+1)*4}s", "")
}
fun String.prefixIfNot(prefix: String) =
if (this.startsWith(prefix)) this else "$prefix$this"
fun String.prefixBaseNameIfNot(prefix: String): String {
val file = File(this).absoluteFile
val name = file.name
val directory = file.parent
return "$directory/${name.prefixIfNot(prefix)}"
}
fun String.suffixIfNot(suffix: String) =
if (this.endsWith(suffix)) this else "$this$suffix"
fun String.removeSuffixIfPresent(suffix: String) =
if (this.endsWith(suffix)) this.dropLast(suffix.length) else this
fun <T> Lazy<T>.getValueOrNull(): T? = if (isInitialized()) value else null
fun parseSpaceSeparatedArgs(argsString: String): List<String> {
val parsedArgs = mutableListOf<String>()
var inQuotes = false
var currentCharSequence = StringBuilder()
fun saveArg() {
if (!currentCharSequence.isEmpty()) {
parsedArgs.add(currentCharSequence.toString())
currentCharSequence = StringBuilder()
}
}
argsString.forEach { char ->
if (char == '"') {
inQuotes = !inQuotes
// Save value which was in quotes.
if (!inQuotes) {
saveArg()
}
} else if (char == ' ' && !inQuotes) {
// Space is separator.
saveArg()
} else {
currentCharSequence.append(char)
}
}
if (inQuotes) {
error("No close-quote was found in $currentCharSequence.")
}
saveArg()
return parsedArgs
}
@@ -23,7 +23,6 @@ javadocJar()
repositories {
google()
maven("https://plugins.gradle.org/m2/")
maven(kotlinNativeRepo)
}
pill {
@@ -95,7 +95,7 @@ class KotlinNativeTargetPreset(
if (!konanTarget.enabledOnCurrentHost) {
with(HostManager()) {
val supportedHosts = enabledTargetsByHost.filterValues { konanTarget in it }.keys
val supportedHosts = enabledByHost.filterValues { konanTarget in it }.keys
val supportedHostsString =
if (supportedHosts.size == 1)
"a ${supportedHosts.single()} host" else