-
Notifications
You must be signed in to change notification settings - Fork 2.3k
feat(ios): add SPM dependency resolution support alongside CocoaPods #8933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jsnavarroc
wants to merge
59
commits into
invertase:main
Choose a base branch
from
jsnavarroc:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
59 commits
Select commit
Hold shift + click to select a range
f64c9b0
feat(ios): add SPM dependency resolution support alongside CocoaPods
jsnavarroc fea0c7d
fix(analytics): use FirebaseAnalyticsCore SPM product when WithoutAdI…
jsnavarroc 0daad30
fix(app): add FirebaseInstallations as explicit SPM product in RNFBApp
jsnavarroc 949f719
fix(ios): address PR review feedback — revert spacing, add Expo docs,…
jsnavarroc ea30238
fix(ios): address Cursor Bugbot review findings on PR #8933
jsnavarroc c9ff00f
fix: harden RNFirebaseDisableSPM boolean check
russellwheatley 38ef2a0
docs: bump ios sdk version, list installations as dep installed to fi…
russellwheatley aa69cf6
docs: a specific, subtle tvOS bug and how to work around it
russellwheatley 4db4cfc
fix: missing SPM import missing header files
russellwheatley 3237fac
fix: import Swift header files when building via SPM
russellwheatley d3ce4f7
chore: ignore Package.Resolved
russellwheatley 15434a2
Podfile.lock
russellwheatley 5a2465a
docs: okf-bundle doc update
russellwheatley 5a85540
fix(ios): delegate Swift-only SPM Firebase calls through plain ObjC h…
russellwheatley fca9dcc
fix: storage needs method file due to upstream pure swift implementation
russellwheatley 6458e71
fix: crashlytics needs a method file to compile via SPM, upstream pur…
russellwheatley 549a640
fix: auth needs a method file to compile via SPM, upstream pure Swift
russellwheatley 52c23e1
fix: explicitly declare Photos framework on packages that import PHAs…
russellwheatley 85c0c44
chore: format + add words to spellcheck
russellwheatley 0455439
test(ios): try -ObjC linker flag to fix release+spm launch failure
russellwheatley 040a922
chore: ios diagnostics
russellwheatley 778dd7e
fix(ios): embed Firebase SPM package frameworks
russellwheatley 6ecdee0
docs(okf): record Firebase SPM embed phase
russellwheatley c6b91cd
fix(ios): auto-embed Firebase SPM frameworks without Podfile changes
russellwheatley 19db507
test(ci, ios): validate real device Release archives, not just simula…
russellwheatley dc7add8
docs(ios-spm): register SPM doc in site navigation and fix mdx lint
russellwheatley 2a60066
docs: follow up to register SPM doc in site navigation and fix mdx lint
russellwheatley 18c897d
docs(ios-spm): reframe SPM rationale around CocoaPods specs read-only…
russellwheatley 7d9a6dc
ci(ios): drop resolved storage predicates from simulator log stream
russellwheatley f78d45d
fix(analytics, ios): enable GoogleAdsOnDeviceConversion under SPM
russellwheatley e860a96
docs: clean up. ios-spm docs for user are leaner as they care about w…
russellwheatley 9978256
chore: fix linting
russellwheatley eac7a60
fix(ios): resolve SPM archive and formatting CI failures
russellwheatley 9fd32e9
fix(ios): link FirebaseCore in SPM test builds
russellwheatley cbc4adc
revert: remove CI fixes that changed consumer integration
russellwheatley dbcdb29
style(ios): apply clang-format to modified Objective-C files
russellwheatley 3e50588
fix(ios): resolve SPM archive duplicate-framework and missing-embed f…
russellwheatley eb77cee
fix(ios): remove stale app-target FirebaseCore SPM link when SPM disa…
russellwheatley 234cbf4
fix(ios): remove duplicate signature files for all resolved SPM binar…
russellwheatley 91b3640
chore: testing project.pbxproj via spm script
russellwheatley 859d1ed
docs: archive build fix
russellwheatley bc9b98d
fix(app, ios): apply SPM Release/module build settings automatically
russellwheatley 271cd03
fix(app, ios): drop C++-modules Archive workaround that broke React N…
russellwheatley 77777ab
fix(app, ios): fail fast on pod install when SPM is combined with sta…
russellwheatley aff72cd
docs(app, ios): put Expo projects first, label CLI-only sections
russellwheatley b59088f
docs(app, ios): clarify $RNFirebaseDisableSPM = false does not disabl…
russellwheatley 398488f
docs(ios-spm): fix markdown lint indentation
russellwheatley 961346e
fix(app, ios): fix false-positive SPM+static-linkage failure on every…
russellwheatley 598aa88
docs(ios-spm): fix spellcheck failures on FIR symbol mentions and tem…
russellwheatley 3253504
fix(app, ios): warn loudly instead of silently no-opping on CocoaPods…
russellwheatley 258e31c
refactor(app, ios): wrap SPM cross-podspec state in RNFirebaseSPM module
russellwheatley 72b5561
fix(app, ios): use require_relative for firebase_spm/firebase_json ac…
russellwheatley 095690a
ci(ios): extract shared, grep-verified Podfile dep-resolution patch s…
russellwheatley 24c2724
test(app, ios): add opt-in Xcodeproj/CocoaPods shape-check suite, cit…
russellwheatley a91593d
docs(ios-spm): fix stale cross-refs, document Crashlytics/SPM and sha…
russellwheatley f92d96d
test(ios): fix SPM dynamic native coverage multi-image flush
mikehardy 1b6188b
fix(app-distribution,ios): stub App Distribution when SPM headers abs…
mikehardy 1479217
fix(ios): stub Performance and In-App Messaging when Catalyst SPM hea…
mikehardy 67488e5
fix(app,ios): raise Pods UUID counter before RN SPM mutates Pods.xcod…
mikehardy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| #!/bin/bash | ||
| # Configure tests/ios/Podfile for the CI dependency-resolution matrix leg (spm vs cocoapods). | ||
| # Shared by both "Configure Dependency Resolution Mode" steps in tests_e2e_ios.yml | ||
| # (the `ios` job and the `ios-release-archive` job) so the two legs can't drift apart. | ||
| # | ||
| # Usage: configure-ios-dep-resolution.sh <spm|cocoapods> [podfile-dir] | ||
| # podfile-dir defaults to tests/ios, since every caller in tests_e2e_ios.yml runs | ||
| # with the workflow's default working directory (the repo root). | ||
| # | ||
| # spm mode is a no-op: the checked-in Podfile already resolves Firebase via SPM | ||
| # (dynamic linkage, no $RNFirebaseDisableSPM flag -- see packages/app/firebase_spm.rb). | ||
| # | ||
| # cocoapods mode patches the Podfile to force static linkage and disable SPM | ||
| # resolution. Each patch is grep-verified immediately after being applied, so a future | ||
| # change to the Podfile's wording (e.g. reformatting `linkage = 'dynamic'`) fails this | ||
| # script loudly instead of silently leaving the "cocoapods" CI leg testing the SPM path | ||
| # a second time. | ||
| set -euo pipefail | ||
|
|
||
| log_dep_resolution() { | ||
| echo "[dep-resolution] $*" | ||
| } | ||
|
|
||
| configure_cocoapods_mode() { | ||
| local podfile_dir="$1" | ||
| local podfile="${podfile_dir}/Podfile" | ||
|
|
||
| log_dep_resolution "configuring CocoaPods-only mode (disabling SPM) in ${podfile}" | ||
|
|
||
| sed -i '' "s/^linkage = 'dynamic'/linkage = 'static'/" "$podfile" | ||
| grep -q "^linkage = 'static'" "$podfile" || { | ||
| log_dep_resolution "ERROR: expected \"linkage = 'static'\" in ${podfile} after sed, but it was not found -- has the Podfile's linkage line wording changed?" | ||
| exit 1 | ||
| } | ||
|
|
||
| printf '%s\n' '$RNFirebaseDisableSPM = true' | cat - "$podfile" > "${podfile}.tmp" && mv "${podfile}.tmp" "$podfile" | ||
| local first_line | ||
| first_line="$(head -n 1 "$podfile")" | ||
| [[ "$first_line" == '$RNFirebaseDisableSPM = true' ]] || { | ||
| log_dep_resolution "ERROR: expected the first line of ${podfile} to be '\$RNFirebaseDisableSPM = true' after prepend, got: ${first_line}" | ||
| exit 1 | ||
| } | ||
|
|
||
| log_dep_resolution "Podfile configured for CocoaPods-only mode" | ||
| } | ||
|
|
||
| configure_spm_mode() { | ||
| log_dep_resolution "using default SPM mode (dynamic linkage)" | ||
| } | ||
|
|
||
| MODE="${1:-}" | ||
| PODFILE_DIR="${2:-tests/ios}" | ||
|
|
||
| case "$MODE" in | ||
| cocoapods) | ||
| configure_cocoapods_mode "$PODFILE_DIR" | ||
| ;; | ||
| spm) | ||
| configure_spm_mode | ||
| ;; | ||
| *) | ||
| log_dep_resolution "ERROR: unrecognized dependency-resolution mode '${MODE}' (expected 'spm' or 'cocoapods')" | ||
| exit 1 | ||
| ;; | ||
| esac |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
.github/workflows/scripts/verify-ios-release-archive.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| #!/bin/bash | ||
| # Archive the iOS test app for a real device destination (unsigned) and verify | ||
| # the app bundle it produces is actually runnable, i.e. every dynamic | ||
| # framework any embedded binary depends on is present in Frameworks/. | ||
| # | ||
| # Why this exists: the CI matrix in tests_e2e_ios.yml only ever runs | ||
| # `xcodebuild build -sdk iphonesimulator`. The "Archive" action is materially | ||
| # different -- Xcode forces ONLY_ACTIVE_ARCH=NO and DEPLOYMENT_POSTPROCESSING=YES | ||
| # (full stripping / install-style processing) for Archive regardless of what | ||
| # the project/Podfile sets, and it targets a real device SDK, not the | ||
| # simulator SDK. That is precisely the difference between "works when Xcode | ||
| # installs it on a real device or in Simulator" and "crashes only from a | ||
| # TestFlight/Fastlane archive" reported against this PR: | ||
| # https://github.com/invertase/react-native-firebase/pull/8933#issuecomment-4308578826 | ||
| # and the release+SPM dyld launch failure fixed by | ||
| # packages/app/firebase_spm.rb's embed phase (see | ||
| # okf-bundle/ios-spm-native-imports.md "Runtime framework embedding"), which | ||
| # was itself only ever validated against a Release-iphonesimulator build. | ||
| # | ||
| # This script does not require a signing identity or provisioning profile -- | ||
| # it produces an unsigned .xcarchive purely to exercise the real Archive | ||
| # build settings and inspect the resulting app bundle. It is not a substitute | ||
| # for an actual signed TestFlight/device install, but it catches the same | ||
| # class of "framework built, but never embedded / stripped at archive time" | ||
| # regression automatically, on every PR, without needing device hardware or | ||
| # Apple signing credentials in CI. | ||
| set -euo pipefail | ||
|
|
||
| WORKSPACE="${RNFB_ARCHIVE_WORKSPACE:-testing.xcworkspace}" | ||
| SCHEME="${RNFB_ARCHIVE_SCHEME:-testing}" | ||
| CONFIGURATION="${RNFB_ARCHIVE_CONFIGURATION:-Release}" | ||
| ARCHIVE_PATH="${RNFB_ARCHIVE_PATH:-build/testing.xcarchive}" | ||
|
|
||
| log() { | ||
| echo "[ios-release-archive] $*" | ||
| } | ||
|
|
||
| rm -rf "$ARCHIVE_PATH" | ||
|
|
||
| log "archiving scheme=${SCHEME} configuration=${CONFIGURATION} destination=generic/platform=iOS (unsigned) -> ${ARCHIVE_PATH}" | ||
|
|
||
| set -o pipefail | ||
| xcodebuild archive \ | ||
| CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ \ | ||
| -workspace "$WORKSPACE" \ | ||
| -scheme "$SCHEME" \ | ||
| -configuration "$CONFIGURATION" \ | ||
| -destination 'generic/platform=iOS' \ | ||
| -archivePath "$ARCHIVE_PATH" \ | ||
| CODE_SIGN_IDENTITY="" \ | ||
| CODE_SIGNING_REQUIRED=NO \ | ||
| CODE_SIGNING_ALLOWED=NO \ | ||
| CODE_SIGN_ENTITLEMENTS="" \ | ||
| | xcbeautify | ||
|
|
||
| APP_DIR="$(find "${ARCHIVE_PATH}/Products/Applications" -maxdepth 1 -name '*.app' 2>/dev/null | head -1)" | ||
| if [[ -z "$APP_DIR" || ! -d "$APP_DIR" ]]; then | ||
| log "ERROR: no .app product found under ${ARCHIVE_PATH}/Products/Applications" | ||
| exit 1 | ||
| fi | ||
|
|
||
| APP_NAME="$(basename "$APP_DIR" .app)" | ||
| MAIN_BINARY="${APP_DIR}/${APP_NAME}" | ||
| FRAMEWORKS_DIR="${APP_DIR}/Frameworks" | ||
|
|
||
| log "app product: ${APP_DIR}" | ||
| lipo -info "$MAIN_BINARY" 2>&1 | sed 's/^/[ios-release-archive] /' || true | ||
|
|
||
| if [[ -d "$FRAMEWORKS_DIR" ]]; then | ||
| log "embedded frameworks in ${FRAMEWORKS_DIR}:" | ||
| ls -1 "$FRAMEWORKS_DIR" | sed 's/^/[ios-release-archive] /' | ||
| else | ||
| log "no ${FRAMEWORKS_DIR} directory (expected for static-linkage/CocoaPods-only configs; continuing)" | ||
| fi | ||
|
|
||
| # Every *.framework a binary loads via @rpath must actually be embedded -- | ||
| # this is the exact regression class fixed by packages/app/firebase_spm.rb's | ||
| # embed phase (missing FirebaseAppCheckInterop.framework / | ||
| # FirebaseAuthInterop.framework), re-checked here at real Archive-action | ||
| # fidelity rather than a plain simulator build. | ||
| missing=0 | ||
|
|
||
| check_binary() { | ||
| local binary="$1" | ||
| local label="$2" | ||
| local dep fw_name | ||
|
|
||
| while IFS= read -r dep; do | ||
| [[ -z "$dep" ]] && continue | ||
| case "$dep" in | ||
| /System/*|/usr/lib/*) continue ;; | ||
| esac | ||
| fw_name="$(echo "$dep" | sed -E 's#.*/([^/]+\.framework)/.*#\1#')" | ||
| # Not a @rpath/Foo.framework/Foo style dependency -- nothing to check. | ||
| [[ "$fw_name" == "$dep" ]] && continue | ||
| if [[ ! -e "${FRAMEWORKS_DIR}/${fw_name}" ]]; then | ||
| log "MISSING: ${label} depends on ${fw_name} but it is not embedded in ${FRAMEWORKS_DIR}" | ||
| missing=$((missing + 1)) | ||
| fi | ||
| done < <(otool -L "$binary" 2>/dev/null | tail -n +2 | awk '{print $1}') | ||
| } | ||
|
|
||
| check_binary "$MAIN_BINARY" "${APP_NAME} (main app binary)" | ||
|
|
||
| if [[ -d "$FRAMEWORKS_DIR" ]]; then | ||
| for fw_bundle in "$FRAMEWORKS_DIR"/*.framework; do | ||
| [[ -d "$fw_bundle" ]] || continue | ||
| fw_binary_name="$(basename "$fw_bundle" .framework)" | ||
| fw_binary="${fw_bundle}/${fw_binary_name}" | ||
| [[ -f "$fw_binary" ]] && check_binary "$fw_binary" "${fw_binary_name}.framework" | ||
| done | ||
| fi | ||
|
|
||
| if [[ "$missing" -gt 0 ]]; then | ||
| log "FAILED: ${missing} missing framework dependency(ies) found in the real device archive -- see MISSING lines above" | ||
| exit 1 | ||
| fi | ||
|
|
||
| log "OK: every embedded binary's @rpath framework dependencies are present in the archived app bundle" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.