Skip to content
12 changes: 8 additions & 4 deletions packages/core/RNSentry.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,14 @@ Pod::Spec.new do |s|
#
# The flag must ride whichever target's link does the stripping, which
# depends on linkage: static libs (the default) absorb Sentry into the app
# binary โ†’ app link โ†’ `user_target_xcconfig`; `:linkage => :dynamic` absorbs
# binary โ†’ app link โ†’ `user_target_xcconfig`; a dynamic framework absorbs
# it into the RNSentry dylib โ†’ that link โ†’ `pod_target_xcconfig`. Never
# both, or a second copy of Sentry lands in the app. Detected via
# `ENV['USE_FRAMEWORKS']`.
# both, or a second copy of Sentry lands in the app.
#
# Linkage is resolved by `sentry_uses_dynamic_linkage` (see sentry_utils):
# `ENV['USE_FRAMEWORKS']` when set (this repo's CI + the RN/Expo samples),
# otherwise read off the consumer's Podfile so a bare `use_frameworks!`
# without that env var still lands on the right target.
force_load_flags = SENTRY_XCFRAMEWORK_SLICES_BY_SDK.each_with_object({}) do |(sdk, slice_ids), acc|
loads = slice_ids.map do |slice|
%(-force_load "#{File.join(sentry_xcframework_ref, slice, 'Sentry.framework', 'Sentry')}")
Expand All @@ -177,7 +181,7 @@ Pod::Spec.new do |s|

pod_target_xcconfig.merge!(xcframework_search_paths)
user_target_xcconfig = xcframework_search_paths.dup
if ENV['USE_FRAMEWORKS'] == 'dynamic'
if sentry_uses_dynamic_linkage
pod_target_xcconfig.merge!(force_load_flags)
else
user_target_xcconfig.merge!(force_load_flags)
Expand Down
37 changes: 37 additions & 0 deletions packages/core/scripts/sentry_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,40 @@ def stage_sentry_xcframework_in_pods(xcframework_dir, version, product = 'Sentry
end
nil
end

# Whether RNSentry (and thus the Sentry static archive it absorbs) is linked
# into a dynamic framework rather than statically into the app. This decides
# which target's link the `-force_load` flag must ride โ€” see the call site in
# `RNSentry.podspec`.
#
# `ENV['USE_FRAMEWORKS']` is an explicit override (the convention the RN and
# Expo sample Podfiles and this repo's CI already use): `dynamic` forces the
# dynamic path, any other value forces static. When it is unset we read the
# actual linkage off the Podfile CocoaPods has already loaded, because a bare
# `use_frameworks!` / `use_frameworks! :linkage => :dynamic` in a consumer's
# Podfile does NOT export that env var โ€” trusting the env var alone would take
# the static path and force-load Sentry into the app while RNSentry is really a
# dylib (a second Sentry copy in the app, and the framework link still strips
# the category). Reading the Podfile closes that gap.
#
# This is a best-effort proxy: the linkage that ultimately governs is
# RNSentry's own pod `build_type`, which the installer only computes after
# `pre_install` hooks run and which isn't available at podspec-eval time. We
# therefore read the declared target linkage, matching (and widening) what the
# env var proxied. Guarded like `stage_sentry_xcframework_in_pods`: outside a
# real `pod install` (`pod ipc spec`, `pod lib lint`) there is no Podfile, so
# we fall back to the static default, which is correct for the RN default.
def sentry_uses_dynamic_linkage
env = ENV['USE_FRAMEWORKS']
return true if env == 'dynamic'
return false unless env.nil? || env.empty?

podfile = (Pod::Config.instance.podfile if defined?(Pod::Config)) rescue nil
return false unless podfile

podfile.target_definition_list.any? do |td|
!td.root? && (td.build_type.dynamic_framework? rescue false)
end
Comment on lines +267 to +269

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The sentry_uses_dynamic_linkage check is too broad. It incorrectly detects dynamic linkage in mixed-target projects, causing build flags to be misapplied, which can lead to runtime crashes.
Severity: HIGH

Suggested Fix

The logic should be changed to check the linkage setting of the specific target that actually includes the RNSentry pod, rather than checking if any target in the Podfile uses dynamic linkage. This will ensure the -force_load flag is correctly applied based on RNSentry's context.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/core/scripts/sentry_utils.rb#L267-L269

Potential issue: The `sentry_uses_dynamic_linkage` function incorrectly determines the
linkage type in projects with multiple targets and mixed linkage settings. It checks if
`any?` target uses dynamic frameworks, which can return `true` even if the target
containing `RNSentry` uses static linkage. This misdetection leads to the `-force_load`
build flag being applied to the wrong configuration (`pod_target_xcconfig` instead of
the user target's xcconfig). As a result, necessary Objective-C category methods are
stripped during the link phase for the static target, causing the application to crash
at runtime.

rescue StandardError, NotImplementedError
false
Comment thread
antonis marked this conversation as resolved.
end
Loading