Phase 1 of the big refactor. Escape the Tauri Android __init_tcb+4 symbol leak (rust-lang/rust#104707) by making wzp-desktop's Android .so pure Rust — ZERO cc::Build, no cpp/ files, no C++ in the rustc link step. All future C++ (Oboe audio bridge) lives in a new standalone cdylib crate `wzp-native` which is built with cargo-ndk (the same path the legacy wzp-android crate uses successfully on the same phone + same NDK), copied into Tauri's gen/android/app/src/main/jniLibs at build time, and dlopened by wzp-desktop at runtime via libloading. Changes in this commit: - NEW crate crates/wzp-native/ with crate-type = ["cdylib"] only (no staticlib, no rlib — rust#104707 shows mixing staticlib with cdylib leaks non-exported symbols, which is the original bug source). Phase 1 scaffold has TWO extern "C" functions: wzp_native_version() -> i32 (returns 42) wzp_native_hello(buf, cap) -> usize (writes a string) So we can verify dlopen + dlsym + cross-.so FFI end-to-end before adding any real C++. - desktop/src-tauri/cpp/ directory DELETED (7 files gone). - desktop/src-tauri/build.rs reduced to just the git hash capture + tauri_build::build(). No more cc::Build of any kind. - desktop/src-tauri/Cargo.toml: drop cc from build-dependencies, add libloading = "0.8" as an Android-only runtime dep. - desktop/src-tauri/src/lib.rs Builder::setup() now (on Android only) dlopens libwzp_native.so, calls wzp_native_version() and wzp_native_hello(), and logs the result: "wzp-native dlopen OK: version=42 msg=\"hello from wzp-native\"" If this log appears in logcat when the app launches and the home screen still renders, the split-cdylib pipeline is validated and Phase 2 (port the Oboe bridge into wzp-native) can proceed. - scripts/build-tauri-android.sh: insert a `cargo ndk -t arm64-v8a build --release -p wzp-native` step before `cargo tauri android build`, with `-o desktop/src-tauri/gen/android/app/src/main/jniLibs` so the resulting libwzp_native.so lands in the place gradle will package into the final APK. - Workspace Cargo.toml: add crates/wzp-native to [workspace] members. Phase 2 (separate commit, only if Phase 1 works): - Copy cpp/oboe_bridge.{h,cpp} + getauxval_fix.c from the legacy wzp-android crate into crates/wzp-native/cpp/. - Add cc = "1" as a build-dependency on wzp-native (safe: it's a single-cdylib crate with no staticlib, so no symbol leak). - Add build.rs that compiles the Oboe C++ and the wzp-native Rust FFI exposes the audio start/stop/read/write functions. - wzp-desktop::engine.rs dlopens wzp-native at CallEngine::start, uses its audio functions instead of CPAL on Android. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
79 lines
3.1 KiB
TOML
79 lines
3.1 KiB
TOML
[package]
|
|
name = "wzp-desktop"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
description = "WarzonePhone Desktop — encrypted VoIP client"
|
|
default-run = "wzp-desktop"
|
|
|
|
# Library target — required for Tauri mobile (Android/iOS link the app as a cdylib)
|
|
# and also used by the desktop binary below.
|
|
#
|
|
# `staticlib` was DROPPED from crate-type because rust-lang/rust#104707
|
|
# documents that having staticlib alongside cdylib leaks non-exported
|
|
# symbols from staticlibs into the cdylib. Bionic's private `__init_tcb`
|
|
# / `pthread_create` symbols end up bound LOCALLY inside our .so instead
|
|
# of resolved dynamically against libc.so at dlopen time — which crashes
|
|
# at launch as soon as tao tries to std::thread::spawn() from the JNI
|
|
# onCreate callback. The legacy wzp-android crate uses ["cdylib", "rlib"]
|
|
# and runs fine on the same phone with the same NDK + Rust toolchain.
|
|
#
|
|
# iOS Tauri builds that actually need staticlib can re-add it behind a
|
|
# target cfg if we ever ship on iOS.
|
|
[lib]
|
|
name = "wzp_desktop_lib"
|
|
crate-type = ["cdylib", "rlib"]
|
|
|
|
[[bin]]
|
|
name = "wzp-desktop"
|
|
path = "src/main.rs"
|
|
|
|
[build-dependencies]
|
|
tauri-build = { version = "2", features = [] }
|
|
# cc is no longer needed — all C++ moved to crates/wzp-native (built with
|
|
# cargo-ndk and loaded via libloading at runtime). wzp-desktop's .so on
|
|
# Android is now pure Rust.
|
|
|
|
[dependencies]
|
|
tauri = { version = "2", features = [] }
|
|
tauri-plugin-shell = "2"
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
tokio = { version = "1", features = ["full"] }
|
|
tracing = "0.1"
|
|
tracing-subscriber = "0.3"
|
|
anyhow = "1"
|
|
rustls = { version = "0.23", default-features = false, features = ["ring", "std"] }
|
|
|
|
# WarzonePhone crates — protocol layer is platform-independent
|
|
wzp-proto = { path = "../../crates/wzp-proto" }
|
|
wzp-codec = { path = "../../crates/wzp-codec" }
|
|
wzp-fec = { path = "../../crates/wzp-fec" }
|
|
wzp-crypto = { path = "../../crates/wzp-crypto" }
|
|
wzp-transport = { path = "../../crates/wzp-transport" }
|
|
|
|
# wzp-client pulls CPAL + (on macOS) VoiceProcessingIO — desktop only.
|
|
# Android gets an oboe/AAudio backend in Step 3 of the Tauri mobile rewrite.
|
|
[target.'cfg(not(target_os = "android"))'.dependencies]
|
|
wzp-client = { path = "../../crates/wzp-client", features = ["audio", "vpio"] }
|
|
|
|
# Step B: depend on wzp-client on Android WITHOUT the audio/vpio features,
|
|
# so we pull in only the platform-independent modules (call, handshake,
|
|
# audio_ring, codec bindings). Deliberately no imports in lib.rs yet — we
|
|
# only want to verify that compiling + linking these crates on android
|
|
# doesn't regress the working build.
|
|
[target.'cfg(target_os = "android")'.dependencies]
|
|
wzp-client = { path = "../../crates/wzp-client", default-features = false }
|
|
# libloading: runtime dlopen of libwzp_native.so — the standalone cdylib
|
|
# crate that owns all C++ (Oboe bridge). Keeps wzp-desktop's .so free of
|
|
# any C/C++ static archives that would otherwise leak bionic's internal
|
|
# pthread_create into our cdylib and trigger the __init_tcb crash.
|
|
libloading = "0.8"
|
|
|
|
# Platform-specific
|
|
[target.'cfg(target_os = "macos")'.dependencies]
|
|
coreaudio-rs = "0.11"
|
|
|
|
[features]
|
|
default = ["custom-protocol"]
|
|
custom-protocol = ["tauri/custom-protocol"]
|