fix: also link libc++abi for RTTI — resolve missing __class_type_info vtable

- Compile all 62 Oboe source files (was headers-only, missing symbols)
- Link libc++_static + libc++abi with NDK sysroot search path
- Bump linker target from android21 to android26 (fixes pthread_atfork)
- Link liblog + libOpenSLES for Oboe runtime deps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude
2026-04-05 05:48:49 +00:00
parent 64566e9acb
commit a8dd0c2f57
3 changed files with 32 additions and 11 deletions

View File

@@ -1,5 +1,5 @@
[target.aarch64-linux-android]
linker = "aarch64-linux-android21-clang"
linker = "aarch64-linux-android26-clang"
[target.armv7-linux-androideabi]
linker = "armv7a-linux-androideabi21-clang"

View File

@@ -4,21 +4,27 @@ fn main() {
let target = std::env::var("TARGET").unwrap_or_default();
if target.contains("android") {
// On Android, try to build with Oboe. If Oboe is not available,
// fall back to the stub (audio will need to be provided via JNI).
let oboe_dir = fetch_oboe();
match oboe_dir {
Some(oboe_path) => {
println!("cargo:warning=Building with Oboe from {:?}", oboe_path);
cc::Build::new()
let mut build = cc::Build::new();
build
.cpp(true)
.std("c++17")
.cpp_link_stdlib(None)
.file("cpp/oboe_bridge.cpp")
.include("cpp")
.include(oboe_path.join("include"))
.include(oboe_path.join("src"))
.define("WZP_HAS_OBOE", None)
.compile("oboe_bridge");
.file("cpp/oboe_bridge.cpp");
// Compile all Oboe source files
let src_dir = oboe_path.join("src");
add_cpp_files_recursive(&mut build, &src_dir);
build.compile("oboe_bridge");
}
None => {
println!("cargo:warning=Oboe not found, building with stub");
@@ -36,8 +42,6 @@ fn main() {
// libc++_static.a — STL (containers, strings, algorithms)
// libc++abi.a — ABI (RTTI, exceptions, typeinfo vtables)
// Both are required; cc crate's cpp_link_stdlib only handles the first.
//
// We also need to tell the linker where to find them in the NDK sysroot.
if let Ok(ndk) = std::env::var("ANDROID_NDK_HOME") {
let arch = if target.contains("aarch64") {
"aarch64-linux-android"
@@ -53,6 +57,10 @@ fn main() {
}
println!("cargo:rustc-link-lib=static=c++_static");
println!("cargo:rustc-link-lib=static=c++abi");
// Oboe needs liblog and libOpenSLES from Android
println!("cargo:rustc-link-lib=log");
println!("cargo:rustc-link-lib=OpenSLES");
} else {
// Non-Android: always use stub
cc::Build::new()
@@ -64,18 +72,31 @@ fn main() {
}
}
/// Recursively add all .cpp files from a directory to a cc::Build.
fn add_cpp_files_recursive(build: &mut cc::Build, dir: &std::path::Path) {
if !dir.is_dir() {
return;
}
for entry in std::fs::read_dir(dir).unwrap() {
let entry = entry.unwrap();
let path = entry.path();
if path.is_dir() {
add_cpp_files_recursive(build, &path);
} else if path.extension().map_or(false, |e| e == "cpp") {
build.file(&path);
}
}
}
/// Try to find or fetch Oboe headers.
/// Returns the path to the Oboe source root (containing include/ directory).
fn fetch_oboe() -> Option<PathBuf> {
let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
let oboe_dir = out_dir.join("oboe");
// Check if already fetched
if oboe_dir.join("include").join("oboe").join("Oboe.h").exists() {
return Some(oboe_dir);
}
// Try to clone Oboe from GitHub
let status = std::process::Command::new("git")
.args([
"clone",

Binary file not shown.