-
-
Notifications
You must be signed in to change notification settings - Fork 360
feat(ios): Default to consuming sentry-cocoa as an xcframework #6381
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
Changes from all commits
d988c1b
9f862f6
cbe639a
d99d143
f1aa3a3
d1a7e8b
f8e312f
b644e2e
deccc6a
e63e394
fe92fc8
aa94ec9
d100f78
f78fc85
dabcb3c
83a6fcc
1d96e69
3eed101
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // This file exists to force Xcode to link the Swift runtime compatibility | ||
| // libraries (e.g. libswiftCompatibility56, libswiftCompatibilityConcurrency) | ||
| // into RNSentry. Those libs are required by our vendored `Sentry.xcframework` | ||
| // static Swift library and Xcode only auto-links them when the consuming | ||
| // target itself contains Swift code โ without this stub, linking a dynamic | ||
| // RNSentry framework fails with: | ||
| // Undefined symbols: "__swift_FORCE_LOAD_$_swiftCompatibility56" | ||
|
sentry[bot] marked this conversation as resolved.
|
||
|
|
||
| // A private, unused constant so the compiler emits a real object file. A | ||
| // pure-comment file compiles to nothing and would defeat the purpose of | ||
| // the stub. | ||
| private let _rnSentrySwiftLinkStub: Void = () | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,3 +40,128 @@ def should_use_folly_flags(rn_version) | |
| def is_new_hermes_runtime(rn_version) | ||
| return (rn_version[:major] >= 1 || (rn_version[:major] == 0 && rn_version[:minor] >= 81)) | ||
| end | ||
|
|
||
| require 'digest' | ||
| require 'fileutils' | ||
| require 'open-uri' | ||
|
|
||
| # SHA256 checksums of `<product>.xcframework.zip` assets published in | ||
| # sentry-cocoa GitHub releases (same value as the SPM binary target checksum | ||
| # in sentry-cocoa's `Package.swift`). Register the checksum for each | ||
| # sentry-cocoa version we ship a prebuilt xcframework for. | ||
| # | ||
| # Kept in sync with `sentry_cocoa_version` in `RNSentry.podspec` by | ||
| # `scripts/update-cocoa.sh set-version <new>`, which downloads the new | ||
| # release archive, computes its SHA256, and rewrites the entry below. | ||
| SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS = { | ||
| # `Sentry.xcframework.zip` โ the static product. Its enclosing xcframework | ||
| # name matches the framework name inside (both `Sentry`), which CocoaPods | ||
| # requires to generate `-framework Sentry` correctly and to resolve the | ||
| # `Sentry` module. `Sentry-Dynamic.xcframework` would ship the same | ||
| # `Sentry.framework` inside but under a mismatched enclosing name, so | ||
| # CocoaPods generates `-framework Sentry-Dynamic` and fails at link. | ||
| '9.19.1' => { | ||
| 'Sentry' => 'd6d545af17e49851cda2747b0f45cde78ce08ea37709dde5a956c6b4671224e8', | ||
|
sentry[bot] marked this conversation as resolved.
Comment on lines
+63
to
+64
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| }, | ||
| }.freeze | ||
|
|
||
| # Static map from xcframework slice directory name to the Xcode SDK selector | ||
| # it should be attached to. `sentry-cocoa`'s `Sentry.xcframework` layout is | ||
| # stable across releases โ same slice names come out of every build โ so we | ||
| # hardcode the mapping rather than scanning the extracted bundle. Add a | ||
| # new entry here if `sentry-cocoa` ever ships a new platform slice. | ||
| SENTRY_XCFRAMEWORK_SLICES_BY_SDK = { | ||
| 'iphoneos' => %w[ios-arm64_arm64e], | ||
| 'iphonesimulator' => %w[ios-arm64_x86_64-simulator], | ||
| 'maccatalyst' => %w[ios-arm64_arm64e_x86_64-maccatalyst], | ||
| 'macosx' => %w[macos-arm64_arm64e_x86_64], | ||
| 'appletvos' => %w[tvos-arm64_arm64e], | ||
| 'appletvsimulator' => %w[tvos-arm64_x86_64-simulator], | ||
| 'watchos' => %w[watchos-arm64_arm64_32_arm64e_armv7k], | ||
| 'watchsimulator' => %w[watchos-arm64_x86_64-simulator], | ||
| 'xros' => %w[xros-arm64_arm64e], | ||
| 'xrsimulator' => %w[xros-arm64_x86_64-simulator], | ||
| }.freeze | ||
|
|
||
| # Ensures `<cache>/<version>/<product>.xcframework` exists. | ||
| # | ||
| # On first invocation, downloads the prebuilt xcframework zip from | ||
| # sentry-cocoa's GitHub release, verifies its SHA256 checksum against | ||
| # `SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS`, and extracts it. Subsequent | ||
| # invocations are no-ops. Returns the absolute path to the extracted | ||
| # xcframework, which callers pass to `FRAMEWORK_SEARCH_PATHS`. | ||
| # | ||
| # The cache lives under a user-writable directory (`~/Library/Caches/ | ||
| # sentry-react-native/xcframeworks/` on macOS by default; override with | ||
| # `SENTRY_XCFRAMEWORK_CACHE_DIR`). Cannot live under the pod's own source | ||
| # tree because pnpm's isolated store makes `node_modules/@sentry/ | ||
| # react-native/ios/` read-only, and `Yarn PnP` doesn't materialize the | ||
| # package directory at all โ writing there fails with `EACCES`. | ||
| # Deduplicating cache across multiple RN projects on the same machine | ||
| # is a nice side effect. | ||
| # | ||
| # Consuming sentry-cocoa this way (vs. through Xcode's SPM integration) | ||
| # avoids the Xcode 16/26 archive bug where a signed SPM binary xcframework's | ||
| # `Signatures/*.signature` file collides during the archive step. | ||
|
sentry-warden[bot] marked this conversation as resolved.
|
||
| def ensure_sentry_xcframework(version, product = 'Sentry') | ||
| cache_root = ENV['SENTRY_XCFRAMEWORK_CACHE_DIR'] || | ||
| File.expand_path('~/Library/Caches/sentry-react-native/xcframeworks') | ||
| vendor_dir = File.join(cache_root, version) | ||
| target_dir = File.join(vendor_dir, "#{product}.xcframework") | ||
| # Treat the presence of `Info.plist` inside the xcframework as the "healthy" | ||
| # sentinel rather than just the directory existence. A directory without | ||
| # `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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cached xcframework skips checksumMedium Severity When Reviewed by Cursor Bugbot for commit 3eed101. Configure here. |
||
|
|
||
| expected_checksum = SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS.dig(version, product) | ||
| unless expected_checksum | ||
| raise "sentry-cocoa xcframework checksum not registered for #{product} " \ | ||
| "#{version}. Add it to SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS in " \ | ||
| "packages/core/scripts/sentry_utils.rb after bumping the version." | ||
| end | ||
|
|
||
| # Wipe any stale partial extract from a previous interrupted run so we | ||
| # always start from a clean tree. | ||
| FileUtils.rm_rf(target_dir) | ||
| FileUtils.mkdir_p(vendor_dir) | ||
| zip_path = File.join(vendor_dir, "#{product}.xcframework.zip") | ||
| url = "https://github.com/getsentry/sentry-cocoa/releases/download/" \ | ||
| "#{version}/#{product}.xcframework.zip" | ||
|
|
||
| Pod::UI.puts "[Sentry] Downloading #{product} #{version} from GitHub Releasesโฆ" if defined?(Pod::UI) | ||
| begin | ||
| URI.open(url, redirect: true) do |remote| | ||
| File.open(zip_path, 'wb') { |f| IO.copy_stream(remote, f) } | ||
| end | ||
| rescue OpenURI::HTTPError, SocketError, StandardError => e | ||
| FileUtils.rm_f(zip_path) | ||
| raise "Failed to download #{url}: #{e.class}: #{e.message}" | ||
| end | ||
|
|
||
| actual_checksum = Digest::SHA256.file(zip_path).hexdigest | ||
| unless actual_checksum == expected_checksum | ||
| FileUtils.rm_f(zip_path) | ||
| raise "Checksum mismatch for #{product} #{version}: expected " \ | ||
| "#{expected_checksum}, got #{actual_checksum}" | ||
| end | ||
|
|
||
| unless system('unzip', '-q', '-o', zip_path, '-d', vendor_dir) | ||
| raise "Failed to extract #{zip_path}" | ||
| end | ||
| FileUtils.rm_f(zip_path) | ||
|
|
||
| # Guard against a release archive whose internal layout changed (e.g. a | ||
| # nested folder). Without this check, a wrong layout silently succeeds and | ||
| # then fails much later during `pod install` with a confusing "framework | ||
| # not found" error. | ||
| unless File.file?(target_manifest) | ||
| raise "Expected #{target_manifest} after extracting #{product}.xcframework.zip. " \ | ||
| "The sentry-cocoa release archive layout may have changed โ update " \ | ||
| "the extraction logic in packages/core/scripts/sentry_utils.rb." | ||
| end | ||
|
|
||
| target_dir | ||
|
sentry[bot] marked this conversation as resolved.
|
||
| end | ||
|
|
||


Uh oh!
There was an error while loading. Please reload this page.