Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@benasher44
Last active April 30, 2019 04:23
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save benasher44/32f602b9d5ec596ceaa3c9d190b14fc9 to your computer and use it in GitHub Desktop.
Save benasher44/32f602b9d5ec596ceaa3c9d190b14fc9 to your computer and use it in GitHub Desktop.
iOS Gradle Utilities for Generating Fat Frameworks and dSYMs
afterEvaluate {
// Create tasks for creating fat frameworks and fat dsyms for sim and device
def binaryKinds = [
// config, sim task, device task
new Tuple('Debug', linkDebugFrameworkIosSim, linkDebugFrameworkIosDevice),
new Tuple('Release', linkReleaseFrameworkIosSim, linkReleaseFrameworkIosDevice),
]
def libName = rootProject.name
def binaryOutputs = [
// binary path, bundle name, task suffix
new Tuple("Contents/Resources/DWARF/$libName", "${libName}.framework.dSYM", 'DSYM'),
new Tuple(libName, "${libName}.framework", "Framework")
]
for (kind in binaryKinds) {
def (config, sim, device) = kind
def defaultOutputDir = "$buildDir/bin/ios${config}Fat"
for (outputInfo in binaryOutputs) {
def (binaryPath, bundleName, taskSuffix) = outputInfo
task("createIos${config}Fat${taskSuffix}", type: Exec, dependsOn: [sim, device]) {
// put together final path
def finalContainerParentDir = System.getenv('PG_POD_FRAMEWORK_DIR') ?: defaultOutputDir
def finalContainerPath = "$finalContainerParentDir/$bundleName"
def finalOutputPath = "$finalContainerPath/$binaryPath"
// gather initial paths
def simContainerParentDir = sim.outputFile.get().parent
def deviceContainerParentDir = device.outputFile.get().parent
doFirst {
mkdir new File(finalOutputPath).parent
}
executable 'lipo'
args = [
'-create',
'-arch', 'arm64', "$deviceContainerParentDir/$bundleName/$binaryPath",
'-arch', 'x86_64', "$simContainerParentDir/$bundleName/$binaryPath",
'-output', finalOutputPath
]
doLast {
// copy other framework bits like info plist and headers
def initialContainer = "$deviceContainerParentDir/$bundleName"
copy {
from(initialContainer) {
// don't copy the thin binary, since we have a fat one already
exclude binaryPath
}
into finalContainerPath
}
// clean plist (only works for frameworks)
def plistPath = "$finalContainerPath/Info.plist"
if (new File(plistPath).exists()) {
exec {
executable '/usr/libexec/PlistBuddy'
args = ['-c', 'Delete :UIRequiredDeviceCapabilities', plistPath]
ignoreExitValue = true
}
}
// add the [system] attribute to the module map to silence warnings
def moduleMapPath = "$finalContainerPath/Modules/module.modulemap"
if (new File(moduleMapPath).exists()) {
exec {
executable 'sed'
args = ['-i', '.bak', '1 s/{/\\[system\\] {/', moduleMapPath]
}
delete "${moduleMapPath}.bak"
}
}
}
}
// Create the tasks that will call the framework and dsym tasks
def dependencies = binaryOutputs.collect { "createIos${config}Fat${it.last()}" }
task("createIos${config}Artifacts", dependsOn: dependencies, group: "iOS"))
}
// disable release dSYM task until https://github.com/JetBrains/kotlin-native/issues/2422 is fixed
createIosReleaseFatDSYM.enabled = false
}
@benasher44
Copy link
Author

benasher44 commented Jan 10, 2019

Here are the assumptions/inputs that this relies on:

  • Release and debug iOS link tasks called linkDebugFrameworkIosSim, linkDebugFrameworkIosDevice, linkReleaseFrameworkIosSim, and linkReleaseFrameworkIosDevice.
  • An env var that Xcode would define in its build phase for the output directory: PG_POD_FRAMEWORK_DIR (PG for PlanGrid; rename as needed :))

@benasher44
Copy link
Author

benasher44 commented Jan 10, 2019

This creates the following tasks in our build setup:

  • createIosReleaseFatFramework: creates release config fat framework
  • createIosDebugFatFramework: creates debug config fat framework
  • createIosReleaseFatDSYM: creates debug config fat dSYM
  • createIosDebugFatDSYM: creates release config fat dSYM
  • createIosReleaseArtifacts: calls the subtasks to create the release fat framework and dsym
  • createIosDebugArtifacts: calls the subtasks to create the debug fat framework and dsym

@benasher44
Copy link
Author

createIosReleaseArtifacts will fail until JetBrains/kotlin-native#2422 is fixed. Once that's fixed, this might need to be adjusted to skip the dSYM step for debug builds (might not be necessary).

@benasher44
Copy link
Author

This should work with Kotlin 1.3.20, if you use the new binaries dsl:

binaries {
    framework {
        baseName = rootProject.name
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment