Skip to content

Commit

Permalink
[Release Tooling] Add functionality to build dynamic frameworks (fire…
Browse files Browse the repository at this point in the history
  • Loading branch information
ncooke3 authored May 7, 2024
1 parent e1e1b93 commit b414bfc
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 68 deletions.
42 changes: 29 additions & 13 deletions .github/workflows/zip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ jobs:
run: |
mkdir -p release_zip_dir
sh -x scripts/build_zip.sh release_zip_dir \
"${{ github.event.inputs.custom_spec_repos || 'https://github.com/firebase/SpecsStaging.git' }}"
"${{ github.event.inputs.custom_spec_repos || 'https://github.com/firebase/SpecsStaging.git' }}" \
build-release \
static
- uses: actions/upload-artifact@v4
with:
name: Firebase-release-zip-zip
Expand All @@ -68,6 +70,9 @@ jobs:
# Don't run on private repo.
if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
needs: build
strategy:
matrix:
linking_type: [static, dynamic]
runs-on: macos-14
steps:
- uses: actions/checkout@v4
Expand All @@ -84,10 +89,11 @@ jobs:
mkdir -p zip_output_dir
sh -x scripts/build_zip.sh \
zip_output_dir "${{ github.event.inputs.custom_spec_repos || 'https://github.com/firebase/SpecsStaging.git,https://github.com/firebase/SpecsDev.git' }}" \
build-head
build-head \
${{ matrix.linking_type }}
- uses: actions/upload-artifact@v4
with:
name: Firebase-actions-dir
name: ${{ matrix.linking_type == 'static' && 'Firebase-actions-dir' || 'Firebase-actions-dir-dynamic' }}
# Zip the entire output directory since the builder adds subdirectories we don't know the
# name of.
path: zip_output_dir
Expand All @@ -103,6 +109,7 @@ jobs:
strategy:
matrix:
os: [macos-13, macos-14]
artifact: [Firebase-actions-dir, Firebase-actions-dir-dynamic]
include:
- os: macos-13
xcode: Xcode_15.2
Expand All @@ -114,7 +121,7 @@ jobs:
- name: Get framework dir
uses: actions/download-artifact@v4
with:
name: Firebase-actions-dir
name: ${{ matrix.artifact }}
- uses: ruby/setup-ruby@v1
- name: Setup Bundler
run: ./scripts/setup_bundler.sh
Expand Down Expand Up @@ -164,6 +171,7 @@ jobs:
strategy:
matrix:
os: [macos-13, macos-14]
artifact: [Firebase-actions-dir, Firebase-actions-dir-dynamic]
include:
- os: macos-13
xcode: Xcode_15.2
Expand All @@ -175,7 +183,7 @@ jobs:
- name: Get framework dir
uses: actions/download-artifact@v4
with:
name: Firebase-actions-dir
name: ${{ matrix.artifact }}
- uses: ruby/setup-ruby@v1
- name: Setup Bundler
run: ./scripts/setup_bundler.sh
Expand Down Expand Up @@ -217,6 +225,7 @@ jobs:
strategy:
matrix:
os: [macos-13, macos-14]
artifact: [Firebase-actions-dir, Firebase-actions-dir-dynamic]
include:
- os: macos-13
xcode: Xcode_15.2
Expand All @@ -228,7 +237,7 @@ jobs:
- name: Get framework dir
uses: actions/download-artifact@v4
with:
name: Firebase-actions-dir
name: ${{ matrix.artifact }}
- uses: ruby/setup-ruby@v1
- name: Setup Bundler
run: ./scripts/setup_bundler.sh
Expand Down Expand Up @@ -268,6 +277,7 @@ jobs:
strategy:
matrix:
os: [macos-13, macos-14]
artifact: [Firebase-actions-dir, Firebase-actions-dir-dynamic]
include:
- os: macos-13
xcode: Xcode_15.2
Expand All @@ -279,7 +289,7 @@ jobs:
- name: Get framework dir
uses: actions/download-artifact@v4
with:
name: Firebase-actions-dir
name: ${{ matrix.artifact }}
- uses: ruby/setup-ruby@v1
- name: Setup Bundler
run: ./scripts/setup_bundler.sh
Expand Down Expand Up @@ -343,6 +353,7 @@ jobs:
matrix:
os: [macos-13]
xcode: [Xcode_15.2]
artifact: [Firebase-actions-dir, Firebase-actions-dir-dynamic]
# TODO: Building FirebaseUI fails on Xcode 15 because it needs to sign the resources.
# - os: macos-13
# xcode: Xcode_15.2
Expand All @@ -352,7 +363,7 @@ jobs:
- name: Get framework dir
uses: actions/download-artifact@v4
with:
name: Firebase-actions-dir
name: ${{ matrix.artifact }}
- uses: ruby/setup-ruby@v1
- name: Setup Bundler
run: ./scripts/setup_bundler.sh
Expand Down Expand Up @@ -396,6 +407,7 @@ jobs:
strategy:
matrix:
os: [macos-13, macos-14]
artifact: [Firebase-actions-dir, Firebase-actions-dir-dynamic]
include:
- os: macos-13
xcode: Xcode_15.2
Expand All @@ -407,7 +419,7 @@ jobs:
- name: Get framework dir
uses: actions/download-artifact@v4
with:
name: Firebase-actions-dir
name: ${{ matrix.artifact }}
- uses: ruby/setup-ruby@v1
- name: Setup Bundler
run: ./scripts/setup_bundler.sh
Expand Down Expand Up @@ -456,14 +468,15 @@ jobs:
# matrix:
# # TODO: Building FirebaseUI fails on Xcode 15 because it needs to sign the resources.
# os: [macos-13]
# artifact: [Firebase-actions-dir, Firebase-actions-dir-dynamic]
# xcode: [Xcode_15.2]
# runs-on: ${{ matrix.os }}
# steps:
# - uses: actions/checkout@v4
# - name: Get framework dir
# uses: actions/download-artifact@v4
# with:
# name: Firebase-actions-dir
# name: ${{ matrix.artifact }}
# - uses: ruby/setup-ruby@v1
# - name: Setup Bundler
# run: ./scripts/setup_bundler.sh
Expand Down Expand Up @@ -536,6 +549,7 @@ jobs:
strategy:
matrix:
os: [macos-13, macos-14]
artifact: [Firebase-actions-dir, Firebase-actions-dir-dynamic]
include:
- os: macos-13
xcode: Xcode_15.2
Expand All @@ -547,7 +561,7 @@ jobs:
- name: Get framework dir
uses: actions/download-artifact@v4
with:
name: Firebase-actions-dir
name: ${{ matrix.artifact }}
- uses: ruby/setup-ruby@v1
- name: Setup Bundler
run: ./scripts/setup_bundler.sh
Expand Down Expand Up @@ -592,6 +606,7 @@ jobs:
strategy:
matrix:
os: [macos-13, macos-14]
artifact: [Firebase-actions-dir, Firebase-actions-dir-dynamic]
include:
- os: macos-13
xcode: Xcode_15.2
Expand All @@ -603,7 +618,7 @@ jobs:
- name: Get framework dir
uses: actions/download-artifact@v4
with:
name: Firebase-actions-dir
name: ${{ matrix.artifact }}
- uses: ruby/setup-ruby@v1
- name: Setup Bundler
run: ./scripts/setup_bundler.sh
Expand Down Expand Up @@ -647,6 +662,7 @@ jobs:
strategy:
matrix:
os: [macos-13, macos-14]
artifact: [Firebase-actions-dir, Firebase-actions-dir-dynamic]
include:
- os: macos-13
xcode: Xcode_15.2
Expand All @@ -658,7 +674,7 @@ jobs:
- name: Get framework dir
uses: actions/download-artifact@v4
with:
name: Firebase-actions-dir
name: ${{ matrix.artifact }}
- uses: ruby/setup-ruby@v1
- name: Setup Bundler
run: ./scripts/setup_bundler.sh
Expand Down
46 changes: 4 additions & 42 deletions ReleaseTooling/Sources/ZipBuilder/FrameworkBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -306,18 +306,14 @@ struct FrameworkBuilder {
logsDir: URL) -> [URL] {
// xcframework doesn't lipo things together but accepts fat frameworks for one target.
// We group architectures here to deal with this fact.
var thinFrameworks = [URL]()
for targetPlatform in TargetPlatform.allCases {
let buildDir = projectDir.appendingPathComponent(targetPlatform.buildName)
let slicedFramework = buildSlicedFramework(
withName: FrameworkBuilder.frameworkBuildName(framework),
return targetPlatforms.map { targetPlatform in
buildSlicedFramework(
withName: framework,
targetPlatform: targetPlatform,
buildDir: buildDir,
buildDir: projectDir.appendingPathComponent(targetPlatform.buildName),
logRoot: logsDir
)
thinFrameworks.append(slicedFramework)
}
return thinFrameworks
}

/// Compiles the specified framework in a temporary directory and writes the build logs to file.
Expand Down Expand Up @@ -565,17 +561,6 @@ struct FrameworkBuilder {
"\(framework): \(error)")
}

// CocoaPods creates a `_CodeSignature` directory. Delete it.
// Note that the build only produces a `_CodeSignature` directory for
// macOS and macCatalyst, but we try to delete it for other platforms
// just in case it were to appear.
let codeSignatureDir = platformFrameworkDir
.appendingPathComponent(
platform == .catalyst || platform == .macOS ? "Versions/A/" : ""
)
.appendingPathComponent("_CodeSignature")
try? fileManager.removeItem(at: codeSignatureDir)

// The minimum OS version is set to 100.0 to work around b/327020913.
// TODO(ncooke3): Revert this logic once b/327020913 is fixed.
// TODO(ncooke3): Does this need to happen on macOS?
Expand Down Expand Up @@ -604,23 +589,6 @@ struct FrameworkBuilder {
)
}

// The macOS slice's `PrivateHeaders` directory may have a
// `PrivateHeaders` file in it that symbolically links to nowhere. Delete
// it here to avoid putting it in the zip or crashing the Carthage hash
// generation. Because this will throw an error for cases where the file
// does not exist, the error is ignored.
let privateHeadersDir = platformFrameworkDir.appendingPathComponent("PrivateHeaders")
if fileManager.directoryExists(at: privateHeadersDir.resolvingSymlinksInPath()) {
try? fileManager
.removeItem(at: privateHeadersDir.resolvingSymlinksInPath()
.appendingPathComponent("PrivateHeaders"))
} else {
try? fileManager.removeItem(at: privateHeadersDir)
}
let headersDir = platformFrameworkDir.appendingPathComponent("Headers")
.resolvingSymlinksInPath()
try? fileManager.removeItem(at: headersDir.appendingPathComponent("Headers"))

// Move privacy manifest containing resource bundles into the framework.
let resourceDir = platformFrameworkDir
.appendingPathComponent(
Expand All @@ -638,12 +606,6 @@ struct FrameworkBuilder {
// Bundles are moved rather than copied to prevent them from being
// packaged in a `Resources` directory at the root of the xcframework.
.forEach {
// Delete `gRPCCertificates-Cpp.bundle` since it is not needed (#9184).
guard $0.lastPathComponent != "gRPCCertificates-Cpp.bundle" else {
try fileManager.removeItem(at: $0)
return
}

try fileManager.moveItem(
at: $0,
to: resourceDir.appendingPathComponent($0.lastPathComponent)
Expand Down
52 changes: 50 additions & 2 deletions ReleaseTooling/Sources/ZipBuilder/ZipBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ struct ZipBuilder {
for groupedFramework in groupedFrameworks {
let name = groupedFramework.key
let xcframework = FrameworkBuilder.makeXCFramework(withName: name,
frameworks: groupedFramework.value,
frameworks: postProcessFrameworks(groupedFramework
.value),
xcframeworksDir: xcframeworksDir,
resourceContents: resources[name])
xcframeworks[name] = [xcframework]
Expand All @@ -299,13 +300,60 @@ struct ZipBuilder {

let carthageGoogleUtilitiesXcframework = FrameworkBuilder.makeXCFramework(
withName: "GoogleUtilities",
frameworks: carthageGoogleUtilitiesFrameworks,
frameworks: postProcessFrameworks(carthageGoogleUtilitiesFrameworks),
xcframeworksDir: xcframeworksCarthageDir,
resourceContents: nil
)
return (podsBuilt, xcframeworks, carthageGoogleUtilitiesXcframework)
}

func postProcessFrameworks(_ frameworks: [URL]) -> [URL] {
for framework in frameworks {
// CocoaPods creates a `_CodeSignature` directory. Delete it.
// Note that the build only produces a `_CodeSignature` directory for
// macOS and macCatalyst (`Versions/A/`), but we try to delete it for
// other platforms just in case it were to appear.
for path in ["", "Versions/A/"] {
let codeSignatureDir = framework
.appendingPathComponent(path)
.appendingPathComponent("_CodeSignature")
.resolvingSymlinksInPath()
try? FileManager.default.removeItem(at: codeSignatureDir)
}

// Delete `gRPCCertificates-Cpp.bundle` since it is not needed (#9184).
// Depending on the platform, it may be at the root of the framework or
// in a symlinked `Resources` directory (for macOS, macCatalyst). Attempt
// to delete at either patch for each framework.
for path in ["", "Resources"] {
let grpcCertsBundle = framework
.appendingPathComponent(path)
.appendingPathComponent("gRPCCertificates-Cpp.bundle")
.resolvingSymlinksInPath()
try? FileManager.default.removeItem(at: grpcCertsBundle)
}

// The macOS slice's `PrivateHeaders` directory may have a
// `PrivateHeaders` file in it that symbolically links to nowhere. Delete
// it here to avoid putting it in the zip or crashing the Carthage hash
// generation. Because this will throw an error for cases where the file
// does not exist, the error is ignored.
let privateHeadersDir = framework.appendingPathComponent("PrivateHeaders")
if !FileManager.default.directoryExists(at: privateHeadersDir.resolvingSymlinksInPath()) {
try? FileManager.default.removeItem(at: privateHeadersDir)
}

// The `Headers` and `PrivateHeaders` directories may contain a symlink
// of the same name. Delete it here to avoid putting it in the zip or
// crashing the Carthage hash generation.
for path in ["Headers", "PrivateHeaders"] {
let headersDir = framework.appendingPathComponent(path).resolvingSymlinksInPath()
try? FileManager.default.removeItem(at: headersDir.appendingPathComponent(path))
}
}
return frameworks
}

/// Try to build and package the contents of the Zip file. This will throw an error as soon as it
/// encounters an error, or will quit due to a fatal error with the appropriate log.
///
Expand Down
Loading

0 comments on commit b414bfc

Please sign in to comment.