From 2718402e960b987a336e400baeeecd89312cd494 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Thu, 9 Apr 2026 13:23:47 +0400 Subject: [PATCH] =?UTF-8?q?fix(android):=20PATH=20wrapper=20to=20redirect?= =?UTF-8?q?=20tauri-cli's=20android24-clang=20=E2=86=92=20android26?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build #12's instrumented pthread_shim gave us the definitive diagnosis: WZP_pthread_shim: dlsym(RTLD_DEFAULT, pthread_create) returned NULL: libdl.a is a stub --- use libdl.so instead Tauri-cli invokes `aarch64-linux-android24-clang` as the linker and the API-24 NDK sysroot ships *stub* libdl.a / libc.a: they compile fine but every symbol crashes if called, because they're meant to coexist with a separate dynamic .so that the dynamic linker provides at runtime. Rust's pre-built libstd.rlib has static calls into those stubs baked in, so no matter what we do at link time the broken code lands in the .so. Env-var overrides of CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER don't stick — tauri-cli resets them before invoking cargo. So instead of fighting the env, we put a wrapper on $PATH, literally named `aarch64-linux-android24-clang`, that exec()s the android26 version. When tauri-cli looks up android24-clang via PATH, it gets our wrapper, our wrapper runs android26-clang, and suddenly the whole build is using the API-26 NDK sysroot with real dynamic bindings to libc.so / libdl.so. Wrappers are installed for all four ABIs (aarch64, armv7, x86_64, i686) × both suffixes (clang, clang++) directly inside the docker bash -c preamble before any cargo invocation. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build-tauri-android.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/scripts/build-tauri-android.sh b/scripts/build-tauri-android.sh index 7956466..73a1bec 100755 --- a/scripts/build-tauri-android.sh +++ b/scripts/build-tauri-android.sh @@ -166,6 +166,30 @@ docker run --rm \ wzp-android-builder \ bash -c ' set -euo pipefail + +# ─── Linker wrappers ─────────────────────────────────────────────────────── +# Tauri-cli hard-codes aarch64-linux-android24-clang as the Rust linker for +# the aarch64 target, which resolves pthread_create / dlsym / __init_tcb +# against the NDK API-24 *stub* libc.a/libdl.a. Those stubs are designed to +# crash if called — they only exist so the API-24 sysroot compiles, not so +# symbols actually work. API-26 has the real dynamic bindings to libc.so. +# +# Rather than fight tauri-cli to change which clang it invokes, we put a +# wrapper on $PATH that IS named android24-clang but exec()s the android26 +# version. Same trick works for every ABI. +mkdir -p /tmp/wrappers +for abi in aarch64-linux-android armv7a-linux-androideabi i686-linux-android x86_64-linux-android; do + for suffix in clang clang++; do + cat > /tmp/wrappers/${abi}24-${suffix} <>> installed android24→android26 linker wrappers in /tmp/wrappers" + cd /build/source/desktop echo ">>> npm install"