Repository navigation
feat(ios): Default to consuming sentry-cocoa as an xcframework - #6381
Conversation
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog.
🤖 This preview updates automatically when you update the PR. |
|
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit c8143aa. Configure here.
|
It would probably be nice to include it to the next release but no stress |
📲 Install BuildsAndroid
|
Android (new) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 0d9949d+dirty | 414.88 ms | 428.68 ms | 13.81 ms |
| a736b76+dirty | 405.78 ms | 458.74 ms | 52.96 ms |
| 5569641+dirty | 465.92 ms | 532.22 ms | 66.30 ms |
| 580fb5c+dirty | 515.72 ms | 585.38 ms | 69.66 ms |
| 7ff4d0f+dirty | 403.38 ms | 427.06 ms | 23.68 ms |
| 6177334+dirty | 404.80 ms | 456.74 ms | 51.94 ms |
| 1e5d96d+dirty | 423.33 ms | 482.46 ms | 59.13 ms |
| f170ec3+dirty | 505.96 ms | 551.88 ms | 45.92 ms |
| 20fbd51+dirty | 594.38 ms | 655.35 ms | 60.97 ms |
| f3215d3+dirty | 396.53 ms | 436.66 ms | 40.13 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 0d9949d+dirty | 43.94 MiB | 48.99 MiB | 5.05 MiB |
| a736b76+dirty | 48.30 MiB | 53.48 MiB | 5.18 MiB |
| 5569641+dirty | 48.30 MiB | 53.48 MiB | 5.18 MiB |
| 580fb5c+dirty | 49.74 MiB | 54.79 MiB | 5.05 MiB |
| 7ff4d0f+dirty | 48.30 MiB | 53.60 MiB | 5.30 MiB |
| 6177334+dirty | 48.30 MiB | 53.54 MiB | 5.23 MiB |
| 1e5d96d+dirty | 49.74 MiB | 54.81 MiB | 5.07 MiB |
| f170ec3+dirty | 48.30 MiB | 53.57 MiB | 5.26 MiB |
| 20fbd51+dirty | 49.74 MiB | 54.81 MiB | 5.07 MiB |
| f3215d3+dirty | 48.30 MiB | 53.49 MiB | 5.19 MiB |
Android (legacy) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 0d9949d+dirty | 403.57 ms | 437.00 ms | 33.43 ms |
| 64630e5+dirty | 419.18 ms | 464.58 ms | 45.40 ms |
| 853723c+dirty | 405.54 ms | 440.08 ms | 34.54 ms |
| 1122a96+dirty | 422.22 ms | 464.33 ms | 42.10 ms |
| 5748023+dirty | 446.69 ms | 505.63 ms | 58.94 ms |
| eb93136+dirty | 416.18 ms | 467.32 ms | 51.14 ms |
| 4e0ba9c+dirty | 452.84 ms | 473.36 ms | 20.52 ms |
| c2e182c+dirty | 471.64 ms | 553.59 ms | 81.95 ms |
| a0d8cf8+dirty | 411.71 ms | 467.57 ms | 55.87 ms |
| d0e3b3e+dirty | 421.53 ms | 498.19 ms | 76.66 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 0d9949d+dirty | 43.75 MiB | 48.13 MiB | 4.37 MiB |
| 64630e5+dirty | 49.74 MiB | 54.82 MiB | 5.07 MiB |
| 853723c+dirty | 48.30 MiB | 53.58 MiB | 5.28 MiB |
| 1122a96+dirty | 48.30 MiB | 53.54 MiB | 5.24 MiB |
| 5748023+dirty | 48.30 MiB | 53.54 MiB | 5.23 MiB |
| eb93136+dirty | 48.30 MiB | 53.58 MiB | 5.28 MiB |
| 4e0ba9c+dirty | 48.30 MiB | 53.49 MiB | 5.19 MiB |
| c2e182c+dirty | 49.74 MiB | 54.85 MiB | 5.11 MiB |
| a0d8cf8+dirty | 48.30 MiB | 53.49 MiB | 5.19 MiB |
| d0e3b3e+dirty | 49.74 MiB | 55.09 MiB | 5.34 MiB |
antonis
left a comment
There was a problem hiding this comment.
Since the dynamic approach didn't resolve the CI build issue and this partially a breaking change for the users I suggest to try the following:
- Keep SPM opt-in till the React Native framework supports it
- Have RNSentry.podspec consume sentry-cocoa as a vendored_frameworks xcframework downloaded from sentry-cocoa's GitHub releases, instead of either s.dependency 'Sentry' (CocoaPods trunk) or SPM.dependency (spm.rb bridge).
Wdyt?
iOS (legacy) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 57e0069+dirty | 3842.29 ms | 1212.12 ms | -2630.17 ms |
| 0bd8916+dirty | 3842.33 ms | 1230.76 ms | -2611.58 ms |
| 774257e+dirty | 3846.90 ms | 1215.02 ms | -2631.88 ms |
| acd838e+dirty | 3849.78 ms | 1230.00 ms | -2619.78 ms |
| 038a6d7+dirty | 3849.69 ms | 1228.40 ms | -2621.28 ms |
| df5d108+dirty | 1225.90 ms | 1220.14 ms | -5.76 ms |
| 2c735cc+dirty | 1229.67 ms | 1221.50 ms | -8.17 ms |
| 5a010b7+dirty | 3838.85 ms | 1214.98 ms | -2623.87 ms |
| f170ec3+dirty | 3822.26 ms | 1218.33 ms | -2603.93 ms |
| 4953e94+dirty | 1212.06 ms | 1214.83 ms | 2.77 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 57e0069+dirty | 4.98 MiB | 6.50 MiB | 1.52 MiB |
| 0bd8916+dirty | 5.15 MiB | 6.69 MiB | 1.53 MiB |
| 774257e+dirty | 5.15 MiB | 6.70 MiB | 1.54 MiB |
| acd838e+dirty | 5.15 MiB | 6.70 MiB | 1.55 MiB |
| 038a6d7+dirty | 5.15 MiB | 6.70 MiB | 1.55 MiB |
| df5d108+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |
| 2c735cc+dirty | 3.38 MiB | 4.74 MiB | 1.35 MiB |
| 5a010b7+dirty | 5.15 MiB | 6.69 MiB | 1.54 MiB |
| f170ec3+dirty | 5.15 MiB | 6.69 MiB | 1.53 MiB |
| 4953e94+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |
iOS (new) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 57e0069+dirty | 3842.23 ms | 1210.00 ms | -2632.23 ms |
| 41d6254+dirty | 3849.78 ms | 1233.91 ms | -2615.86 ms |
| 7d8c8bd+dirty | 3847.98 ms | 1230.77 ms | -2617.21 ms |
| c823bb5+dirty | 3845.16 ms | 1210.33 ms | -2634.83 ms |
| bc0d8cf+dirty | 3834.64 ms | 1223.91 ms | -2610.73 ms |
| 1e5d96d+dirty | 3845.93 ms | 1222.51 ms | -2623.42 ms |
| 7d6fd3a+dirty | 1210.89 ms | 1217.63 ms | 6.74 ms |
| 7436d0f+dirty | 3861.51 ms | 1231.07 ms | -2630.44 ms |
| 4953e94+dirty | 1217.41 ms | 1223.53 ms | 6.12 ms |
| 6acdf1d+dirty | 3835.35 ms | 1218.30 ms | -2617.06 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 57e0069+dirty | 4.98 MiB | 6.50 MiB | 1.52 MiB |
| 41d6254+dirty | 5.15 MiB | 6.70 MiB | 1.54 MiB |
| 7d8c8bd+dirty | 5.15 MiB | 6.68 MiB | 1.53 MiB |
| c823bb5+dirty | 5.15 MiB | 6.69 MiB | 1.53 MiB |
| bc0d8cf+dirty | 5.15 MiB | 6.67 MiB | 1.51 MiB |
| 1e5d96d+dirty | 4.98 MiB | 6.46 MiB | 1.49 MiB |
| 7d6fd3a+dirty | 3.38 MiB | 4.77 MiB | 1.39 MiB |
| 7436d0f+dirty | 5.15 MiB | 6.70 MiB | 1.54 MiB |
| 4953e94+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |
| 6acdf1d+dirty | 4.98 MiB | 6.51 MiB | 1.53 MiB |
aae21ec to
3eed101
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3eed101. Configure here.
| # `Info.plist` most likely came from an interrupted `unzip` and would | ||
| # otherwise silently short-circuit re-download here. | ||
| target_manifest = File.join(target_dir, 'Info.plist') | ||
| return target_dir if File.file?(target_manifest) |
There was a problem hiding this comment.
Cached xcframework skips checksum
Medium Severity
When Info.plist already exists under the versioned cache directory, ensure_sentry_xcframework returns immediately and never re-checks the zip SHA256 from SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS. Upgrading @sentry/react-native after a checksum fix for the same sentry-cocoa version can leave a stale or tampered binary in use.
Reviewed by Cursor Bugbot for commit 3eed101. Configure here.
pod install now downloads Sentry.xcframework.zip from sentry-cocoa's GitHub release (SHA256-verified) and caches it under ~/Library/Caches/sentry-react-native/xcframeworks/<version>/, instead of building Sentry from source as a CocoaPod. Sentry symbols are then statically linked into the app binary (no framework embed, no dylib dep) via `FRAMEWORK_SEARCH_PATHS[sdk=…*]` + clang's -fmodules-autolink. Motivation: - CocoaPods trunk is winding down; we needed a path off it that also sidesteps the Xcode 16/26 archive bug that hits any signed SPM binary xcframework (`Signatures/*.signature` collision). - Consuming via CocoaPods' `vendored_frameworks` pipeline goes through a different code path and is unaffected. Fallback: set `SENTRY_USE_XCFRAMEWORK=0` before pod install to restore the source-built `Sentry` CocoaPod (for offline builds behind a restrictive proxy, or projects with another pod that transitively depends on the Sentry CocoaPod). Cache location is user-writable (not inside node_modules), which means pnpm's isolated store and Yarn PnP work without changes. Override the cache root with `SENTRY_XCFRAMEWORK_CACHE_DIR`. Verified end-to-end against alpha.3 on: - Real device signed archive (Apple accepts, codesign strict-verify passes) - Native crash → dSYM upload → Sentry frames symbolicated - RN 0.71 archive (via SKIP_BUNDLING) with 21k Sentry symbols in dSYM - EAS Build with npm, pnpm-isolated, and `SENTRY_USE_XCFRAMEWORK=0` - Second EAS build after version bump (no stale-cache pollution) Reapplies the content of PR #6381 (merged prematurely as part of the alpha.3 release, then rolled back via #6412) with the pnpm cache-location fix baked in from the start this time. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…6413) pod install now downloads Sentry.xcframework.zip from sentry-cocoa's GitHub release (SHA256-verified) and caches it under ~/Library/Caches/sentry-react-native/xcframeworks/<version>/, instead of building Sentry from source as a CocoaPod. Sentry symbols are then statically linked into the app binary (no framework embed, no dylib dep) via `FRAMEWORK_SEARCH_PATHS[sdk=…*]` + clang's -fmodules-autolink. Motivation: - CocoaPods trunk is winding down; we needed a path off it that also sidesteps the Xcode 16/26 archive bug that hits any signed SPM binary xcframework (`Signatures/*.signature` collision). - Consuming via CocoaPods' `vendored_frameworks` pipeline goes through a different code path and is unaffected. Fallback: set `SENTRY_USE_XCFRAMEWORK=0` before pod install to restore the source-built `Sentry` CocoaPod (for offline builds behind a restrictive proxy, or projects with another pod that transitively depends on the Sentry CocoaPod). Cache location is user-writable (not inside node_modules), which means pnpm's isolated store and Yarn PnP work without changes. Override the cache root with `SENTRY_XCFRAMEWORK_CACHE_DIR`. Verified end-to-end against alpha.3 on: - Real device signed archive (Apple accepts, codesign strict-verify passes) - Native crash → dSYM upload → Sentry frames symbolicated - RN 0.71 archive (via SKIP_BUNDLING) with 21k Sentry symbols in dSYM - EAS Build with npm, pnpm-isolated, and `SENTRY_USE_XCFRAMEWORK=0` - Second EAS build after version bump (no stale-cache pollution) Reapplies the content of PR #6381 (merged prematurely as part of the alpha.3 release, then rolled back via #6412) with the pnpm cache-location fix baked in from the start this time. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…es (#58781) Summary: `spm_dependency` links a pod against Swift package products, but CocoaPods only embeds the frameworks of pods. Dynamic frameworks from Swift packages (binary targets like rive-ios' `RiveRuntime`, or `type: .dynamic` products like `AlamofireDynamic`) never reach the app bundle, so the app builds but fails at launch with `dyld: Library not loaded: rpath/RiveRuntime.framework/RiveRuntime`. Separately, Xcode 26 archives fail on the duplicate signature Xcode writes for a binary target used by a pod: `"RiveRuntime.xcframework-ios.signature" couldn't be copied to "Signatures" because an item with the same name already exists.` This PR: 1. Adds an `install_spm_framework <name>` call per framework to the app's `[CP] Embed Pods Frameworks` script, which embeds the framework from where Xcode builds it, unless it is static. 2. Adds `embed_frameworks:` to `spm_dependency`, defaulting to `products`, for frameworks named differently from their product (`Sentry-Dynamic` is `Sentry.framework`) or coming from the packages a product depends on (`MapboxMaps` loads `MapboxCommon`, `MapboxCoreMaps` and `Turf`). 3. Removes the pod's duplicate `*.xcframework-*.signature` for pods not built into the shared products dir. 4. Records a dependency once, even though CocoaPods evaluates a podspec several times per install. Libraries work around this on their own today, e.g. react-native-firebase's `firebase_spm.rb`, stripe/stripe-react-native#2608, maplibre/maplibre-react-native#1490, or by dropping SPM as in getsentry/sentry-react-native#6381. ## Changelog: [IOS] [FIXED] - `spm_dependency` embeds the dynamic frameworks of Swift packages in the app, and takes `embed_frameworks` for frameworks named differently from their product Pull Request resolved: #58781 Test Plan: `ruby -Itest packages/react-native/scripts/cocoapods/__tests__/spm-test.rb` passes, with 5 new tests. It also fixes the existing tests, whose installer stub lacked `aggregate_targets` since #57602. Built https://github.com/mfazekas/rn-spm-dynamic-poc (a library using `AlamofireDynamic`, `RiveRuntime` and `Sentry-Dynamic`) with this `spm.rb` on RN 0.84 and Xcode 26.5: - Before: Debug simulator launch fails with `Library not loaded: rpath/RiveRuntime.framework`, and the Release archive fails on the duplicate signature. - After: the frameworks are embedded, the app launches and the archive succeeds, with dynamic frameworks (all three) and with static libraries (`RiveRuntime` and `Sentry`; `AlamofireDynamic` does not link statically, with or without this change). Its `more-packages` branch does the same with Agora, Mapbox, Stripe and Firebase. Reviewed By: cortinico Differential Revision: D122772893 Pulled By: cipolleschi fbshipit-source-id: c201a20388fe1c50cc1f7c3d06873535a2be73c7


📢 Type of change
📜 Description
Vendor
sentry-cocoaas a prebuiltSentry-Dynamic.xcframework(downloaded from the GitHub release and SHA256-verified atpod installtime), instead of buildingSentryfrom source as a CocoaPod. Sidesteps the Xcode 16/26 archive bug that hits when the same xcframework is consumed through Xcode's SPM integration ("Sentry-Dynamic.xcframework-ios.signature" couldn't be copied to "Signatures"…).Override with:
SENTRY_USE_XCFRAMEWORK=0— fall back to the source-builtSentryCocoaPod (e.g. offline builds behind a restrictive proxy).💡 Motivation and Context
CocoaPods source builds of
sentry-cocoaare slow and diverge from where the RN community is moving (prebuilt binaries). SPM was the first attempt, but Xcode 16/26 archives fail with a duplicate-signature error on any signed SPM binary xcframework. Consuming the same xcframework through CocoaPods'vendored_frameworksavoids the Xcode-SPM archive pipeline and works on the full RN version range.💚 How did you test it?
CI: sample-application (iOS matrix, both
xcframeworkdefault andcocoapodsfallback), iOS Size Analysis (archive), metrics (fastlane archive).📝 Checklist
sendDefaultPIIis enabled🔮 Next steps