Fix Android: whole-archive pulp-view for accessibility JNI symbols - #148
Closed
danielraffel wants to merge 1 commit into
Closed
Fix Android: whole-archive pulp-view for accessibility JNI symbols#148danielraffel wants to merge 1 commit into
danielraffel wants to merge 1 commit into
Conversation
…vive PR #132 P1 (never actually resolved): accessibility_android.cpp provides the TalkBack JNI entry points (Java_com_pulp_accessibility_nativeGetAccessibilityNodeCount, nativePerformAction, nativeGetNodeRole, etc.) inside pulp-view. Nothing inside pulp-view or libpulp.so references these symbols — the callers are on the Kotlin side (PulpAccessibility.kt) — so the Android linker is free to strip them under the default dead-code elimination. That manifests at runtime as UnsatisfiedLinkError the first time TalkBack queries the node tree. pulp-jni's target_link_options already wraps pulp-platform, pulp-audio, and (when present) pulp-render in --whole-archive for the same reason. Add pulp-view to the same block. Fixes the only P1 from PR #132 that was merged unresolved.
Collaborator
Author
|
Closing: this approach breaks the Android build. Adding pulp-view to --whole-archive transitively pulls in SDL3's libSDL3.a, which defines its own JNI_OnLoad and collides with core/platform/src/android/jni_bridge.cpp:41. The right fix keeps only the accessibility JNI symbols alive without dragging in SDL3 — either force-reference them via -Wl,--undefined=Java_com_pulp_accessibility_* in pulp-jni's link options, or compile accessibility_android.cpp directly into pulp-jni rather than pulp-view. Will open a follow-up PR with the narrower fix. |
danielraffel
added a commit
that referenced
this pull request
Apr 13, 2026
…pulp-view PR #132's P1 review never actually landed on main. accessibility_android.cpp defines all Java_com_pulp_accessibility_PulpAccessibilityDelegate_native* entry points inside pulp-view (static lib). Nothing inside libpulp.so references them — the only callers are on the Kotlin side (PulpAccessibility.kt) — so the Android linker is free to strip them under default dead-code elimination. At runtime TalkBack's first node-tree walk then hits UnsatisfiedLinkError. PR #148 tried to fix this by whole-archiving pulp-view. That pulled SDL3's libSDL3.a in transitively, and SDL3 defines its own JNI_OnLoad, colliding with core/platform/src/android/jni_bridge.cpp:41. #148 was closed. This PR uses the narrower `-Wl,--undefined=<symbol>` approach: force- reference each of the nine TalkBack JNI exports in pulp-jni's link options. The linker then keeps the accessibility_android.cpp object file alive without dragging any other sections of pulp-view (or its SDL3 transitive closure) into libpulp.so. No behaviour change on non-Android builds (the whole pulp-jni target is gated on ANDROID). On Android, the nine forced references grow libpulp.so by the single accessibility_android.cpp object file — same footprint PR #127 intended when it first landed TalkBack.
3 tasks
danielraffel
added a commit
that referenced
this pull request
Apr 14, 2026
…pulp-view PR #132's P1 review never actually landed on main. accessibility_android.cpp defines all Java_com_pulp_accessibility_PulpAccessibilityDelegate_native* entry points inside pulp-view (static lib). Nothing inside libpulp.so references them — the only callers are on the Kotlin side (PulpAccessibility.kt) — so the Android linker is free to strip them under default dead-code elimination. At runtime TalkBack's first node-tree walk then hits UnsatisfiedLinkError. PR #148 tried to fix this by whole-archiving pulp-view. That pulled SDL3's libSDL3.a in transitively, and SDL3 defines its own JNI_OnLoad, colliding with core/platform/src/android/jni_bridge.cpp:41. #148 was closed. This PR uses the narrower `-Wl,--undefined=<symbol>` approach: force- reference each of the nine TalkBack JNI exports in pulp-jni's link options. The linker then keeps the accessibility_android.cpp object file alive without dragging any other sections of pulp-view (or its SDL3 transitive closure) into libpulp.so. No behaviour change on non-Android builds (the whole pulp-jni target is gated on ANDROID). On Android, the nine forced references grow libpulp.so by the single accessibility_android.cpp object file — same footprint PR #127 intended when it first landed TalkBack.
danielraffel
added a commit
that referenced
this pull request
Apr 14, 2026
…pulp-view (#151) * Fix Android: force-keep TalkBack JNI symbols without whole-archiving pulp-view PR #132's P1 review never actually landed on main. accessibility_android.cpp defines all Java_com_pulp_accessibility_PulpAccessibilityDelegate_native* entry points inside pulp-view (static lib). Nothing inside libpulp.so references them — the only callers are on the Kotlin side (PulpAccessibility.kt) — so the Android linker is free to strip them under default dead-code elimination. At runtime TalkBack's first node-tree walk then hits UnsatisfiedLinkError. PR #148 tried to fix this by whole-archiving pulp-view. That pulled SDL3's libSDL3.a in transitively, and SDL3 defines its own JNI_OnLoad, colliding with core/platform/src/android/jni_bridge.cpp:41. #148 was closed. This PR uses the narrower `-Wl,--undefined=<symbol>` approach: force- reference each of the nine TalkBack JNI exports in pulp-jni's link options. The linker then keeps the accessibility_android.cpp object file alive without dragging any other sections of pulp-view (or its SDL3 transitive closure) into libpulp.so. No behaviour change on non-Android builds (the whole pulp-jni target is gated on ANDROID). On Android, the nine forced references grow libpulp.so by the single accessibility_android.cpp object file — same footprint PR #127 intended when it first landed TalkBack. * Fix macOS AU v2 plugin bundles: pin CXX_STANDARD=23 on ${target}_AU ViewBridge Phase 3 (#146) added au_v2_cocoa_view.mm to each plugin's ${target}_AU MODULE target via PulpUtils.cmake's pulp_add_plugin helper. The .mm compiles inside that AU target, not pulp-format, so it does NOT inherit pulp-format's `target_compile_features(... PUBLIC cxx_std_23)` PUBLIC setting — CMake only propagates compile features when the consumer links against the target, not when its sources are merely `add_library(... src1 src2 ...)`-ed in alongside. AUUtility.h in AudioUnitSDK 1.4 uses std::expected / std::unexpected (C++23). Apple clang only exposes those at -std=c++23. Result on github-hosted macos-14 runners (clang 17): every plugin AU target fails to build with 'no template named unexpected in namespace std'. Pin CXX_STANDARD=23 + CXX_STANDARD_REQUIRED=ON on ${target}_AU directly. Same rationale documented at core/format/CMakeLists.txt L76 for the pulp-format target. * Fix macOS AU v2 (follow-up): .mm files need OBJCXX_STANDARD=23 too CXX_STANDARD=23 alone doesn't apply to .mm sources — CMake treats them as Objective-C++ (OBJCXX), a separate language with its own OBJCXX_STANDARD property. Previous commit 1e3b4f9 only set the C++ standard, so au_v2_cocoa_view.mm still compiled at the default C++17 and AUUtility.h's std::expected still failed. Add OBJCXX_STANDARD=23 + OBJCXX_STANDARD_REQUIRED=ON alongside the existing CXX_STANDARD so both C++ and Objective-C++ TUs in ${target}_AU pick up the required standard.
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.
Summary
Resolves the P1 Codex finding from PR #132 that was merged unresolved:
pulp-viewneeds to be wrapped in--whole-archiveso theJava_com_pulp_accessibility_*JNI entry points survive the Android linker's dead-code elimination.Why this is still an issue on main
core/view/platform/android/accessibility_android.cppdefines every TalkBack JNI entry point (nativeGetAccessibilityNodeCount,nativeGetNodeRole,nativePerformAction, etc.). The only callers are inandroid/app/src/main/kotlin/com/pulp/accessibility/PulpAccessibility.kt— nothing insidelibpulp.soreferences them.CMakeLists.txtL536-541 currently wraps onlypulp-platform,pulp-audio, andpulp-renderin--whole-archive;pulp-viewis absent. The linker is therefore free to strip the JNI symbols, producingUnsatisfiedLinkErrorthe first time TalkBack queries the node tree.Compile-time CI passes because the symbols are emitted into
libpulp-view.a; the failure only surfaces at runtime on a device with accessibility services enabled.Fix
Add
$<TARGET_FILE:pulp-view>to the existing--whole-archiveblock inCMakeLists.txt. Mirrors the pattern already used forpulp-platform/pulp-audio/pulp-render.Test plan