Skip to content

fix(android): Prevent New Arch build break linking libsentry-tm-perf-logger.so + CI ABI/link coverage#6406

Merged
antonis merged 6 commits into
mainfrom
fix/tm-perf-logger-armeabi-v7a-link
Jul 6, 2026
Merged

fix(android): Prevent New Arch build break linking libsentry-tm-perf-logger.so + CI ABI/link coverage#6406
antonis merged 6 commits into
mainfrom
fix/tm-perf-logger-armeabi-v7a-link

Conversation

@antonis

@antonis antonis commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 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 reactNativeArchitectures

libsentry-tm-perf-logger.so (added in 8.17.0, #6307) is compiled from source in the consuming app and links React Native's reactnative prefab. Our build.gradle hardcoded abiFilters to all four ABIs, ignoring the app's reactNativeArchitectures — unlike react-native-screens, reanimated and 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 its reactnative prefab for that subset. Our module still tried to build the other three ABIs, which then can't resolve TurboModulePerfLogger::enableLogging at link time → build break. (This matches the reporter's clue: the app requested arm64-v8a yet :sentry_react-native:buildCMakeDebug[armeabi-v7a] ran and failed.)

def reactNativeArchitectures() {
    def value = project.getProperties().get("reactNativeArchitectures")
    return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}
// ...
ndk { abiFilters(*reactNativeArchitectures()) }

Defense-in-depth — -Wl,-z,undefs

src/main/jni/CMakeLists.txt also appends -Wl,-z,undefs so 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 against libreactnative.so; the library is loaded lazily and only when tracking is opted in, and an unresolvable symbol surfaces as an UnsatisfiedLinkError the 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:

  • All-ABI sample builds — the New Architecture sample Android builds (bare React Native and Expo) now build all four ABIs, and the 16 KB alignment check runs across every ABI.
  • scripts/check-tm-perf-logger-link.sh — a lightweight guard (runs on every PR via buildandtest.yml) that reproduces the link condition using the real sources and the real CMakeLists.txt flags; fails if -Wl,-z,undefs is 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):

build.gradle ABIs the module builds
hardcoded (before) arm64-v8a + armeabi-v7a + x86 + x86_64 (builds unrequested ABIs — the bug)
reactNativeArchitectures() (after) arm64-v8a only

Link flag — built the real sources with NDK 27 against the RN 0.86 prefab: reproduces ld.lld: undefined symbol: TurboModulePerfLogger::enableLogging under --no-undefined without the flag; links with it; normal builds keep libreactnative.so in DT_NEEDED. Verified across all four ABIs, all staying 16 KB aligned. check-tm-perf-logger-link.sh passes on the fix and fails when -Wl,-z,undefs is removed.

📝 Checklist

  • I added tests to verify changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.
  • No breaking changes.

🔮 Next steps

  • Consider a CI subset-ABI build (e.g. -PreactNativeArchitectures=arm64-v8a) to assert the module builds only the requested ABIs.

🤖 Generated with Claude Code

…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>
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • fix(android): Prevent New Arch build break linking libsentry-tm-perf-logger.so + CI ABI/link coverage by antonis in #6406
  • fix(android): Correct New Architecture native-build gate to RN 0.76+ by antonis in #6407
  • chore(deps): bump reactivecircus/android-emulator-runner from 2.37.0 to 2.38.0 by dependabot in #6404

🤖 This preview updates automatically when you update the PR.

antonis and others added 2 commits July 6, 2026 10:08
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>
@antonis antonis changed the title fix(android): Prevent New Arch build break linking libsentry-tm-perf-logger.so fix(android): Prevent New Arch build break linking libsentry-tm-perf-logger.so + CI ABI/link coverage Jul 6, 2026
#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>
@antonis antonis added the ready-to-merge Triggers the full CI test suite label Jul 6, 2026
@antonis

antonis commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@sentry review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ 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.

@sentry

sentry Bot commented Jul 6, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
Sentry RN io.sentry.reactnative.sample 8.17.1 (96) Release

⚙️ sentry-react-native Build Distribution Settings

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

iOS (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3853.80 ms 1231.39 ms -2622.41 ms
Size 4.98 MiB 6.51 MiB 1.53 MiB

Baseline results on branch: main

Startup times

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

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 412.24 ms 459.28 ms 47.04 ms
Size 49.74 MiB 55.09 MiB 5.34 MiB

Baseline results on branch: main

Startup times

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

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

iOS (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3841.54 ms 1224.77 ms -2616.78 ms
Size 4.98 MiB 6.51 MiB 1.53 MiB

Baseline results on branch: main

Startup times

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

@antonis antonis marked this pull request as ready for review July 6, 2026 09:19
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 418.02 ms 485.02 ms 67.00 ms
Size 49.74 MiB 55.09 MiB 5.34 MiB

Baseline results on branch: main

Startup times

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>
@antonis antonis merged commit 0a9e622 into main Jul 6, 2026
88 of 96 checks passed
@antonis antonis deleted the fix/tm-perf-logger-armeabi-v7a-link branch July 6, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Triggers the full CI test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Android New Architecture build fails linking libsentry-tm-perf-logger.so with undefined TurboModulePerfLogger::enableLogging on RN 0.86

2 participants