From 47a037368c22951cdab2942427fce05db48ccf64 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Thu, 9 Apr 2026 16:31:53 +0400 Subject: [PATCH] step E.0: drop cpp_link_stdlib entirely (no libc++ linkage) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit c++_shared crashed. c++_static also crashed. Both have libc++ code landing in the final .so — one as a NEEDED dynamic lib, the other bundled statically. So the trigger isn't the NEEDED entry specifically, it's libc++ being present in any form. cpp_smoke.cpp is just 'extern "C" int wzp_cpp_hello() { return 42; }' with zero C++ features used, so we can drop cpp_link_stdlib completely and the compile still succeeds. No libc++ .a or .so referenced at all. If this crashes: the trigger is cc::Build::new().cpp(true) switching rustc's final linker driver from clang to clang++ (which pulls in different default libraries). If this launches: the trigger is libc++'s own static initializers or the libc++ code itself doing something that breaks our .so at dlopen time, and we have a path forward — C++ code that doesn't need libc++ (e.g., a thin C++ bridge to Oboe that uses only POD types at the boundary, with all the STL stuff confined to Oboe's own compilation unit which would still need libc++...). More likely we still need a C-only audio interface like raw AAudio via the ndk Rust crate. Co-Authored-By: Claude Opus 4.6 (1M context) --- desktop/src-tauri/build.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/desktop/src-tauri/build.rs b/desktop/src-tauri/build.rs index 54faaf2..2a61f50 100644 --- a/desktop/src-tauri/build.rs +++ b/desktop/src-tauri/build.rs @@ -37,25 +37,25 @@ fn build_android_native() { .file("cpp/getauxval_fix.c") .compile("getauxval_fix"); - // ─── Step E.1 with STATIC libc++ ─────────────────────────────────────── - // Every cpp_smoke variant (atomic-mutex-thread / atomic-only / empty - // function) crashed identically with c++_shared linkage — byte- - // identical crash offsets. The cpp code was dead-stripped from the - // final .so in every case, so the only remaining delta was the - // NEEDED entry for libc++_shared.so added by - // cargo:rustc-link-lib=c++_shared. Theory: that NEEDED entry (and - // Android's dynamic linker running libc++_shared.so's init_array at - // dlopen time) is the trigger. + // ─── Step E.0: no C++ stdlib linkage at all ──────────────────────────── + // c++_shared crashed. c++_static also crashed (same byte stack, new + // offsets because the .so layout shifted). So it's NOT the NEEDED + // entry — it's something that happens whenever libc++ code lands in + // our .so, regardless of linkage. // - // Test: swap c++_shared → c++_static. Bundles libc++ code directly - // into our .so, drops the NEEDED entry. If the app launches, we've - // proven the NEEDED libc++_shared.so is the trigger and have a - // working linkage for adding C++ to Tauri Android cdylibs. + // cpp_smoke.cpp is just `extern "C" int wzp_cpp_hello(){return 42;}` + // — it uses zero C++ features, so we can drop cpp_link_stdlib + // entirely and the compile still succeeds. No libc++ code gets + // dragged in at all. If the app launches, the trigger is the libc++ + // code itself (probably its .init_array static constructors). If it + // still crashes, the trigger is just `cc::Build::new().cpp(true)` + // switching rustc's linker driver from clang to clang++ and the + // different default library pull-ins that causes. println!("cargo:rerun-if-changed=cpp/cpp_smoke.cpp"); cc::Build::new() .cpp(true) .std("c++17") - .cpp_link_stdlib(Some("c++_static")) + .cpp_link_stdlib(None::<&str>) .file("cpp/cpp_smoke.cpp") .compile("wzp_cpp_smoke");