build: Android APK builds working — debug (8.9MB) and release (2.0MB)
- Fix C++ std::std:: double namespace in oboe_bridge.cpp - Auto-fetch Oboe headers from GitHub in build.rs - Configure cargo cross-compilation (.cargo/config.toml) with NDK linkers - Fix Gradle settings (dependencyResolutionManagement), signing configs, Compose LinearProgressIndicator API, and Android manifest theme - Add Gradle wrapper, .gitignore for build artifacts - arm64-v8a only (raptorq crate incompatible with armv7 32-bit) - Release APK: 2.0MB signed with wzp-release key - Debug APK: 8.9MB signed with wzp-debug key Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,15 +1,36 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let target = std::env::var("TARGET").unwrap_or_default();
|
||||
|
||||
if target.contains("android") {
|
||||
// Real Oboe build for Android targets
|
||||
cc::Build::new()
|
||||
.cpp(true)
|
||||
.std("c++17")
|
||||
.file("cpp/oboe_bridge.cpp")
|
||||
.include("cpp")
|
||||
.compile("oboe_bridge");
|
||||
// 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()
|
||||
.cpp(true)
|
||||
.std("c++17")
|
||||
.file("cpp/oboe_bridge.cpp")
|
||||
.include("cpp")
|
||||
.include(oboe_path.join("include"))
|
||||
.define("WZP_HAS_OBOE", None)
|
||||
.compile("oboe_bridge");
|
||||
}
|
||||
None => {
|
||||
println!("cargo:warning=Oboe not found, building with stub");
|
||||
cc::Build::new()
|
||||
.cpp(true)
|
||||
.std("c++17")
|
||||
.file("cpp/oboe_stub.cpp")
|
||||
.include("cpp")
|
||||
.compile("oboe_bridge");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Stub for host builds / testing
|
||||
// Non-Android: always use stub
|
||||
cc::Build::new()
|
||||
.cpp(true)
|
||||
.std("c++17")
|
||||
@@ -18,3 +39,37 @@ fn main() {
|
||||
.compile("oboe_bridge");
|
||||
}
|
||||
}
|
||||
|
||||
/// 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",
|
||||
"--depth=1",
|
||||
"--branch=1.8.1",
|
||||
"https://github.com/google/oboe.git",
|
||||
oboe_dir.to_str().unwrap(),
|
||||
])
|
||||
.status();
|
||||
|
||||
match status {
|
||||
Ok(s) if s.success() => {
|
||||
if oboe_dir.join("include").join("oboe").join("Oboe.h").exists() {
|
||||
Some(oboe_dir)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
oboe::AudioStream* stream,
|
||||
void* audioData,
|
||||
int32_t numFrames) override {
|
||||
if (!g_running.load(std::std::memory_order_relaxed) || !g_rings) {
|
||||
if (!g_running.load(std::memory_order_relaxed) || !g_rings) {
|
||||
return oboe::DataCallbackResult::Stop;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
auto result = stream->calculateLatencyMillis();
|
||||
if (result) {
|
||||
g_capture_latency_ms.store(static_cast<float>(result.value()),
|
||||
std::std::memory_order_relaxed);
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
return oboe::DataCallbackResult::Continue;
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
oboe::AudioStream* stream,
|
||||
void* audioData,
|
||||
int32_t numFrames) override {
|
||||
if (!g_running.load(std::std::memory_order_relaxed) || !g_rings) {
|
||||
if (!g_running.load(std::memory_order_relaxed) || !g_rings) {
|
||||
memset(audioData, 0, numFrames * sizeof(int16_t));
|
||||
return oboe::DataCallbackResult::Stop;
|
||||
}
|
||||
@@ -140,7 +140,7 @@ public:
|
||||
auto result = stream->calculateLatencyMillis();
|
||||
if (result) {
|
||||
g_playout_latency_ms.store(static_cast<float>(result.value()),
|
||||
std::std::memory_order_relaxed);
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
return oboe::DataCallbackResult::Continue;
|
||||
@@ -155,7 +155,7 @@ static PlayoutCallback g_playout_cb;
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int wzp_oboe_start(const WzpOboeConfig* config, const WzpOboeRings* rings) {
|
||||
if (g_running.load(std::std::memory_order_relaxed)) {
|
||||
if (g_running.load(std::memory_order_relaxed)) {
|
||||
LOGW("wzp_oboe_start: already running");
|
||||
return -1;
|
||||
}
|
||||
@@ -200,13 +200,13 @@ int wzp_oboe_start(const WzpOboeConfig* config, const WzpOboeRings* rings) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
g_running.store(true, std::std::memory_order_release);
|
||||
g_running.store(true, std::memory_order_release);
|
||||
|
||||
// Start both streams
|
||||
result = g_capture_stream->requestStart();
|
||||
if (result != oboe::Result::OK) {
|
||||
LOGE("Failed to start capture: %s", oboe::convertToText(result));
|
||||
g_running.store(false, std::std::memory_order_release);
|
||||
g_running.store(false, std::memory_order_release);
|
||||
g_capture_stream->close();
|
||||
g_playout_stream->close();
|
||||
g_capture_stream.reset();
|
||||
@@ -217,7 +217,7 @@ int wzp_oboe_start(const WzpOboeConfig* config, const WzpOboeRings* rings) {
|
||||
result = g_playout_stream->requestStart();
|
||||
if (result != oboe::Result::OK) {
|
||||
LOGE("Failed to start playout: %s", oboe::convertToText(result));
|
||||
g_running.store(false, std::std::memory_order_release);
|
||||
g_running.store(false, std::memory_order_release);
|
||||
g_capture_stream->requestStop();
|
||||
g_capture_stream->close();
|
||||
g_playout_stream->close();
|
||||
@@ -232,7 +232,7 @@ int wzp_oboe_start(const WzpOboeConfig* config, const WzpOboeRings* rings) {
|
||||
}
|
||||
|
||||
void wzp_oboe_stop(void) {
|
||||
g_running.store(false, std::std::memory_order_release);
|
||||
g_running.store(false, std::memory_order_release);
|
||||
|
||||
if (g_capture_stream) {
|
||||
g_capture_stream->requestStop();
|
||||
@@ -250,15 +250,15 @@ void wzp_oboe_stop(void) {
|
||||
}
|
||||
|
||||
float wzp_oboe_capture_latency_ms(void) {
|
||||
return g_capture_latency_ms.load(std::std::memory_order_relaxed);
|
||||
return g_capture_latency_ms.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
float wzp_oboe_playout_latency_ms(void) {
|
||||
return g_playout_latency_ms.load(std::std::memory_order_relaxed);
|
||||
return g_playout_latency_ms.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
int wzp_oboe_is_running(void) {
|
||||
return g_running.load(std::std::memory_order_relaxed) ? 1 : 0;
|
||||
return g_running.load(std::memory_order_relaxed) ? 1 : 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user