fix(android): Prevent New Arch build break linking libsentry-tm-perf-logger.so + CI ABI/link coverage#6406
Merged
Merged
Conversation
…logger.so The perf-logger native library added in 8.17.0 (#6307) references facebook::react::TurboModulePerfLogger::enableLogging, which lives in React Native's `reactnative` prefab. Some New Architecture build setups (e.g. Expo builds on armeabi-v7a) do not satisfy that reference at link time, and because the NDK/AGP toolchain links with -Wl,-z,defs (--no-undefined) the unresolved symbol becomes a fatal "undefined symbol" error that breaks the whole Android build — even for hosts that never opt in to enableTurboModuleTracking, since the library is compiled whenever the New Architecture is enabled. Append -Wl,-z,undefs to the target's link options so undefined symbols are non-fatal, leaving them to resolve at load time against the loaded libreactnative.so. This is safe: the library is loaded lazily and only when tracking is opted in, and an unresolvable symbol surfaces as an UnsatisfiedLinkError from System.loadLibrary that the Java side already swallows (RNSentryTurboModulePerfTracker), degrading the experimental feature to a no-op rather than crashing. Verified with NDK 27 against the RN 0.86 prefab: - armeabi-v7a with --no-undefined and the prefab unresolved: FAILED before, links after the fix. - normal builds (prefab linked) keep libreactnative.so in DT_NEEDED and resolve the symbol at load time -- the flag is a no-op there. - x86 / arm64 still build and stay 16 KB aligned. Fixes #6398 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
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. |
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…gger Two CI additions to catch the class of failures that shipped with the app-compiled libsentry-tm-perf-logger.so (#6394, #6398), both of which escaped because CI only built x86: - Build all four ABIs (armeabi-v7a, arm64-v8a, x86, x86_64) in the New Architecture sample Android build instead of x86 only, so per-ABI native breakage is exercised and the 16 KB alignment check runs across every ABI. - Add scripts/check-tm-perf-logger-link.sh, a lightweight guard that reproduces the #6398 link condition (armeabi-v7a, --no-undefined, reactnative prefab reference unresolved) using the real sources and the real link flags declared in CMakeLists.txt. It fails if -Wl,-z,undefs is ever removed. Wired into buildandtest.yml so it runs on every PR using the runner's preinstalled NDK. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#6398 (armeabi-v7a link failure) was reported on an Expo build, but the Expo sample only built x86 in CI. Build all four ABIs to keep coverage consistent with the bare React Native sample. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
11 tasks
Contributor
Author
|
@sentry 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 f06c668. Configure here.
📲 Install BuildsAndroid
|
Contributor
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 |
Contributor
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 |
Contributor
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 |
alwx
approved these changes
Jul 6, 2026
Contributor
Android (new) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| f170ec3+dirty | 505.96 ms | 551.88 ms | 45.92 ms |
| b04af96+dirty | 430.33 ms | 485.98 ms | 55.65 ms |
| 7887847+dirty | 420.47 ms | 460.55 ms | 40.08 ms |
| eb93136+dirty | 500.37 ms | 532.58 ms | 32.21 ms |
| c2e182c+dirty | 468.50 ms | 545.44 ms | 76.94 ms |
| d0e3b3e+dirty | 443.19 ms | 480.00 ms | 36.81 ms |
| 0a147b2+dirty | 442.80 ms | 522.24 ms | 79.44 ms |
| d038a14+dirty | 405.08 ms | 444.36 ms | 39.28 ms |
| 890d145+dirty | 486.42 ms | 514.85 ms | 28.43 ms |
| 15d4514+dirty | 413.63 ms | 449.62 ms | 35.99 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| f170ec3+dirty | 48.30 MiB | 53.57 MiB | 5.26 MiB |
| b04af96+dirty | 49.74 MiB | 55.00 MiB | 5.26 MiB |
| 7887847+dirty | 49.74 MiB | 54.81 MiB | 5.07 MiB |
| eb93136+dirty | 48.30 MiB | 53.58 MiB | 5.28 MiB |
| c2e182c+dirty | 49.74 MiB | 54.85 MiB | 5.11 MiB |
| d0e3b3e+dirty | 49.74 MiB | 55.09 MiB | 5.34 MiB |
| 0a147b2+dirty | 49.74 MiB | 55.08 MiB | 5.34 MiB |
| d038a14+dirty | 48.30 MiB | 53.49 MiB | 5.19 MiB |
| 890d145+dirty | 43.94 MiB | 49.00 MiB | 5.06 MiB |
| 15d4514+dirty | 48.30 MiB | 53.60 MiB | 5.30 MiB |
…ve build Root-cause fix for #6398. The module hardcoded `abiFilters` to all four ABIs, ignoring the host app's `reactNativeArchitectures`. When the app builds a subset (e.g. `-PreactNativeArchitectures=arm64-v8a`, common in Expo/dev/CI builds), React Native only provides its `reactnative` prefab for that subset, so building the extra ABIs cannot resolve `TurboModulePerfLogger::enableLogging` at link time and breaks the build. Honor `reactNativeArchitectures` (falling back to all four when unset), matching react-native-screens, reanimated and the RN app template. Now the module builds only the ABIs the app requested. Verified locally against a subset build: with the old hardcoded filters, `:sentry_react-native:externalNativeBuildDebug -PreactNativeArchitectures=arm64-v8a` built arm64-v8a + armeabi-v7a + x86 + x86_64; with the fix it builds only arm64-v8a. The `-Wl,-z,undefs` link flag stays as defense-in-depth for any remaining setup where a built ABI's prefab reference is unresolved. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
📢 Type of change
📜 Description
Fixes the Android New Architecture build break in #6398, plus CI coverage for the class of failures around this app-compiled library.
Root-cause fix — honor
reactNativeArchitectureslibsentry-tm-perf-logger.so(added in 8.17.0, #6307) is compiled from source in the consuming app and links React Native'sreactnativeprefab. Ourbuild.gradlehardcodedabiFiltersto all four ABIs, ignoring the app'sreactNativeArchitectures— unlikereact-native-screens,reanimatedand the RN app template, which all honor it.When the app builds a subset (e.g.
-PreactNativeArchitectures=arm64-v8a, common in Expo/dev/CI builds), React Native only provides itsreactnativeprefab for that subset. Our module still tried to build the other three ABIs, which then can't resolveTurboModulePerfLogger::enableLoggingat link time → build break. (This matches the reporter's clue: the app requestedarm64-v8ayet:sentry_react-native:buildCMakeDebug[armeabi-v7a]ran and failed.)Defense-in-depth —
-Wl,-z,undefssrc/main/jni/CMakeLists.txtalso appends-Wl,-z,undefsso that if any built ABI's prefab reference is still unresolved at link time, the build doesn't hard-fail (the NDK/AGP toolchain links with--no-undefined). Undefined symbols then resolve at load againstlibreactnative.so; the library is loaded lazily and only when tracking is opted in, and an unresolvable symbol surfaces as anUnsatisfiedLinkErrorthe Java side already swallows (RNSentryTurboModulePerfTracker) — degrading the experimental feature to a no-op rather than crashing.CI coverage
Both #6394 (16 KB alignment) and #6398 escaped because CI only built x86, while this is the SDK's only library compiled per-ABI on the user's side:
scripts/check-tm-perf-logger-link.sh— a lightweight guard (runs on every PR viabuildandtest.yml) that reproduces the link condition using the real sources and the realCMakeLists.txtflags; fails if-Wl,-z,undefsis removed.💡 Motivation and Context
Fixes #6398. Present since 8.17.0 (still in 8.17.1). Hard build failure with no clean workaround, hitting New Architecture apps that build a subset of ABIs — including Expo — regardless of whether the perf-tracking feature is enabled.
💚 How did you test it?
Root-cause fix — verified locally against a subset build (
:sentry_react-native:externalNativeBuildDebug -PreactNativeArchitectures=arm64-v8a):reactNativeArchitectures()(after)Link flag — built the real sources with NDK 27 against the RN 0.86 prefab: reproduces
ld.lld: undefined symbol: TurboModulePerfLogger::enableLoggingunder--no-undefinedwithout the flag; links with it; normal builds keeplibreactnative.soinDT_NEEDED. Verified across all four ABIs, all staying 16 KB aligned.check-tm-perf-logger-link.shpasses on the fix and fails when-Wl,-z,undefsis removed.📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps
-PreactNativeArchitectures=arm64-v8a) to assert the module builds only the requested ABIs.🤖 Generated with Claude Code