[KT-47355] Support macOS targets in FatFramework task.
This commit is contained in:
committed by
Space
parent
09a72fd679
commit
d5164fbc86
+41
-6
@@ -7,12 +7,14 @@ package org.jetbrains.kotlin.gradle.native
|
||||
|
||||
import org.jetbrains.kotlin.gradle.*
|
||||
import org.jetbrains.kotlin.gradle.embedProject
|
||||
import org.jetbrains.kotlin.gradle.tasks.FrameworkLayout
|
||||
import org.jetbrains.kotlin.gradle.transformProjectWithPluginsDsl
|
||||
import org.jetbrains.kotlin.gradle.util.*
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.junit.Assume
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
@@ -71,10 +73,39 @@ class FatFrameworkIT : BaseGradleIT() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun smokeMacos() {
|
||||
with(transformProjectWithPluginsDsl("smoke", directoryPrefix = "native-fat-framework")) {
|
||||
|
||||
gradleBuildScript().modify {
|
||||
it.checkedReplace("iosArm32()", "")
|
||||
.checkedReplace("iosArm64()", "macosArm64()")
|
||||
.checkedReplace("iosX64()", "macosX64()")
|
||||
}
|
||||
|
||||
build("fat") {
|
||||
checkSmokeBuild(
|
||||
archs = listOf("x64", "arm64"),
|
||||
targetPrefix = "macos",
|
||||
expectedPlistPlatform = "MacOSX",
|
||||
true
|
||||
)
|
||||
|
||||
val binary = fileInWorkingDir("build/fat-framework/smoke.framework/Versions/A/smoke")
|
||||
with(runProcess(listOf("file", binary.absolutePath), projectDir)) {
|
||||
assertTrue(isSuccessful)
|
||||
assertTrue(output.contains("\\(for architecture x86_64\\):\\s+Mach-O 64-bit dynamically linked shared library x86_64".toRegex()))
|
||||
assertTrue(output.contains("\\(for architecture arm64\\):\\s+Mach-O 64-bit dynamically linked shared library arm64".toRegex()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun CompiledProject.checkSmokeBuild(
|
||||
archs: List<String>,
|
||||
targetPrefix: String,
|
||||
expectedPlistPlatform: String
|
||||
expectedPlistPlatform: String,
|
||||
isMacosFramework: Boolean = false
|
||||
) {
|
||||
assertSuccessful()
|
||||
val linkTasks = archs.map {
|
||||
@@ -89,17 +120,21 @@ class FatFrameworkIT : BaseGradleIT() {
|
||||
assertTasksExecuted(linkTasks)
|
||||
assertTasksExecuted(":fat")
|
||||
|
||||
assertFileExists("build/fat-framework/smoke.framework/smoke")
|
||||
assertFileExists("build/fat-framework/smoke.framework/Headers/smoke.h")
|
||||
assertFileExists("build/fat-framework/smoke.framework.dSYM/Contents/Resources/DWARF/smoke")
|
||||
val frameworkLayout = FrameworkLayout(fileInWorkingDir("build/fat-framework/smoke.framework"), isMacosFramework)
|
||||
|
||||
val headerContent = fileInWorkingDir("build/fat-framework/smoke.framework/Headers/smoke.h").readText()
|
||||
fun File.projectRelative() = relativeTo(File(workingDir, project.projectName)).path
|
||||
|
||||
assertFileExists(frameworkLayout.binary.projectRelative())
|
||||
assertFileExists(frameworkLayout.header.projectRelative())
|
||||
assertFileExists(frameworkLayout.dSYM.binary.projectRelative())
|
||||
|
||||
val headerContent = frameworkLayout.header.readText()
|
||||
assertTrue(
|
||||
headerContent.contains("+ (int32_t)foo __attribute__((swift_name(\"foo()\")));"),
|
||||
"Unexpected header content:\n$headerContent"
|
||||
)
|
||||
|
||||
val plistContent = fileInWorkingDir("build/fat-framework/smoke.framework/Info.plist")
|
||||
val plistContent = frameworkLayout.infoPlist
|
||||
.readLines()
|
||||
.joinToString(separator = "\n") { it.trim() }
|
||||
|
||||
|
||||
+33
-16
@@ -20,8 +20,11 @@ import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget.*
|
||||
import org.jetbrains.kotlin.konan.util.visibleName
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
class FrameworkDsymLayout(val rootDir: File) {
|
||||
init {
|
||||
@@ -41,27 +44,43 @@ class FrameworkDsymLayout(val rootDir: File) {
|
||||
fun exists() = rootDir.exists()
|
||||
}
|
||||
|
||||
class FrameworkLayout(val rootDir: File) {
|
||||
class FrameworkLayout(
|
||||
val rootDir: File,
|
||||
val isMacosFramework: Boolean
|
||||
) {
|
||||
init {
|
||||
require(rootDir.extension == "framework")
|
||||
}
|
||||
|
||||
private val frameworkName = rootDir.nameWithoutExtension
|
||||
private val macosVersionsDir = rootDir.resolve("Versions")
|
||||
private val macosADir = macosVersionsDir.resolve("A")
|
||||
private val macosResourcesDir = macosADir.resolve("Resources")
|
||||
private val contentDir = if (isMacosFramework) macosADir else rootDir
|
||||
|
||||
val headerDir = rootDir.resolve("Headers")
|
||||
val modulesDir = rootDir.resolve("Modules")
|
||||
val headerDir = contentDir.resolve("Headers")
|
||||
val modulesDir = contentDir.resolve("Modules")
|
||||
|
||||
val binary = rootDir.resolve(frameworkName)
|
||||
val binary = contentDir.resolve(frameworkName)
|
||||
val header = headerDir.resolve("$frameworkName.h")
|
||||
val moduleFile = modulesDir.resolve("module.modulemap")
|
||||
val infoPlist = rootDir.resolve("Info.plist")
|
||||
val infoPlist = (if (isMacosFramework) macosResourcesDir else rootDir).resolve("Info.plist")
|
||||
|
||||
val dSYM = FrameworkDsymLayout(rootDir.parentFile.resolve("$frameworkName.framework.dSYM"))
|
||||
|
||||
fun mkdirs() {
|
||||
rootDir.mkdirs()
|
||||
headerDir.mkdir()
|
||||
modulesDir.mkdir()
|
||||
headerDir.mkdirs()
|
||||
modulesDir.mkdirs()
|
||||
if (isMacosFramework) {
|
||||
macosResourcesDir.mkdirs()
|
||||
val root = rootDir.toPath()
|
||||
Files.createSymbolicLink(root.resolve("Headers"), headerDir.toPath())
|
||||
Files.createSymbolicLink(root.resolve("Modules"), modulesDir.toPath())
|
||||
Files.createSymbolicLink(root.resolve("Resources"), macosResourcesDir.toPath())
|
||||
Files.createSymbolicLink(root.resolve(frameworkName), binary.toPath())
|
||||
Files.createSymbolicLink(macosVersionsDir.toPath().resolve("Current"), macosADir.toPath())
|
||||
}
|
||||
}
|
||||
|
||||
fun exists() = rootDir.exists()
|
||||
@@ -83,7 +102,7 @@ class FrameworkDescriptor(
|
||||
}
|
||||
|
||||
val name = file.nameWithoutExtension
|
||||
val files = FrameworkLayout(file)
|
||||
val files = FrameworkLayout(file, target.family == Family.OSX)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,9 +143,6 @@ open class FatFrameworkTask : DefaultTask() {
|
||||
val fatFramework: File
|
||||
get() = destinationDir.resolve(fatFrameworkName + ".framework")
|
||||
|
||||
private val fatFrameworkLayout: FrameworkLayout
|
||||
get() = FrameworkLayout(fatFramework)
|
||||
|
||||
@get:PathSensitive(PathSensitivity.ABSOLUTE)
|
||||
@get:IgnoreEmptyDirectories
|
||||
@get:InputFiles
|
||||
@@ -212,6 +228,7 @@ open class FatFrameworkTask : DefaultTask() {
|
||||
|
||||
private val FrameworkDescriptor.plistPlatform: String
|
||||
get() = when (target) {
|
||||
MACOS_X64, MACOS_ARM64 -> "MacOSX"
|
||||
IOS_ARM32, IOS_ARM64, IOS_X64, IOS_SIMULATOR_ARM64 -> "iPhoneOS"
|
||||
TVOS_ARM64, TVOS_X64, TVOS_SIMULATOR_ARM64 -> "AppleTVOS"
|
||||
WATCHOS_ARM32, WATCHOS_ARM64, WATCHOS_X86, WATCHOS_X64, WATCHOS_SIMULATOR_ARM64 -> "WatchOS"
|
||||
@@ -358,7 +375,7 @@ open class FatFrameworkTask : DefaultTask() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun mergeDSYM() {
|
||||
private fun mergeDSYM(fatDsym: FrameworkDsymLayout) {
|
||||
val dsymInputs = archToFramework.mapValues { (_, framework) ->
|
||||
framework.files.dSYM
|
||||
}.filterValues {
|
||||
@@ -369,7 +386,6 @@ open class FatFrameworkTask : DefaultTask() {
|
||||
return
|
||||
}
|
||||
|
||||
val fatDsym = fatFrameworkLayout.dSYM
|
||||
fatDsym.mkdirs()
|
||||
|
||||
// Merge dSYM binary.
|
||||
@@ -386,21 +402,22 @@ open class FatFrameworkTask : DefaultTask() {
|
||||
|
||||
@TaskAction
|
||||
protected fun createFatFramework() {
|
||||
val outFramework = fatFrameworkLayout
|
||||
val outFramework = FrameworkLayout(fatFramework, getFatFrameworkFamily() == Family.OSX)
|
||||
|
||||
outFramework.mkdirs()
|
||||
mergeBinaries(outFramework.binary)
|
||||
mergeHeaders(outFramework.header)
|
||||
createModuleFile(outFramework.moduleFile, fatFrameworkName)
|
||||
mergePlists(outFramework.infoPlist, fatFrameworkName)
|
||||
mergeDSYM()
|
||||
mergeDSYM(outFramework.dSYM)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val supportedTargets = listOf(
|
||||
IOS_ARM32, IOS_ARM64, IOS_X64,
|
||||
WATCHOS_ARM32, WATCHOS_ARM64, WATCHOS_X86, WATCHOS_X64,
|
||||
TVOS_ARM64, TVOS_X64
|
||||
TVOS_ARM64, TVOS_X64,
|
||||
MACOS_X64, MACOS_ARM64
|
||||
)
|
||||
|
||||
fun isSupportedTarget(target: KotlinNativeTarget): Boolean {
|
||||
|
||||
Reference in New Issue
Block a user