Preliminary tvOS support.

This commit is contained in:
Sergey Bogolepov
2019-05-15 19:08:19 +07:00
committed by Sergey Bogolepov
parent 7844dc5228
commit 237b7ef182
23 changed files with 300 additions and 97 deletions
@@ -248,19 +248,24 @@ internal val ObjCContainer.classOrProtocol: ObjCClassOrProtocol
internal fun Type.isStret(target: KonanTarget): Boolean { internal fun Type.isStret(target: KonanTarget): Boolean {
val unwrappedType = this.unwrapTypedefs() val unwrappedType = this.unwrapTypedefs()
return when (target) { return when (target) {
KonanTarget.IOS_ARM64 -> KonanTarget.IOS_ARM64,
KonanTarget.TVOS_ARM64 ->
false // On aarch64 stret is never the case, since an implicit argument gets passed on x8. false // On aarch64 stret is never the case, since an implicit argument gets passed on x8.
KonanTarget.IOS_X64, KonanTarget.MACOS_X64 -> when (unwrappedType) { KonanTarget.IOS_X64,
KonanTarget.MACOS_X64,
KonanTarget.WATCHOS_X64,
KonanTarget.TVOS_X64 -> when (unwrappedType) {
is RecordType -> unwrappedType.decl.def!!.size > 16 || this.hasUnalignedMembers() is RecordType -> unwrappedType.decl.def!!.size > 16 || this.hasUnalignedMembers()
else -> false else -> false
} }
KonanTarget.IOS_ARM32 -> {
when (unwrappedType) { KonanTarget.IOS_ARM32 -> when (unwrappedType) {
is RecordType -> !this.isIntegerLikeType() is RecordType -> !this.isIntegerLikeType()
else -> false else -> false
} }
}
KonanTarget.WATCHOS_ARM64 -> TODO("")
else -> error(target) else -> error(target)
} }
@@ -21,8 +21,8 @@ class CStubsManager(private val target: KonanTarget) {
if (stubs.isEmpty()) return null if (stubs.isEmpty()) return null
val compilerOptions = mutableListOf<String>() val compilerOptions = mutableListOf<String>()
val sourceFileExtension = when (target.family) { val sourceFileExtension = when {
Family.OSX, Family.IOS -> { target.family.isAppleFamily -> {
compilerOptions += "-fobjc-arc" compilerOptions += "-fobjc-arc"
".m" // TODO: consider managing C and Objective-C stubs separately. ".m" // TODO: consider managing C and Objective-C stubs separately.
} }
@@ -4,6 +4,7 @@ import org.jetbrains.kotlin.konan.KonanExternalToolFailure
import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.Family import org.jetbrains.kotlin.konan.target.Family
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.target.LinkerOutputKind import org.jetbrains.kotlin.konan.target.LinkerOutputKind
internal fun determineLinkerOutput(context: Context): LinkerOutputKind = internal fun determineLinkerOutput(context: Context): LinkerOutputKind =
@@ -66,7 +67,9 @@ internal class Linker(val context: Context) {
val framework = File(context.config.outputFile) val framework = File(context.config.outputFile)
val dylibName = framework.name.removeSuffix(".framework") val dylibName = framework.name.removeSuffix(".framework")
val dylibRelativePath = when (target.family) { val dylibRelativePath = when (target.family) {
Family.IOS -> dylibName Family.IOS,
Family.TVOS,
Family.WATCHOS -> dylibName
Family.OSX -> "Versions/A/$dylibName" Family.OSX -> "Versions/A/$dylibName"
else -> error(target) else -> error(target)
} }
@@ -51,6 +51,8 @@ private class LlvmPipelineConfiguration(context: Context) {
KonanTarget.IOS_ARM32 -> "generic" KonanTarget.IOS_ARM32 -> "generic"
KonanTarget.IOS_ARM64 -> "cyclone" KonanTarget.IOS_ARM64 -> "cyclone"
KonanTarget.IOS_X64 -> "core2" KonanTarget.IOS_X64 -> "core2"
KonanTarget.TVOS_ARM64 -> "cyclone"
KonanTarget.TVOS_X64 -> "core2"
KonanTarget.LINUX_X64 -> "x86-64" KonanTarget.LINUX_X64 -> "x86-64"
KonanTarget.MINGW_X86 -> "pentium4" KonanTarget.MINGW_X86 -> "pentium4"
KonanTarget.MINGW_X64 -> "x86-64" KonanTarget.MINGW_X64 -> "x86-64"
@@ -67,8 +69,6 @@ private class LlvmPipelineConfiguration(context: Context) {
KonanTarget.WATCHOS_ARM32 -> TODO("implement me") KonanTarget.WATCHOS_ARM32 -> TODO("implement me")
KonanTarget.WATCHOS_X64 -> TODO("implement me") KonanTarget.WATCHOS_X64 -> TODO("implement me")
KonanTarget.WATCHOS_X86 -> TODO("implement me") KonanTarget.WATCHOS_X86 -> TODO("implement me")
KonanTarget.TVOS_ARM64 -> TODO("implement me")
KonanTarget.TVOS_X64 -> TODO("implement me")
KonanTarget.WASM32, KonanTarget.WASM32,
is KonanTarget.ZEPHYR -> error("There is no support for ${target.name} target yet.") is KonanTarget.ZEPHYR -> error("There is no support for ${target.name} target yet.")
} }
@@ -634,8 +634,9 @@ private fun KotlinStubs.getNamedCStructType(kotlinClass: IrClass): CType? {
} }
// TODO: rework Boolean support. // TODO: rework Boolean support.
// TODO: What should be used on watchOS?
private fun cBoolType(target: KonanTarget): CType? = when (target.family) { private fun cBoolType(target: KonanTarget): CType? = when (target.family) {
Family.IOS -> CTypes.C99Bool Family.IOS, Family.TVOS -> CTypes.C99Bool
else -> CTypes.signedChar else -> CTypes.signedChar
} }
@@ -809,7 +810,7 @@ private fun KotlinStubs.mapType(
} }
private fun KotlinStubs.isObjCReferenceType(type: IrType): Boolean { private fun KotlinStubs.isObjCReferenceType(type: IrType): Boolean {
if (target.family != Family.OSX && target.family != Family.IOS) return false if (!target.family.isAppleFamily) return false
// Handle the same types as produced by [objCPointerMirror] in Interop/StubGenerator/.../Mappings.kt. // Handle the same types as produced by [objCPointerMirror] in Interop/StubGenerator/.../Mappings.kt.
@@ -90,8 +90,8 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
else else
LLVMCreateLocation(LLVMGetModuleContext(context.llvmModule), locationInfo.line, locationInfo.column, locationInfo.scope) LLVMCreateLocation(LLVMGetModuleContext(context.llvmModule), locationInfo.line, locationInfo.column, locationInfo.scope)
val objCDataGenerator = when (context.config.target.family) { val objCDataGenerator = when {
Family.IOS, Family.OSX -> ObjCDataGenerator(this) context.config.target.family.isAppleFamily -> ObjCDataGenerator(this)
else -> null else -> null
} }
@@ -19,10 +19,7 @@ import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.konan.exec.Command import org.jetbrains.kotlin.konan.exec.Command
import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.file.createTempFile import org.jetbrains.kotlin.konan.file.createTempFile
import org.jetbrains.kotlin.konan.target.AppleConfigurables import org.jetbrains.kotlin.konan.target.*
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.Family
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.isSubpackageOf import org.jetbrains.kotlin.name.isSubpackageOf
@@ -43,7 +40,7 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
private val codeSpec = exportedInterface?.createCodeSpec(symbolTable) private val codeSpec = exportedInterface?.createCodeSpec(symbolTable)
private fun produceInterface(): ObjCExportedInterface? { private fun produceInterface(): ObjCExportedInterface? {
if (target.family != Family.IOS && target.family != Family.OSX) return null if (!target.family.isAppleFamily) return null
if (!context.config.produce.isNativeBinary) return null // TODO: emit RTTI to the same modules as classes belong to. if (!context.config.produce.isNativeBinary) return null // TODO: emit RTTI to the same modules as classes belong to.
@@ -70,7 +67,7 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
} }
internal fun generate(codegen: CodeGenerator) { internal fun generate(codegen: CodeGenerator) {
if (target.family != Family.IOS && target.family != Family.OSX) return if (!target.family.isAppleFamily) return
if (!context.config.produce.isNativeBinary) return // TODO: emit RTTI to the same modules as classes belong to. if (!context.config.produce.isNativeBinary) return // TODO: emit RTTI to the same modules as classes belong to.
@@ -99,7 +96,9 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
private fun produceFrameworkSpecific(headerLines: List<String>) { private fun produceFrameworkSpecific(headerLines: List<String>) {
val framework = File(context.config.outputFile) val framework = File(context.config.outputFile)
val frameworkContents = when(target.family) { val frameworkContents = when(target.family) {
Family.IOS -> framework Family.IOS,
Family.WATCHOS,
Family.TVOS -> framework
Family.OSX -> framework.child("Versions/A") Family.OSX -> framework.child("Versions/A")
else -> error(target) else -> error(target)
} }
@@ -137,9 +136,11 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
} }
private fun emitInfoPlist(frameworkContents: File, name: String) { private fun emitInfoPlist(frameworkContents: File, name: String) {
val directory = when { val directory = when (target.family) {
target.family == Family.IOS -> frameworkContents Family.IOS,
target == KonanTarget.MACOS_X64 -> frameworkContents.child("Resources").also { it.mkdirs() } Family.WATCHOS,
Family.TVOS -> frameworkContents
Family.OSX -> frameworkContents.child("Resources").also { it.mkdirs() }
else -> error(target) else -> error(target)
} }
@@ -150,6 +151,8 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
val platform = when (target) { val platform = when (target) {
KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> "iPhoneOS" KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> "iPhoneOS"
KonanTarget.IOS_X64 -> "iPhoneSimulator" KonanTarget.IOS_X64 -> "iPhoneSimulator"
KonanTarget.TVOS_ARM64 -> "AppleTVOS"
KonanTarget.TVOS_X64 -> "AppleTVSimulator"
KonanTarget.MACOS_X64 -> "MacOSX" KonanTarget.MACOS_X64 -> "MacOSX"
else -> error(target) else -> error(target)
} }
@@ -183,21 +186,32 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
""".trimIndent()) """.trimIndent())
fun addUiDeviceFamilies(vararg values: Int) {
contents.append(when (target.family) { val xmlValues = values.joinToString(separator = "\n") {
Family.IOS -> """ " <integer>$it</integer>"
}
contents.append("""
| <key>MinimumOSVersion</key> | <key>MinimumOSVersion</key>
| <string>$minimumOsVersion</string> | <string>$minimumOsVersion</string>
| <key>UIDeviceFamily</key> | <key>UIDeviceFamily</key>
| <array> | <array>
| <integer>1</integer> |$xmlValues
| <integer>2</integer>
| </array> | </array>
""".trimMargin() """.trimMargin())
Family.OSX -> "" }
else -> error(target)
}) // UIDeviceFamily mapping:
// 1 - iPhone
// 2 - iPad
// 3 - AppleTV
// 4 - Apple Watch
when (target.family) {
Family.IOS -> addUiDeviceFamilies(1, 2)
Family.TVOS -> addUiDeviceFamilies(3)
Family.WATCHOS -> addUiDeviceFamilies(4)
else -> {}
}
if (target == KonanTarget.IOS_ARM64) { if (target == KonanTarget.IOS_ARM64) {
contents.append(""" contents.append("""
@@ -85,6 +85,7 @@ fun create(project: Project): ExecutorService {
} }
KonanTarget.IOS_X64 -> simulator(project) KonanTarget.IOS_X64 -> simulator(project)
KonanTarget.TVOS_X64 -> simulator(project)
else -> { else -> {
if (project.hasProperty("remote")) sshExecutor(project) if (project.hasProperty("remote")) sshExecutor(project)
@@ -213,8 +214,14 @@ fun localExecutor(project: Project) = { a: Action<in ExecSpec> -> project.exec(a
*/ */
private fun simulator(project: Project) : ExecutorService = object : ExecutorService { private fun simulator(project: Project) : ExecutorService = object : ExecutorService {
private val target = project.testTarget
private val simctl by lazy { private val simctl by lazy {
val sdk = Xcode.current.iphonesimulatorSdk val sdk = when (target) {
KonanTarget.TVOS_X64 -> Xcode.current.appletvsimulatorSdk
KonanTarget.IOS_X64 -> Xcode.current.iphonesimulatorSdk
else -> error("Unexpected simulation target: $target")
}
val out = ByteArrayOutputStream() val out = ByteArrayOutputStream()
val result = project.exec { val result = project.exec {
it.commandLine("/usr/bin/xcrun", "--find", "simctl", "--sdk", sdk) it.commandLine("/usr/bin/xcrun", "--find", "simctl", "--sdk", sdk)
@@ -224,11 +231,16 @@ private fun simulator(project: Project) : ExecutorService = object : ExecutorSer
out.toString("UTF-8").trim() out.toString("UTF-8").trim()
} }
private val iosDevice = project.findProperty("iosDevice")?.toString() ?: "iPhone 6" private val device = project.findProperty("iosDevice")?.toString() ?: when (target) {
KonanTarget.TVOS_X64 -> "Apple TV 4K"
KonanTarget.IOS_X64 -> "iPhone 6"
else -> error("Unexpected simulation target: $target")
}
override fun execute(action: Action<in ExecSpec>): ExecResult? = project.exec { execSpec -> override fun execute(action: Action<in ExecSpec>): ExecResult? = project.exec { execSpec ->
action.execute(execSpec) action.execute(execSpec)
with(execSpec) { commandLine = listOf(simctl, "spawn", iosDevice, executable) + args } // Starting Xcode 11 `simctl spawn` requires explicit `--standalone` flag.
with(execSpec) { commandLine = listOf(simctl, "spawn", "--standalone", device, executable) + args }
} }
} }
@@ -86,31 +86,50 @@ open class FrameworkTest : DefaultTask() {
runTest(testExecutable) runTest(testExecutable)
} }
private fun runTest(testExecutable: Path) { /**
* Returns path to directory that contains `libswiftCore.dylib` for the current
* test target.
*/
private fun getSwiftLibsPathForTestTarget(): String {
val target = project.testTarget val target = project.testTarget
val platform = project.platformManager.platform(target) val platform = project.platformManager.platform(target)
val configs = platform.configurables as AppleConfigurables val configs = platform.configurables as AppleConfigurables
val swiftPlatform = when (target) { val swiftPlatform = when (target) {
KonanTarget.IOS_X64 -> "iphonesimulator" KonanTarget.IOS_X64 -> "iphonesimulator"
KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> "iphoneos" KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> "iphoneos"
KonanTarget.TVOS_X64 -> "appletvsimulator"
KonanTarget.TVOS_ARM64 -> "appletvos"
KonanTarget.MACOS_X64 -> "macosx" KonanTarget.MACOS_X64 -> "macosx"
else -> throw IllegalStateException("Test target $target is not supported") else -> throw IllegalStateException("Test target $target is not supported")
} }
val libraryPath = configs.absoluteTargetToolchain + "/usr/lib/swift/$swiftPlatform" return when (target) {
val executor = (project.convention.plugins["executor"] as? ExecutorService) KonanTarget.TVOS_X64,
?: throw RuntimeException("Executor wasn't found") KonanTarget.IOS_X64,
KonanTarget.WATCHOS_X64 -> Xcode.current.getLatestSimulatorRuntimeFor(target, configs.osVersionMin)?.let {
"${it.bundlePath}/Contents/Resources/RuntimeRoot/usr/lib/swift"
} ?: error("Simulator runtime for $target ${configs.osVersionMin} is not available")
else -> configs.absoluteTargetToolchain + "/usr/lib/swift/$swiftPlatform"
}
}
private fun buildEnvironment(): Map<String, String> {
val target = project.testTarget
// Hopefully, lexicographical comparison will work. // Hopefully, lexicographical comparison will work.
val newMacos = System.getProperty("os.version").compareTo("10.14.4") >= 0 val newMacos = System.getProperty("os.version").compareTo("10.14.4") >= 0
val dyldLibraryPathKey = if (target == KonanTarget.IOS_X64) { val dyldLibraryPathKey = when (target) {
"SIMCTL_CHILD_DYLD_LIBRARY_PATH" KonanTarget.IOS_X64, KonanTarget.TVOS_X64 -> "SIMCTL_CHILD_DYLD_LIBRARY_PATH"
} else { else -> "DYLD_LIBRARY_PATH"
"DYLD_LIBRARY_PATH"
} }
val environment = if (newMacos) emptyMap() else mapOf( return if (newMacos && target == KonanTarget.MACOS_X64) emptyMap() else mapOf(
dyldLibraryPathKey to libraryPath dyldLibraryPathKey to getSwiftLibsPathForTestTarget()
) )
}
private fun runTest(testExecutable: Path) {
val executor = (project.convention.plugins["executor"] as? ExecutorService)
?: throw RuntimeException("Executor wasn't found")
val (stdOut, stdErr, exitCode) = runProcess( val (stdOut, stdErr, exitCode) = runProcess(
executor = executor.add(Action { it.environment = environment })::execute, executor = executor.add(Action { it.environment = buildEnvironment() })::execute,
executable = testExecutable.toString()) executable = testExecutable.toString())
println(""" println("""
@@ -131,9 +150,10 @@ open class FrameworkTest : DefaultTask() {
val bitcodeBuildTool = "${configurables.absoluteAdditionalToolsDir}/bin/bitcode-build-tool" val bitcodeBuildTool = "${configurables.absoluteAdditionalToolsDir}/bin/bitcode-build-tool"
val ldPath = "${configurables.absoluteTargetToolchain}/usr/bin/ld" val ldPath = "${configurables.absoluteTargetToolchain}/usr/bin/ld"
val sdk = when (testTarget) { val sdk = when (testTarget) {
KonanTarget.IOS_X64 -> return // bitcode-build-tool doesn't support iPhone Simulator. KonanTarget.IOS_X64, KonanTarget.TVOS_X64 -> return // bitcode-build-tool doesn't support simulators.
KonanTarget.IOS_ARM64, KonanTarget.IOS_ARM32 -> Xcode.current.iphoneosSdk KonanTarget.IOS_ARM64, KonanTarget.IOS_ARM32 -> Xcode.current.iphoneosSdk
KonanTarget.MACOS_X64 -> Xcode.current.macosxSdk KonanTarget.MACOS_X64 -> Xcode.current.macosxSdk
KonanTarget.TVOS_ARM64 -> Xcode.current.appletvosSdk
else -> error("Cannot validate bitcode for test target $testTarget") else -> error("Cannot validate bitcode for test target $testTarget")
} }
@@ -147,4 +167,4 @@ open class FrameworkTest : DefaultTask() {
""".trimMargin() """.trimMargin()
} }
} }
} }
@@ -15,12 +15,12 @@ object PlatformInfo {
@JvmStatic @JvmStatic
fun isAppleTarget(project: Project): Boolean { fun isAppleTarget(project: Project): Boolean {
val target = getTarget(project) val target = getTarget(project)
return target.family == Family.IOS || target.family == Family.OSX return target.family.isAppleFamily
} }
@JvmStatic @JvmStatic
fun isAppleTarget(target: KonanTarget): Boolean { fun isAppleTarget(target: KonanTarget): Boolean {
return target.family == Family.IOS || target.family == Family.OSX return target.family.isAppleFamily
} }
@JvmStatic @JvmStatic
@@ -215,6 +215,8 @@ fun compileSwift(project: Project, target: KonanTarget, sources: List<String>, o
val swiftTarget = when (target) { val swiftTarget = when (target) {
KonanTarget.IOS_X64 -> "x86_64-apple-ios" + configs.osVersionMin KonanTarget.IOS_X64 -> "x86_64-apple-ios" + configs.osVersionMin
KonanTarget.IOS_ARM64 -> "arm64_64-apple-ios" + configs.osVersionMin KonanTarget.IOS_ARM64 -> "arm64_64-apple-ios" + configs.osVersionMin
KonanTarget.TVOS_X64 -> "x86_64-apple-tvos" + configs.osVersionMin
KonanTarget.TVOS_ARM64 -> "arm64_64-apple-tvos" + configs.osVersionMin
KonanTarget.MACOS_X64 -> "x86_64-apple-macosx" + configs.osVersionMin KonanTarget.MACOS_X64 -> "x86_64-apple-macosx" + configs.osVersionMin
else -> throw IllegalStateException("Test target $target is not supported") else -> throw IllegalStateException("Test target $target is not supported")
} }
@@ -0,0 +1,59 @@
package org.jetbrains.kotlin
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.target.Xcode
import kotlin.math.min
/**
* Compares two strings assuming that both are representing numeric version strings.
* Examples of numeric version strings: "12.4.1.2", "9", "0.5".
*/
private fun compareStringsAsVersions(version1: String, version2: String): Int {
val version1 = version1.split('.').map { it.toInt() }
val version2 = version2.split('.').map { it.toInt() }
val minimalLength = min(version1.size, version2.size)
for (index in 0 until minimalLength) {
if (version1[index] < version2[index]) return -1
if (version1[index] > version2[index]) return 1
}
return version1.size.compareTo(version2.size)
}
/**
* Returns parsed output of `xcrun simctl list runtimes -j`.
*/
private fun Xcode.getSimulatorRuntimeDescriptors(): List<SimulatorRuntimeDescriptor> =
Json.nonstrict.parse(ListRuntimesReport.serializer(), this.simulatorRuntimes).runtimes
/**
* Returns first available simulator runtime for [target] with at least [osMinVersion] OS version.
* */
fun Xcode.getLatestSimulatorRuntimeFor(target: KonanTarget, osMinVersion: String): SimulatorRuntimeDescriptor? {
val osName = when (target) {
KonanTarget.IOS_X64 -> "iOS"
KonanTarget.WATCHOS_X64 -> "watchOS"
KonanTarget.TVOS_X64 -> "tvOS"
else -> error("Unexpected simulator target: $target")
}
return getSimulatorRuntimeDescriptors().firstOrNull {
it.isAvailable && it.name.startsWith(osName) && compareStringsAsVersions(it.version, osMinVersion) >= 0
}
}
// Result of `xcrun simctl list runtimes -j`.
@Serializable
data class ListRuntimesReport(
val runtimes: List<SimulatorRuntimeDescriptor>
)
@Serializable
data class SimulatorRuntimeDescriptor(
val version: String,
val bundlePath: String,
val isAvailable: Boolean,
val name: String,
val identifier: String,
val buildversion: String
)
+54
View File
@@ -151,6 +151,60 @@ osVersionMinFlagLd.ios_x64 = -ios_simulator_version_min
osVersionMinFlagClang.ios_x64 = -mios-simulator-version-min osVersionMinFlagClang.ios_x64 = -mios-simulator-version-min
osVersionMin.ios_x64 = 9.0 osVersionMin.ios_x64 = 9.0
# Apple's tvOS simulator.
targetToolchain.macos_x64-tvos_x64 = target-toolchain-9-macos_x64
dependencies.macos_x64-tvos_x64 = \
libffi-3.2.1-3-darwin-macos \
clang-llvm-6.0.1-darwin-macos
target-sysroot-9-tvos_x64.default = \
remote:internal
arch.tvos_x64 = x86_64
entrySelector.tvos_x64 = -alias _Konan_main _main
targetSysRoot.tvos_x64 = target-sysroot-9-tvos_x64
clangFlags.tvos_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir
clangNooptFlags.tvos_x64 = -O1
clangOptFlags.tvos_x64 = -O3
clangDebugFlags.tvos_x64 = -O0
clangDynamicFlags.tvos_x64 =
linkerKonanFlags.tvos_x64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 11.2
linkerOptimizationFlags.tvos_x64 = -dead_strip
linkerNoDebugFlags.tvos_x64 = -S
linkerDynamicFlags.tvos_x64 = -dylib
osVersionMinFlagLd.tvos_x64 = -tvos_simulator_version_min
osVersionMinFlagClang.tvos_x64 = -mtvos-simulator-version-min
osVersionMin.tvos_x64 = 9.0
# Apple's 64-bit tvOS.
targetToolchain.macos_x64-tvos_arm64 = target-toolchain-9-macos_x64
dependencies.macos_x64-tvos_arm64 = \
libffi-3.2.1-3-darwin-macos \
clang-llvm-6.0.1-darwin-macos
target-sysroot-9-tvos_arm64.default = \
remote:internal
arch.tvos_arm64 = arm64
entrySelector.tvos_arm64 = -alias _Konan_main _main
targetSysRoot.tvos_arm64 = target-sysroot-9-tvos_arm64
clangFlags.tvos_arm64 = -cc1 -emit-obj -disable-llvm-passes -x ir
clangNooptFlags.tvos_arm64 = -O1
clangOptFlags.tvos_arm64 = -O3
clangDebugFlags.tvos_arm64 = -O0
clangDynamicFlags.tvos_arm64 =
linkerNoDebugFlags.tvos_arm64 = -S
linkerDynamicFlags.tvos_arm64 = -dylib
linkerKonanFlags.tvos_arm64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 11.2
linkerOptimizationFlags.tvos_arm64 = -dead_strip
osVersionMinFlagLd.tvos_arm64 = -tvos_version_min
osVersionMinFlagClang.tvos_arm64 = -mtvos-version-min
osVersionMin.tvos_arm64 = 9.0
# Linux x86-64. # Linux x86-64.
llvmHome.linux_x64 = clang-llvm-6.0.1-linux-x86-64 llvmHome.linux_x64 = clang-llvm-6.0.1-linux-x86-64
libffiDir.linux_x64 = libffi-3.2.1-2-linux-x86-64 libffiDir.linux_x64 = libffi-3.2.1-2-linux-x86-64
@@ -35,6 +35,8 @@ class AppleConfigurablesImpl(
KonanTarget.MACOS_X64 -> xcodePartsProvider.xcode.macosxSdk KonanTarget.MACOS_X64 -> xcodePartsProvider.xcode.macosxSdk
KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> xcodePartsProvider.xcode.iphoneosSdk KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> xcodePartsProvider.xcode.iphoneosSdk
KonanTarget.IOS_X64 -> xcodePartsProvider.xcode.iphonesimulatorSdk KonanTarget.IOS_X64 -> xcodePartsProvider.xcode.iphonesimulatorSdk
KonanTarget.TVOS_ARM64 -> xcodePartsProvider.xcode.appletvosSdk
KonanTarget.TVOS_X64 -> xcodePartsProvider.xcode.appletvsimulatorSdk
else -> error(target) else -> error(target)
} }
XcodePartsProvider.InternalServer -> absolute(sdkDependency) XcodePartsProvider.InternalServer -> absolute(sdkDependency)
@@ -37,6 +37,12 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con
configurables.targetArg configurables.targetArg
else null else null
private val osVersionMin: String
get() {
require(configurables is AppleConfigurables)
return configurables.osVersionMin
}
val specificClangArgs: List<String> val specificClangArgs: List<String>
get() { get() {
val result = when (target) { val result = when (target) {
@@ -74,16 +80,22 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con
listOf("-target", targetArg!!, "--sysroot=$absoluteTargetSysRoot", "-Xclang", "-flto-visibility-public-std") listOf("-target", targetArg!!, "--sysroot=$absoluteTargetSysRoot", "-Xclang", "-flto-visibility-public-std")
KonanTarget.MACOS_X64 -> KonanTarget.MACOS_X64 ->
listOf("--sysroot=$absoluteTargetSysRoot", "-mmacosx-version-min=10.11") listOf("--sysroot=$absoluteTargetSysRoot", "-mmacosx-version-min=$osVersionMin")
KonanTarget.IOS_ARM32 -> KonanTarget.IOS_ARM32 ->
listOf("-stdlib=libc++", "-arch", "armv7", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=9.0.0") listOf("-stdlib=libc++", "-arch", "armv7", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=$osVersionMin")
KonanTarget.IOS_ARM64 -> KonanTarget.IOS_ARM64 ->
listOf("-stdlib=libc++", "-arch", "arm64", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=9.0.0") listOf("-stdlib=libc++", "-arch", "arm64", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=$osVersionMin")
KonanTarget.TVOS_ARM64 ->
listOf("-stdlib=libc++", "-arch", "arm64", "-isysroot", absoluteTargetSysRoot, "-mtvos-version-min=$osVersionMin")
KonanTarget.TVOS_X64 ->
listOf("-stdlib=libc++", "-isysroot", absoluteTargetSysRoot, "-mtvos-simulator-version-min=$osVersionMin")
KonanTarget.IOS_X64 -> KonanTarget.IOS_X64 ->
listOf("-stdlib=libc++", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=9.0.0") listOf("-stdlib=libc++", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=$osVersionMin")
KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64, KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64,
KonanTarget.ANDROID_X86, KonanTarget.ANDROID_X64 -> { KonanTarget.ANDROID_X86, KonanTarget.ANDROID_X64 -> {
@@ -118,8 +130,6 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con
KonanTarget.WATCHOS_ARM32 -> TODO("implement me") KonanTarget.WATCHOS_ARM32 -> TODO("implement me")
KonanTarget.WATCHOS_X64 -> TODO("implement me") KonanTarget.WATCHOS_X64 -> TODO("implement me")
KonanTarget.WATCHOS_X86 -> TODO("implement me") KonanTarget.WATCHOS_X86 -> TODO("implement me")
KonanTarget.TVOS_ARM64 -> TODO("implement me")
KonanTarget.TVOS_X64 -> TODO("implement me")
is KonanTarget.ZEPHYR -> is KonanTarget.ZEPHYR ->
listOf("-target", targetArg!!, listOf("-target", targetArg!!,
@@ -233,6 +243,21 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con
"-DKONAN_CORE_SYMBOLICATION=1", "-DKONAN_CORE_SYMBOLICATION=1",
"-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1") "-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1")
KonanTarget.TVOS_ARM64 ->
listOf("-DKONAN_OBJC_INTEROP=1",
"-DKONAN_IOS=1",
"-DKONAN_ARM64=1",
"-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1",
"-DKONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG=1",
"-DMACHSIZE=64")
KonanTarget.TVOS_X64 ->
listOf("-DKONAN_OBJC_INTEROP=1",
"-DKONAN_IOS=1",
"-DKONAN_X64=1",
"-DKONAN_CORE_SYMBOLICATION=1",
"-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1")
KonanTarget.ANDROID_ARM32 -> KonanTarget.ANDROID_ARM32 ->
listOf("-D__ANDROID__", listOf("-D__ANDROID__",
"-DUSE_GCC_UNWIND=1", "-DUSE_GCC_UNWIND=1",
@@ -284,9 +309,6 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con
KonanTarget.WATCHOS_ARM32 -> TODO("implement me") KonanTarget.WATCHOS_ARM32 -> TODO("implement me")
KonanTarget.WATCHOS_X64 -> TODO("implement me") KonanTarget.WATCHOS_X64 -> TODO("implement me")
KonanTarget.WATCHOS_X86 -> TODO("implement me") KonanTarget.WATCHOS_X86 -> TODO("implement me")
KonanTarget.TVOS_ARM64 -> TODO("implement me")
KonanTarget.TVOS_X64 -> TODO("implement me")
is KonanTarget.ZEPHYR -> is KonanTarget.ZEPHYR ->
listOf( "-DKONAN_ZEPHYR=1", listOf( "-DKONAN_ZEPHYR=1",
@@ -42,7 +42,9 @@ fun loadConfigurables(target: KonanTarget, properties: Properties, baseDir: Stri
LinuxConfigurablesImpl(target, properties, baseDir) LinuxConfigurablesImpl(target, properties, baseDir)
KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 -> KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 ->
LinuxMIPSConfigurablesImpl(target, properties, baseDir) LinuxMIPSConfigurablesImpl(target, properties, baseDir)
KonanTarget.MACOS_X64, KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64, KonanTarget.IOS_X64 -> KonanTarget.MACOS_X64,
KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64, KonanTarget.IOS_X64,
KonanTarget.TVOS_ARM64, KonanTarget.TVOS_X64 ->
AppleConfigurablesImpl(target, properties, baseDir) AppleConfigurablesImpl(target, properties, baseDir)
KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64, KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64,
KonanTarget.ANDROID_X86, KonanTarget.ANDROID_X64 -> KonanTarget.ANDROID_X86, KonanTarget.ANDROID_X64 ->
@@ -52,7 +54,6 @@ fun loadConfigurables(target: KonanTarget, properties: Properties, baseDir: Stri
KonanTarget.WASM32 -> KonanTarget.WASM32 ->
WasmConfigurablesImpl(target, properties, baseDir) WasmConfigurablesImpl(target, properties, baseDir)
KonanTarget.WATCHOS_ARM64, KonanTarget.WATCHOS_ARM32, KonanTarget.WATCHOS_X64, KonanTarget.WATCHOS_X86-> TODO("unimplemented: $target") KonanTarget.WATCHOS_ARM64, KonanTarget.WATCHOS_ARM32, KonanTarget.WATCHOS_X64, KonanTarget.WATCHOS_X86-> TODO("unimplemented: $target")
KonanTarget.TVOS_ARM64, KonanTarget.TVOS_X64 -> TODO("unimplemented: $target")
is KonanTarget.ZEPHYR -> is KonanTarget.ZEPHYR ->
ZephyrConfigurablesImpl(target, properties, baseDir) ZephyrConfigurablesImpl(target, properties, baseDir)
} }
@@ -58,16 +58,4 @@ abstract class KonanPropertiesLoader(override val target: KonanTarget,
private val dependencyProcessor by lazy { private val dependencyProcessor by lazy {
baseDir?.let { DependencyProcessor(java.io.File(it), this) } baseDir?.let { DependencyProcessor(java.io.File(it), this) }
} }
} }
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).
}
@@ -145,20 +145,28 @@ open class MacOSBasedLinker(targetProperties: AppleConfigurables)
private val strip = "$absoluteTargetToolchain/usr/bin/strip" private val strip = "$absoluteTargetToolchain/usr/bin/strip"
private val dsymutil = "$absoluteLlvmHome/bin/llvm-dsymutil" private val dsymutil = "$absoluteLlvmHome/bin/llvm-dsymutil"
private fun provideCompilerRtLibrary(libraryName: String): String? { private val KonanTarget.isSimulator: Boolean
val suffix = if (libraryName.isNotEmpty() && target == KonanTarget.IOS_X64) { get() = this == KonanTarget.TVOS_X64 || this == KonanTarget.IOS_X64 ||
"iossim" this == KonanTarget.WATCHOS_X86 || this == KonanTarget.WATCHOS_X64
} else {
when (val family = configurables.target.family) {
Family.OSX -> "osx"
Family.IOS -> "ios"
else -> error("Family $family is unsupported")
}
}
val dir = File("$absoluteTargetToolchain/usr/lib/clang/").listFiles.firstOrNull()?.absolutePath
val mangledName = if (libraryName.isEmpty()) "" else "${libraryName}_"
return if (dir != null) "$dir/lib/darwin/libclang_rt.$mangledName$suffix.a" else null private fun provideCompilerRtLibrary(libraryName: String): String? {
val prefix = when (target.family) {
Family.IOS -> "ios"
Family.WATCHOS -> "watchos"
Family.TVOS -> "tvos"
Family.OSX -> "osx"
else -> error("Target $target is unsupported")
}
val suffix = if (libraryName.isNotEmpty() && target.isSimulator) {
"sim"
} else {
""
}
val dir = File("$absoluteTargetToolchain/usr/lib/clang/").listFiles.firstOrNull()?.absolutePath
val mangledLibraryName = if (libraryName.isEmpty()) "" else "${libraryName}_"
return if (dir != null) "$dir/lib/darwin/libclang_rt.$mangledLibraryName$prefix$suffix.a" else null
} }
private val compilerRtLibrary: String? by lazy { private val compilerRtLibrary: String? by lazy {
@@ -222,7 +230,9 @@ open class MacOSBasedLinker(targetProperties: AppleConfigurables)
private fun rpath(dynamic: Boolean): List<String> = listOfNotNull( private fun rpath(dynamic: Boolean): List<String> = listOfNotNull(
when (target.family) { when (target.family) {
Family.OSX -> "@executable_path/../Frameworks" Family.OSX -> "@executable_path/../Frameworks"
Family.IOS -> "@executable_path/Frameworks" Family.IOS,
Family.WATCHOS,
Family.TVOS -> "@executable_path/Frameworks"
else -> error(target) else -> error(target)
}, },
"@loader_path/Frameworks".takeIf { dynamic } "@loader_path/Frameworks".takeIf { dynamic }
@@ -437,7 +447,9 @@ fun linker(configurables: Configurables): LinkerFlags =
LinuxBasedLinker(configurables as LinuxConfigurables) LinuxBasedLinker(configurables as LinuxConfigurables)
KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 -> KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 ->
LinuxBasedLinker(configurables as LinuxMIPSConfigurables) LinuxBasedLinker(configurables as LinuxMIPSConfigurables)
KonanTarget.MACOS_X64, KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64, KonanTarget.IOS_X64 -> KonanTarget.MACOS_X64,
KonanTarget.TVOS_X64, KonanTarget.TVOS_ARM64,
KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64, KonanTarget.IOS_X64 ->
MacOSBasedLinker(configurables as AppleConfigurables) MacOSBasedLinker(configurables as AppleConfigurables)
KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64, KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64,
KonanTarget.ANDROID_X86, KonanTarget.ANDROID_X64 -> KonanTarget.ANDROID_X86, KonanTarget.ANDROID_X64 ->
@@ -450,8 +462,6 @@ fun linker(configurables: Configurables): LinkerFlags =
KonanTarget.WATCHOS_ARM32 -> TODO("implement me") KonanTarget.WATCHOS_ARM32 -> TODO("implement me")
KonanTarget.WATCHOS_X64 -> TODO("implement me") KonanTarget.WATCHOS_X64 -> TODO("implement me")
KonanTarget.WATCHOS_X86 -> TODO("implement me") KonanTarget.WATCHOS_X86 -> TODO("implement me")
KonanTarget.TVOS_ARM64 -> TODO("implement me")
KonanTarget.TVOS_X64 -> TODO("implement me")
is KonanTarget.ZEPHYR -> is KonanTarget.ZEPHYR ->
ZephyrLinker(configurables as ZephyrConfigurables) ZephyrLinker(configurables as ZephyrConfigurables)
} }
@@ -50,7 +50,7 @@ class PlatformManager(distribution: Distribution = Distribution(), experimental:
*/ */
val filteredOutEnabledButNotSupported val filteredOutEnabledButNotSupported
get() = enabled.filterNot { it == KonanTarget.WATCHOS_X64 || get() = enabled.filterNot { it == KonanTarget.WATCHOS_X64 ||
it == KonanTarget.WATCHOS_X86|| it == KonanTarget.WATCHOS_ARM64 || it == KonanTarget.WATCHOS_ARM32 || it == KonanTarget.WATCHOS_X86|| it == KonanTarget.WATCHOS_ARM64 || it == KonanTarget.WATCHOS_ARM32
it == KonanTarget.TVOS_X64 || it == KonanTarget.TVOS_ARM64} }
} }
@@ -25,8 +25,11 @@ interface Xcode {
val iphoneosSdk: String val iphoneosSdk: String
val iphonesimulatorSdk: String val iphonesimulatorSdk: String
val version: String val version: String
val appletvosSdk: String
val appletvsimulatorSdk: String
// Xcode.app/Contents/Developer/usr // Xcode.app/Contents/Developer/usr
val additionalTools: String val additionalTools: String
val simulatorRuntimes: String
companion object { companion object {
val current: Xcode by lazy { val current: Xcode by lazy {
@@ -47,9 +50,14 @@ private object CurrentXcode : Xcode {
File(bitcodeBuildToolPath).parentFile.parentFile.absolutePath File(bitcodeBuildToolPath).parentFile.parentFile.absolutePath
} }
override val simulatorRuntimes: String by lazy {
Command("/usr/bin/xcrun", "simctl", "list", "runtimes", "-j").getOutputLines().joinToString(separator = "\n")
}
override val macosxSdk by lazy { getSdkPath("macosx") } override val macosxSdk by lazy { getSdkPath("macosx") }
override val iphoneosSdk by lazy { getSdkPath("iphoneos") } override val iphoneosSdk by lazy { getSdkPath("iphoneos") }
override val iphonesimulatorSdk by lazy { getSdkPath("iphonesimulator") } override val iphonesimulatorSdk by lazy { getSdkPath("iphonesimulator") }
override val appletvosSdk by lazy { getSdkPath("appletvos") }
override val appletvsimulatorSdk by lazy { getSdkPath("appletvsimulator") }
override val version by lazy { override val version by lazy {
xcrun("xcodebuild", "-version") xcrun("xcodebuild", "-version")
@@ -54,7 +54,7 @@ enum class OutputKind(
false false
) { ) {
override fun availableFor(target: KonanTarget) = override fun availableFor(target: KonanTarget) =
target.family == Family.OSX || target.family == Family.IOS target.family.isAppleFamily
}, },
DYNAMIC( DYNAMIC(
CompilerOutputKind.DYNAMIC, CompilerOutputKind.DYNAMIC,
@@ -119,7 +119,7 @@ open class KonanFramework(name: String,
get() = project.konanBinBaseDir get() = project.konanBinBaseDir
override fun targetIsSupported(target: KonanTarget): Boolean = override fun targetIsSupported(target: KonanTarget): Boolean =
target.family == Family.OSX || target.family == Family.IOS target.family.isAppleFamily
} }
open class KonanLibrary(name: String, open class KonanLibrary(name: String,
+3 -1
View File
@@ -2,10 +2,12 @@
# "brew install coreutils" for grealpath. # "brew install coreutils" for grealpath.
KONAN_TOOLCHAIN_VERSION=9 KONAN_TOOLCHAIN_VERSION=9
SDKS="macosx iphoneos iphonesimulator" SDKS="macosx iphoneos iphonesimulator appletvos appletvsimulator"
TARBALL_macosx=target-sysroot-$KONAN_TOOLCHAIN_VERSION-macos_x64 TARBALL_macosx=target-sysroot-$KONAN_TOOLCHAIN_VERSION-macos_x64
TARBALL_iphoneos=target-sysroot-$KONAN_TOOLCHAIN_VERSION-ios_arm64 TARBALL_iphoneos=target-sysroot-$KONAN_TOOLCHAIN_VERSION-ios_arm64
TARBALL_iphonesimulator=target-sysroot-$KONAN_TOOLCHAIN_VERSION-ios_x64 TARBALL_iphonesimulator=target-sysroot-$KONAN_TOOLCHAIN_VERSION-ios_x64
TARBALL_appletvos=target-sysroot-$KONAN_TOOLCHAIN_VERSION-tvos_arm64
TARBALL_appletvsimulator=target-sysroot-$KONAN_TOOLCHAIN_VERSION-tvos_x64
TARBALL_watchos=target-sysroot-$KONAN_TOOLCHAIN_VERSION-watchos_arm32 TARBALL_watchos=target-sysroot-$KONAN_TOOLCHAIN_VERSION-watchos_arm32
TARBALL_watchsimulator=target-sysroot-$KONAN_TOOLCHAIN_VERSION-watchos_x64 TARBALL_watchsimulator=target-sysroot-$KONAN_TOOLCHAIN_VERSION-watchos_x64
TARBALL_xcode=target-toolchain-$KONAN_TOOLCHAIN_VERSION-macos_x64 TARBALL_xcode=target-toolchain-$KONAN_TOOLCHAIN_VERSION-macos_x64