From d216dcc7a39bddbbe087f5b33abcd85521e5c111 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Thu, 9 Apr 2026 15:17:34 +0400 Subject: [PATCH] =?UTF-8?q?step=20E=20fix=20(Option=203):=20bake=20android?= =?UTF-8?q?24=E2=86=9226=20clang=20shim=20into=20image?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Incremental Step E (commit 4250f1b) proved that merely compiling the Oboe C++ bridge into libwzp_desktop_lib.so — with NO Rust-side FFI bindings, no function calls — resurrects the __init_tcb+4 / pthread_ create SIGSEGV at WryActivity.onCreate. Bisection: build #17 (baseline) ✓ build #18 (Step A, hello.c) ✓ build #19 (Step B, wzp-client dep) ✓ build #21 (Step C, engine mod compiled) ✓ build #22 (Step D, getauxval_fix.c) ✓ build #23 (Step E, Oboe C++ compiled) ✗ — __init_tcb+4 crash Root cause: tauri-cli hard-codes `aarch64-linux-android24-clang` as the Rust linker. Without any C++ code in the .so, libstd's pthread_create reference gets resolved against the dynamic libc.so. The moment we add a C++ static library that links against libc++_shared, the link-time resolution pulls in the API-24 libc.a static pthread_create stub — and Rust's libstd then also calls that stub instead of libc.so's real one. The stub calls __init_tcb which SIGSEGVs because bionic's TCB state only exists for static-libc main executables, not .so's loaded via dlopen. API-26 NDK has proper dynamic bindings that resolve correctly. Option 3 fix: at image build time, replace every NDK aarch64-linux-android24-clang (and armv7/x86_64/i686, clang/clang++) binary with a one-line shell script that exec()s the corresponding android26-clang. Since tauri-cli invokes the linker via absolute path, PATH and env var overrides fail — but replacing the binary on disk inside the image is guaranteed to take effect. The legacy wzp-android crate doesn't need this because cargo-ndk respects .cargo/config.toml where a crate-level linker override is set. Only changing the Dockerfile here. Next: rebuild the image no-cache, retry Step E, and if the baseline holds, proceed to Steps F/G. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/Dockerfile.android-builder | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/scripts/Dockerfile.android-builder b/scripts/Dockerfile.android-builder index b5ea21f..fd07b46 100644 --- a/scripts/Dockerfile.android-builder +++ b/scripts/Dockerfile.android-builder @@ -74,6 +74,30 @@ RUN yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses > /dev/nu "platform-tools" \ 2>&1 | grep -v '^\[' > /dev/null +# Work around the API-24 libc.a stub in the NDK. Any C++ static lib we +# link into libwzp_desktop_lib.so (e.g. the Oboe audio bridge) pulls in +# bionic's static pthread_create from API-24 libc.a via libc++_shared, +# and that pthread_create crashes at __init_tcb+4 when called from a +# .so loaded via dlopen (the static stub expects libc init state that +# only exists for main executables). API-26 has the proper runtime +# bindings. Tauri-cli hard-codes aarch64-linux-android24-clang as the +# linker and ignores .cargo/config.toml overrides, so the only sure +# fix is to replace the NDK's ${abi}24-clang binary itself with a +# shim that exec()s the ${abi}26-clang equivalent. Applies to all four +# ABIs × {clang, clang++}. The legacy wzp-android crate works without +# this because cargo-ndk honours a crate-level linker override; the +# shim is the minimal targeted fix for the cargo-tauri build path. +# Added as Option 3 for the incremental Step E regression (commit 4250f1b). +RUN set -eux; \ + BIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin; \ + for abi in aarch64-linux-android armv7a-linux-androideabi i686-linux-android x86_64-linux-android; do \ + for suffix in clang clang++; do \ + mv "$BIN/${abi}24-${suffix}" "$BIN/${abi}24-${suffix}.orig"; \ + printf '#!/bin/sh\nexec "%s/%s26-%s" "$@"\n' "$BIN" "$abi" "$suffix" > "$BIN/${abi}24-${suffix}"; \ + chmod +x "$BIN/${abi}24-${suffix}"; \ + done; \ + done + # Make SDK world-readable so builder user can access it RUN chmod -R a+rX $ANDROID_HOME