step E.0: drop cpp_link_stdlib entirely (no libc++ linkage)
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) <noreply@anthropic.com>
This commit is contained in:
@@ -37,25 +37,25 @@ fn build_android_native() {
|
|||||||
.file("cpp/getauxval_fix.c")
|
.file("cpp/getauxval_fix.c")
|
||||||
.compile("getauxval_fix");
|
.compile("getauxval_fix");
|
||||||
|
|
||||||
// ─── Step E.1 with STATIC libc++ ───────────────────────────────────────
|
// ─── Step E.0: no C++ stdlib linkage at all ────────────────────────────
|
||||||
// Every cpp_smoke variant (atomic-mutex-thread / atomic-only / empty
|
// c++_shared crashed. c++_static also crashed (same byte stack, new
|
||||||
// function) crashed identically with c++_shared linkage — byte-
|
// offsets because the .so layout shifted). So it's NOT the NEEDED
|
||||||
// identical crash offsets. The cpp code was dead-stripped from the
|
// entry — it's something that happens whenever libc++ code lands in
|
||||||
// final .so in every case, so the only remaining delta was the
|
// our .so, regardless of linkage.
|
||||||
// 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.
|
|
||||||
//
|
//
|
||||||
// Test: swap c++_shared → c++_static. Bundles libc++ code directly
|
// cpp_smoke.cpp is just `extern "C" int wzp_cpp_hello(){return 42;}`
|
||||||
// into our .so, drops the NEEDED entry. If the app launches, we've
|
// — it uses zero C++ features, so we can drop cpp_link_stdlib
|
||||||
// proven the NEEDED libc++_shared.so is the trigger and have a
|
// entirely and the compile still succeeds. No libc++ code gets
|
||||||
// working linkage for adding C++ to Tauri Android cdylibs.
|
// 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");
|
println!("cargo:rerun-if-changed=cpp/cpp_smoke.cpp");
|
||||||
cc::Build::new()
|
cc::Build::new()
|
||||||
.cpp(true)
|
.cpp(true)
|
||||||
.std("c++17")
|
.std("c++17")
|
||||||
.cpp_link_stdlib(Some("c++_static"))
|
.cpp_link_stdlib(None::<&str>)
|
||||||
.file("cpp/cpp_smoke.cpp")
|
.file("cpp/cpp_smoke.cpp")
|
||||||
.compile("wzp_cpp_smoke");
|
.compile("wzp_cpp_smoke");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user