Custom name support for fat frameworks

#KT-30805
This commit is contained in:
Viacheslav Kormushkin
2021-06-18 06:28:01 +00:00
committed by Space
parent ce107d06d4
commit 0b6d2cd21a
2 changed files with 84 additions and 6 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.native
import org.jetbrains.kotlin.gradle.BaseGradleIT
import org.jetbrains.kotlin.gradle.GradleVersionRequired
import org.jetbrains.kotlin.gradle.transformProjectWithPluginsDsl
import org.jetbrains.kotlin.gradle.util.addBeforeSubstring
import org.jetbrains.kotlin.gradle.util.checkedReplace
import org.jetbrains.kotlin.gradle.util.modify
import org.jetbrains.kotlin.gradle.util.runProcess
@@ -146,6 +147,54 @@ class FatFrameworkIT : BaseGradleIT() {
}
}
@Test
fun testCustomName() {
with(transformProjectWithPluginsDsl("smoke", directoryPrefix = "native-fat-framework")) {
gradleBuildScript().modify {
it.addBeforeSubstring("baseName = \"custom\"\n","from(frameworksToMerge)")
}
build("fat") {
val binary = fileInWorkingDir("build/fat-framework/custom.framework/custom")
with(runProcess(listOf("otool", "-D", binary.absolutePath), project.projectDir)) {
assertSuccessful()
assertTrue { output.lines().any { it.contains("@rpath/custom.framework/custom") } }
}
}
}
}
@Test
fun testDifferentTypes() {
with(transformProjectWithPluginsDsl("smoke", directoryPrefix = "native-fat-framework")) {
gradleBuildScript().modify {
it.checkedReplace("iosArm32()", "iosArm32{binaries.framework {isStatic = true}}")
.checkedReplace("iosArm64()", "iosArm64{binaries.framework {isStatic = false}}")
.checkedReplace("iosX64()", "iosX64{binaries.framework {isStatic = false}}")
.addBeforeSubstring("//", "binaries.framework(listOf(DEBUG))")
}
build("fat") {
assertFailed()
assertContains("All input frameworks must be either static or dynamic")
}
}
}
@Test
fun testAllStatic() {
with(transformProjectWithPluginsDsl("smoke", directoryPrefix = "native-fat-framework")) {
gradleBuildScript().modify {
it.checkedReplace("iosArm32()", "iosArm32{binaries.framework {isStatic = true}}")
.checkedReplace("iosArm64()", "iosArm64{binaries.framework {isStatic = true}}")
.checkedReplace("iosX64()", "iosX64{binaries.framework {isStatic = true}}")
.addBeforeSubstring("//", "binaries.framework(listOf(DEBUG))")
}
build("fat") {
assertSuccessful()
}
}
}
companion object {
@BeforeClass
@JvmStatic
@@ -134,9 +134,9 @@ open class FatFrameworkTask : DefaultTask() {
* Adds the specified frameworks in this fat framework.
*/
fun from(frameworks: Iterable<Framework>) {
frameworks.forEach {
val arch = it.konanTarget.architecture
val family = it.konanTarget.family
frameworks.forEach { framework ->
val arch = framework.konanTarget.architecture
val family = framework.konanTarget.family
val fatFrameworkFamily = getFatFrameworkFamily()
require(fatFrameworkFamily == null || family == fatFrameworkFamily) {
"Cannot add a binary with platform family '${family.visibleName}' to the fat framework:\n" +
@@ -149,8 +149,20 @@ open class FatFrameworkTask : DefaultTask() {
"This fat framework already has a binary for architecture `${arch.name.toLowerCase()}` " +
"(${alreadyAdded.name} for target `${alreadyAdded.target.name}`)"
}
archToFramework[arch] = it
dependsOn(it.linkTask)
require(archToFramework.all { it.value.isStatic == framework.isStatic }) {
fun Framework.staticOrDynamic(): String = if (isStatic) "static" else "dynamic"
buildString {
append("Cannot create a fat framework from:\n")
archToFramework.forEach { append("${it.value.baseName} - ${it.key.name.toLowerCase()} - ${it.value.staticOrDynamic()}\n") }
append("${framework.baseName} - ${arch.name.toLowerCase()} - ${framework.staticOrDynamic()}\n")
append("All input frameworks must be either static or dynamic")
}
}
archToFramework[arch] = framework
dependsOn(framework.linkTask)
}
}
@@ -218,9 +230,26 @@ open class FatFrameworkTask : DefaultTask() {
)
}
private fun mergeBinaries(outputFile: File) =
private fun runInstallNameTool(file: File, frameworkName: String) {
project.exec { exec ->
exec.executable = "install_name_tool"
exec.args = listOf(
"-id",
"@rpath/${frameworkName}.framework/${frameworkName}",
file.absolutePath
)
}
}
private fun mergeBinaries(outputFile: File) {
runLipo(archToFramework.values.map { it.files.binary }, outputFile)
if (archToFramework.values.any{ it.isStatic.not() && it.baseName != fatFrameworkName }) {
runInstallNameTool(outputFile, fatFrameworkName)
}
}
private fun mergeHeaders(outputFile: File) = outputFile.writer().use { writer ->
val headerContents = archToFramework.mapValues { (_, framework) ->