From fc4fb7023251c8b45bd990dd5410f991ba220b6b Mon Sep 17 00:00:00 2001 From: roboomp Date: Tue, 28 Jul 2026 03:39:36 +0000 Subject: [PATCH] fix(natives): restore macos coreaudio capture bindings The 17.1.6 Bazel migration dropped maudio's generate-bindings feature, so the darwin addon shipped maudio-sys's Linux-shaped pregenerated miniaudio bindings. Those bindings omit the MA_SUPPORT_COREAUDIO backend-state union members that the macOS build of miniaudio.c actually contains, producing a Rust/C ABI mismatch: capture callbacks saw zero channels and yielded no PCM. Re-enable generate-bindings for apple targets only. Patch maudio-sys's build script to branch on Cargo's TARGET rather than the build-script host, so a macOS-hosted Linux/Windows cross-build keeps target-family pregenerated bindings instead of incorrectly running Darwin bindgen. Repin the Bazel graph to apply the patch and gate bindgen behind the apple target selects. Fixes #6846 --- Cargo.Bazel.lock | 103 +++++++++++++++++- Cargo.lock | 3 + MODULE.bazel | 10 ++ .../patches/maudio-sys-target-bindings.patch | 38 +++++++ crates/pi-natives/Cargo.toml | 10 ++ packages/natives/CHANGELOG.md | 4 + 6 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 bazel/patches/maudio-sys-target-bindings.patch diff --git a/Cargo.Bazel.lock b/Cargo.Bazel.lock index 30a610bec..6220dec51 100644 --- a/Cargo.Bazel.lock +++ b/Cargo.Bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "895940582b3df625bf97f8d0dbfa4e278a01598c711363c7c09b944c976796d4", + "checksum": "fc307c26a4097bcc99136c3cf6a30b6170ac95277b3f7999f8619c401d44d644", "crates": { "adler2 2.0.1": { "name": "adler2", @@ -2998,6 +2998,15 @@ "compile_data_glob": [ "**" ], + "crate_features": { + "common": [ + "default", + "logging", + "prettyplease", + "runtime" + ], + "selects": {} + }, "deps": { "common": [ { @@ -3020,6 +3029,14 @@ "id": "itertools 0.13.0", "target": "itertools" }, + { + "id": "log 0.4.33", + "target": "log" + }, + { + "id": "prettyplease 0.2.37", + "target": "prettyplease" + }, { "id": "proc-macro2 1.0.107", "target": "proc_macro2" @@ -3065,6 +3082,10 @@ { "id": "clang-sys 1.8.1", "target": "clang_sys" + }, + { + "id": "prettyplease 0.2.37", + "target": "prettyplease" } ], "selects": {} @@ -6417,6 +6438,26 @@ "compile_data_glob": [ "**" ], + "crate_features": { + "common": [ + "clang_10_0", + "clang_11_0", + "clang_3_5", + "clang_3_6", + "clang_3_7", + "clang_3_8", + "clang_3_9", + "clang_4_0", + "clang_5_0", + "clang_6_0", + "clang_7_0", + "clang_8_0", + "clang_9_0", + "libloading", + "runtime" + ], + "selects": {} + }, "deps": { "common": [ { @@ -6430,6 +6471,10 @@ { "id": "libc 0.2.189", "target": "libc" + }, + { + "id": "libloading 0.8.9", + "target": "libloading" } ], "selects": {} @@ -22288,6 +22333,17 @@ "compile_data_glob": [ "**" ], + "crate_features": { + "common": [], + "selects": { + "aarch64-apple-darwin": [ + "generate-bindings" + ], + "x86_64-apple-darwin": [ + "generate-bindings" + ] + } + }, "deps": { "common": [ { @@ -22313,7 +22369,13 @@ "repository": { "Http": { "url": "https://static.crates.io/crates/maudio-sys/0.1.3/download", - "sha256": "f00ae1969d0a389937161b834623e5cba2d8449752a0970d71382cf9a905bb35" + "sha256": "f00ae1969d0a389937161b834623e5cba2d8449752a0970d71382cf9a905bb35", + "patch_args": [ + "-p1" + ], + "patches": [ + "@@//bazel/patches:maudio-sys-target-bindings.patch" + ] } }, "targets": [ @@ -22351,7 +22413,14 @@ "common": [ "default" ], - "selects": {} + "selects": { + "aarch64-apple-darwin": [ + "generate-bindings" + ], + "x86_64-apple-darwin": [ + "generate-bindings" + ] + } }, "deps": { "common": [ @@ -22382,7 +22451,20 @@ "target": "cc" } ], - "selects": {} + "selects": { + "aarch64-apple-darwin": [ + { + "id": "bindgen 0.72.1", + "target": "bindgen" + } + ], + "x86_64-apple-darwin": [ + { + "id": "bindgen 0.72.1", + "target": "bindgen" + } + ] + } } }, "license": "MIT", @@ -32301,6 +32383,12 @@ "compile_data_glob": [ "**" ], + "crate_features": { + "common": [ + "verbatim" + ], + "selects": {} + }, "deps": { "common": [ { @@ -37454,6 +37542,13 @@ "compile_data_glob": [ "**" ], + "crate_features": { + "common": [ + "default", + "std" + ], + "selects": {} + }, "edition": "2015", "version": "1.3.0" }, diff --git a/Cargo.lock b/Cargo.lock index b30d863fb..a26d15a4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -502,6 +502,8 @@ dependencies = [ "cexpr", "clang-sys", "itertools 0.13.0", + "log", + "prettyplease", "proc-macro2", "quote", "regex", @@ -3662,6 +3664,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f00ae1969d0a389937161b834623e5cba2d8449752a0970d71382cf9a905bb35" dependencies = [ + "bindgen", "cc", ] diff --git a/MODULE.bazel b/MODULE.bazel index df090aed4..d62cdd1f6 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -153,6 +153,16 @@ crate.annotation( crate = "tree-sitter-just", build_script_env = {"CFLAGS": "-UNDEBUG"}, ) +# `generate-bindings` is enabled for darwin so miniaudio's Rust bindings match +# its CoreAudio C layout. Build scripts execute for the host, however, so a +# macOS-hosted Linux cross-build also sees that feature. Use Cargo's TARGET to +# keep bindgen darwin-only and select pregenerated bindings for other targets. +crate.annotation( + crate = "maudio-sys", + patches = ["//bazel/patches:maudio-sys-target-bindings.patch"], + patch_args = ["-p1"], +) + use_repo(crate, "crates") diff --git a/bazel/patches/maudio-sys-target-bindings.patch b/bazel/patches/maudio-sys-target-bindings.patch new file mode 100644 index 000000000..779ebda03 --- /dev/null +++ b/bazel/patches/maudio-sys-target-bindings.patch @@ -0,0 +1,38 @@ +--- a/build.rs ++++ b/build.rs +@@ -5,6 +5,12 @@ use cc::Build; + + #[cfg(feature = "generate-bindings")] + fn write_bindings(out_bindings: &std::path::Path) { ++ let target = env::var("TARGET").expect("TARGET must be set by Cargo"); ++ if !target.contains("apple-darwin") { ++ copy_bindings(&target, out_bindings); ++ return; ++ } ++ + let mut builder = bindgen::Builder::default() + .header("native/miniaudio/miniaudio.h") + .clang_arg("-Inative") +@@ -25,11 +31,17 @@ fn write_bindings(out_bindings: &std::path::Path) { + + #[cfg(not(feature = "generate-bindings"))] + fn write_bindings(out_bindings: &std::path::Path) { ++ let target = env::var("TARGET").expect("TARGET must be set by Cargo"); ++ copy_bindings(&target, out_bindings); ++} ++ ++fn copy_bindings(target: &str, out_bindings: &std::path::Path) { + eprintln!("Copying bindings"); +- #[cfg(unix)] +- std::fs::copy("src/pregen_bindings/unix.rs", out_bindings) +- .expect("Failed to copy pre-generated bindings to OUT_DIR"); +- #[cfg(windows)] +- std::fs::copy("src/pregen_bindings/windows.rs", out_bindings) ++ let source = if target.contains("windows") { ++ "src/pregen_bindings/windows.rs" ++ } else { ++ "src/pregen_bindings/unix.rs" ++ }; ++ std::fs::copy(source, out_bindings) + .expect("Failed to copy pre-generated bindings to OUT_DIR"); + } diff --git a/crates/pi-natives/Cargo.toml b/crates/pi-natives/Cargo.toml index 03eda173f..78ce21756 100644 --- a/crates/pi-natives/Cargo.toml +++ b/crates/pi-natives/Cargo.toml @@ -72,6 +72,16 @@ xcap = { version = "=0.9.6", default-features = false } [target.'cfg(target_os = "macos")'.dependencies] tempfile = "=3.27.0" core-graphics = "0.25" +# Regenerate miniaudio FFI bindings from the compiled headers on macOS only. +# The maudio-sys pregenerated `unix.rs` bindings are Linux-shaped: their +# `ma_device`/`ma_context` backend-state unions omit the `#ifdef +# MA_SUPPORT_COREAUDIO` members that the macOS build of miniaudio.c actually +# contains, so shipping them on darwin is an ABI mismatch that silently breaks +# CoreAudio capture (device init/start succeed but no render callbacks fire). +# darwin builds with host Xcode (libclang available), so bindgen is fine here; +# the hermetic zig/musl/windows toolchains keep the bindgen-free pregen path, +# whose bindings are correct for those platforms. +maudio = { workspace = true, features = ["generate-bindings"] } [target.'cfg(unix)'.dependencies] libc.workspace = true diff --git a/packages/natives/CHANGELOG.md b/packages/natives/CHANGELOG.md index 2e309c06f..13d16acc4 100644 --- a/packages/natives/CHANGELOG.md +++ b/packages/natives/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed the macOS (darwin) native addon delivering zero `AudioCapture` callbacks — `/live` could listen without ever capturing microphone audio ([#6846](https://github.com/can1357/oh-my-pi/issues/6846)). The 17.1.6 Bazel migration dropped `maudio`'s `generate-bindings` feature, so darwin shipped `maudio-sys`'s Linux-shaped pregenerated miniaudio bindings, whose `ma_device`/`ma_context` backend-state unions omit the `MA_SUPPORT_COREAUDIO` members present in the macOS build of `miniaudio.c`. The resulting Rust↔C ABI mismatch let device init/start succeed while the CoreAudio render callback never fired. `generate-bindings` is now re-enabled for apple targets only (darwin builds with host Xcode, so bindgen/libclang are available); the hermetic linux/musl/windows toolchains keep the bindgen-free pregenerated bindings, which are correct for those platforms. + ## [17.1.6] - 2026-07-27 ### Changed