func buildAndAssembleZip()

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)
  }