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:
committed by
alexander-gorshenev
parent
1d532729a8
commit
55c4966203
@@ -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"),
|
||||
MINGW("mingw", "exe"),
|
||||
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 {
|
||||
PROGRAM {
|
||||
override fun suffix(target: KonanTarget?) = ".${target!!.programSuffix}"
|
||||
@@ -42,37 +46,15 @@ enum class CompilerOutputKind {
|
||||
}
|
||||
|
||||
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 targetName
|
||||
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 {
|
||||
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
|
||||
}
|
||||
@@ -94,36 +76,52 @@ class TargetManager(val userRequest: String? = null) {
|
||||
}
|
||||
}
|
||||
|
||||
val hostSuffix get() = host.targetSuffix
|
||||
val hostTargetSuffix get() =
|
||||
if (target == host) host.targetSuffix else "${host.targetSuffix}-${target.targetSuffix}"
|
||||
val hostTargetSuffix get() = hostTargetSuffix(host, target)
|
||||
val targetSuffix get() = target.targetSuffix
|
||||
|
||||
val programSuffix get() = CompilerOutputKind.PROGRAM.suffix(target)
|
||||
|
||||
companion object {
|
||||
|
||||
fun host_os(): String {
|
||||
val javaOsName = System.getProperty("os.name")
|
||||
return when {
|
||||
javaOsName == "Mac OS X" -> "osx"
|
||||
javaOsName == "Linux" -> "linux"
|
||||
javaOsName.startsWith("Windows") -> "windows"
|
||||
else -> error("Unknown operating system: ${javaOsName}")
|
||||
else -> throw TargetSupportException("Unknown operating system: ${javaOsName}")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun simpleOsName(): String {
|
||||
val hostOs = host_os()
|
||||
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 {
|
||||
val javaArch = System.getProperty("os.arch")
|
||||
return when (javaArch) {
|
||||
"x86_64" -> "x86_64"
|
||||
"amd64" -> "x86_64"
|
||||
"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
|
||||
"linux" -> KonanTarget.LINUX
|
||||
"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)
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.properties
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
|
||||
typealias Properties = java.util.Properties
|
||||
|
||||
fun File.loadProperties(): Properties {
|
||||
val properties = java.util.Properties()
|
||||
this.bufferedReader().use { reader ->
|
||||
properties.load(reader)
|
||||
}
|
||||
return properties
|
||||
}
|
||||
|
||||
fun loadProperties(path: String): Properties = File(path).loadProperties()
|
||||
|
||||
fun File.saveProperties(properties: Properties) {
|
||||
this.outputStream().use {
|
||||
properties.store(it, null)
|
||||
}
|
||||
}
|
||||
|
||||
fun Properties.saveToFile(file: File) = file.saveProperties(this)
|
||||
|
||||
fun Properties.propertyString(key: String, suffix: String? = null): String?
|
||||
= this.getProperty(key.suffix(suffix))
|
||||
|
||||
/**
|
||||
* TODO: this method working with suffixes should be replaced with
|
||||
* functionality borrowed from def file parser and unified for interop tool
|
||||
* and kotlin compiler.
|
||||
*/
|
||||
fun Properties.propertyList(key: String, suffix: String? = null): List<String> {
|
||||
val value = this.getProperty(key.suffix(suffix)) ?: this.getProperty(key)
|
||||
return value?.split(' ') ?: emptyList()
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.properties
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
|
||||
fun Properties.hostString(name: String): String?
|
||||
= this.propertyString(name, TargetManager.host.targetSuffix)
|
||||
|
||||
fun Properties.hostList(name: String): List<String>
|
||||
= this.propertyList(name, TargetManager.host.targetSuffix)
|
||||
|
||||
fun Properties.targetString(name: String, target: KonanTarget): String?
|
||||
= this.propertyString(name, target.targetSuffix)
|
||||
|
||||
fun Properties.targetList(name: String, target: KonanTarget): List<String>
|
||||
= 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))
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.file
|
||||
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStream
|
||||
import java.io.InputStreamReader
|
||||
import java.net.URI
|
||||
import java.nio.file.*
|
||||
import java.nio.file.attribute.BasicFileAttributes
|
||||
|
||||
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))
|
||||
|
||||
val path: String
|
||||
get() = javaPath.toString()
|
||||
val absolutePath: String
|
||||
get() = javaPath.toAbsolutePath().toString()
|
||||
val absoluteFile: File
|
||||
get() = File(absolutePath)
|
||||
val name: String
|
||||
get() = javaPath.fileName.toString()
|
||||
val parent: String
|
||||
get() = javaPath.parent.toString()
|
||||
|
||||
val exists
|
||||
get() = Files.exists(javaPath)
|
||||
val isDirectory
|
||||
get() = Files.isDirectory(javaPath)
|
||||
val isFile
|
||||
get() = Files.isRegularFile(javaPath)
|
||||
val isAbsolute
|
||||
get() = javaPath.isAbsolute()
|
||||
val listFiles: List<File>
|
||||
get() {
|
||||
val stream = Files.newDirectoryStream(javaPath)
|
||||
val result = mutableListOf<File>()
|
||||
for (entry in stream) {
|
||||
result.add(File(entry))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun copyTo(destination: File, vararg options: StandardCopyOption) {
|
||||
Files.copy(javaPath, destination.javaPath, StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
|
||||
fun recursiveCopyTo(destination: File) {
|
||||
val sourcePath = javaPath
|
||||
val destPath = destination.javaPath
|
||||
sourcePath.recursiveCopyTo(destPath)
|
||||
}
|
||||
|
||||
fun mkdirs() = Files.createDirectories(javaPath)
|
||||
fun delete() = Files.deleteIfExists(javaPath)
|
||||
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>() {
|
||||
override fun visitFile(file: Path?, attrs: BasicFileAttributes?): FileVisitResult {
|
||||
task(file!!)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
|
||||
override fun preVisitDirectory(dir: Path?, attrs: BasicFileAttributes?): FileVisitResult {
|
||||
task(dir!!)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
fun postorder(task: (Path) -> Unit) {
|
||||
if (!this.exists) return
|
||||
|
||||
Files.walkFileTree(javaPath, object: SimpleFileVisitor<Path>() {
|
||||
override fun visitFile(file: Path?, attrs: BasicFileAttributes?): FileVisitResult {
|
||||
task(file!!)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
|
||||
override fun postVisitDirectory(dir: Path?, exc: java.io.IOException?): FileVisitResult {
|
||||
task(dir!!)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
fun deleteOnExit() {
|
||||
// Works only on the default file system,
|
||||
// but that's okay for now.
|
||||
javaPath.toFile().deleteOnExit()
|
||||
}
|
||||
fun readBytes() = Files.readAllBytes(javaPath)
|
||||
fun writeBytes(bytes: ByteArray) = Files.write(javaPath, bytes)
|
||||
fun forEachLine(action: (String) -> Unit) { Files.lines(javaPath).forEach { action(it) } }
|
||||
|
||||
override fun toString() = path
|
||||
|
||||
// TODO: Consider removeing these after konanazing java.util.Properties.
|
||||
fun bufferedReader() = Files.newBufferedReader(javaPath)
|
||||
fun outputStream() = Files.newOutputStream(javaPath)
|
||||
|
||||
companion object {
|
||||
val userDir
|
||||
get() = File(System.getProperty("user.dir"))
|
||||
|
||||
val userHome
|
||||
get() = File(System.getProperty("user.home"))
|
||||
|
||||
val jdkHome
|
||||
get() = File(System.getProperty("java.home"))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
private val File.zipUri: URI
|
||||
get() = URI.create("jar:${this.toPath().toUri()}")
|
||||
|
||||
fun File.zipFileSystem(mutable: Boolean = false): FileSystem {
|
||||
val zipUri = this.zipUri
|
||||
val allowCreation = if (mutable) "true" else "false"
|
||||
val attributes = hashMapOf("create" to if (mutable) "true" else "false")
|
||||
return FileSystems.newFileSystem(zipUri, attributes, null)
|
||||
}
|
||||
|
||||
fun File.mutableZipFileSystem() = this.zipFileSystem(mutable = true)
|
||||
|
||||
fun File.zipPath(path: String): Path
|
||||
= this.zipFileSystem().getPath(path)
|
||||
|
||||
val File.asZipRoot: File
|
||||
get() = File(this.zipPath("/"))
|
||||
|
||||
val File.asWritableZipRoot: File
|
||||
get() = File(this.mutableZipFileSystem().getPath("/"))
|
||||
|
||||
private fun File.toPath() = Paths.get(this.path)
|
||||
|
||||
fun File.zipDirAs(unixFile: File) {
|
||||
val zipRoot = unixFile.asWritableZipRoot
|
||||
this.recursiveCopyTo(zipRoot)
|
||||
zipRoot.javaPath.fileSystem.close()
|
||||
}
|
||||
|
||||
fun Path.recursiveCopyTo(destPath: Path) {
|
||||
val sourcePath = this
|
||||
Files.walk(sourcePath).forEach next@ { oldPath ->
|
||||
|
||||
val relative = sourcePath.relativize(oldPath)
|
||||
val destFs = destPath.getFileSystem()
|
||||
// We are copying files between file systems,
|
||||
// so pass the relative path through the Sting.
|
||||
val newPath = destFs.getPath(destPath.toString(), relative.toString())
|
||||
|
||||
// File systems don't allow replacing an existing root.
|
||||
if (newPath == newPath.getRoot()) return@next
|
||||
Files.copy(oldPath, newPath,
|
||||
StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
}
|
||||
|
||||
fun bufferedReader(errorStream: InputStream?) = BufferedReader(InputStreamReader(errorStream))
|
||||
|
||||
Reference in New Issue
Block a user