in ReleaseTooling/Sources/ZipBuilder/ZipBuilder.swift [166:308]
func buildAndAssembleZip(podsToInstall: [CocoaPodUtils.VersionedPod],
includeCarthage: Bool,
includeDependencies: Bool) ->
([String: CocoaPodUtils.PodInfo], [String: [URL]], URL?) {
// Remove CocoaPods cache so the build gets updates after a version is rebuilt during the
// release process. Always do this, since it can be the source of subtle failures on rebuilds.
CocoaPodUtils.cleanPodCache()
// We need to install all the pods in order to get every single framework that we'll need
// for the zip file. We can't install each one individually since some pods depend on different
// subspecs from the same pod (ex: GoogleUtilities, GoogleToolboxForMac, etc). All of the code
// wouldn't be included so we need to install all of the subspecs to catch the superset of all
// required frameworks, then use that as the source of frameworks to pull from when including
// the folders in each product directory.
let linkage: CocoaPodUtils.LinkageType = dynamicFrameworks ? .dynamic : .standardStatic
var groupedFrameworks: [String: [URL]] = [:]
var carthageCoreDiagnosticsFrameworks: [URL] = []
var podsBuilt: [String: CocoaPodUtils.PodInfo] = [:]
var xcframeworks: [String: [URL]] = [:]
var resources: [String: URL] = [:]
for platform in platforms {
let projectDir = FileManager.default.temporaryDirectory(withName: "project-" + platform.name)
CocoaPodUtils.podInstallPrepare(inProjectDir: projectDir, templateDir: paths.templateDir)
let platformPods = podsToInstall.filter { $0.platforms.contains(platform.name) }
CocoaPodUtils.installPods(platformPods,
inDir: projectDir,
platform: platform,
customSpecRepos: customSpecRepos,
localPodspecPath: paths.localPodspecPath,
linkage: linkage)
// Find out what pods were installed with the above commands.
let installedPods = CocoaPodUtils.installedPodsInfo(inProjectDir: projectDir,
localPodspecPath: paths.localPodspecPath)
// If module maps are needed for static frameworks, build them here to be available to copy
// into the generated frameworks.
if !dynamicFrameworks {
ModuleMapBuilder(customSpecRepos: customSpecRepos,
selectedPods: installedPods,
platform: platform,
paths: paths).build()
}
let podsToBuild = includeDependencies ? installedPods : installedPods.filter {
platformPods.map { $0.name.components(separatedBy: "/").first }.contains($0.key)
}
// Build in a sorted order to make the build deterministic and to avoid exposing random
// build order bugs.
// Also AppCheck must be built after other pods so that its restricted architecture
// selection does not restrict any of its dependencies.
var sortedPods = podsToBuild.keys.sorted()
sortedPods.removeAll(where: { value in
value == "FirebaseAppCheck"
})
sortedPods.append("FirebaseAppCheck")
for podName in sortedPods {
guard let podInfo = podsToBuild[podName] else {
continue
}
if podName == "Firebase" {
// Don't build the Firebase pod.
} else if podInfo.isSourcePod {
let builder = FrameworkBuilder(projectDir: projectDir,
targetPlatforms: platform.platformTargets,
dynamicFrameworks: dynamicFrameworks)
let (frameworks, resourceContents) =
builder.compileFrameworkAndResources(withName: podName,
logsOutputDir: paths.logsOutputDir,
setCarthage: false,
podInfo: podInfo)
groupedFrameworks[podName] = (groupedFrameworks[podName] ?? []) + frameworks
if includeCarthage, podName == "FirebaseCoreDiagnostics" {
let (cdFrameworks, _) = builder.compileFrameworkAndResources(withName: podName,
logsOutputDir: paths
.logsOutputDir,
setCarthage: true,
podInfo: podInfo)
carthageCoreDiagnosticsFrameworks += cdFrameworks
}
if resourceContents != nil {
resources[podName] = resourceContents
}
} else if podsBuilt[podName] == nil {
// Binary pods need to be collected once, since the platforms should already be merged.
let binaryFrameworks = collectBinaryFrameworks(fromPod: podName, podInfo: podInfo)
xcframeworks[podName] = binaryFrameworks
}
// Union all pods built across platforms.
// Be conservative and favor iOS if it exists - and workaround
// bug where Firebase.h doesn't get installed for tvOS and macOS.
// Fixed in #7284.
if podsBuilt[podName] == nil {
podsBuilt[podName] = podInfo
}
}
}
// Now consolidate the built frameworks for all platforms into a single xcframework.
let xcframeworksDir = FileManager.default.temporaryDirectory(withName: "xcframeworks")
do {
try FileManager.default.createDirectory(at: xcframeworksDir,
withIntermediateDirectories: false)
} catch {
fatalError("Could not create XCFrameworks directory: \(error)")
}
for groupedFramework in groupedFrameworks {
let name = groupedFramework.key
let xcframework = FrameworkBuilder.makeXCFramework(withName: name,
frameworks: groupedFramework.value,
xcframeworksDir: xcframeworksDir,
resourceContents: resources[name])
xcframeworks[name] = [xcframework]
}
for (framework, paths) in xcframeworks {
print("Frameworks for pod: \(framework) were compiled at \(paths)")
}
guard includeCarthage else {
// No Carthage build necessary, return now.
return (podsBuilt, xcframeworks, nil)
}
let xcframeworksCarthageDir = FileManager.default.temporaryDirectory(withName: "xcf-carthage")
do {
try FileManager.default.createDirectory(at: xcframeworksCarthageDir,
withIntermediateDirectories: false)
} catch {
fatalError("Could not create XCFrameworks Carthage directory: \(error)")
}
let carthageCoreDiagnosticsXcframework = FrameworkBuilder.makeXCFramework(
withName: "FirebaseCoreDiagnostics",
frameworks: carthageCoreDiagnosticsFrameworks,
xcframeworksDir: xcframeworksCarthageDir,
resourceContents: nil
)
return (podsBuilt, xcframeworks, carthageCoreDiagnosticsXcframework)
}