From 3d2811dcaef8a65b4a8db8952a0633e7a1ad9c1f Mon Sep 17 00:00:00 2001 From: sim Date: Fri, 21 Aug 2026 14:49:55 +0800 Subject: [PATCH] fix(release): link Apple compiler runtime for MLX --- .../macos-compiler-runtime-contract.test.mjs | 16 +++++++++ openless-all/app/src-tauri/build.rs | 36 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 openless-all/app/scripts/macos-compiler-runtime-contract.test.mjs diff --git a/openless-all/app/scripts/macos-compiler-runtime-contract.test.mjs b/openless-all/app/scripts/macos-compiler-runtime-contract.test.mjs new file mode 100644 index 00000000..6c1e4c6e --- /dev/null +++ b/openless-all/app/scripts/macos-compiler-runtime-contract.test.mjs @@ -0,0 +1,16 @@ +import { readFile } from 'node:fs/promises'; + +const buildScript = await readFile(new URL('../src-tauri/build.rs', import.meta.url), 'utf8'); +const requiredFragments = [ + '-print-resource-dir', + 'rustc-link-search=native=', + 'clang_rt.osx', +]; + +for (const fragment of requiredFragments) { + if (!buildScript.includes(fragment)) { + throw new Error(`macOS compiler runtime link contract is missing: ${fragment}`); + } +} + +console.log('macOS compiler runtime link contract passed'); diff --git a/openless-all/app/src-tauri/build.rs b/openless-all/app/src-tauri/build.rs index e82910c3..3a556ec9 100644 --- a/openless-all/app/src-tauri/build.rs +++ b/openless-all/app/src-tauri/build.rs @@ -18,6 +18,10 @@ fn main() { build_qwen_asr(target_os); } + if target_os == "macos" { + link_macos_compiler_runtime(); + } + if target_os == "android" { link_android_cpp_runtime(); } @@ -25,6 +29,38 @@ fn main() { tauri_build::build(); } +/// MLX uses `__builtin_available` for newer Metal APIs. Rust links with +/// `-nodefaultlibs`, so the availability helper from Apple compiler-rt must be +/// added explicitly or Apple Silicon release links fail on macOS 14 targets. +fn link_macos_compiler_runtime() { + let compiler = cc::Build::new().get_compiler(); + let output = std::process::Command::new(compiler.path()) + .arg("-print-resource-dir") + .output() + .expect("failed to query the macOS compiler resource directory"); + if !output.status.success() { + panic!( + "macOS compiler did not return its resource directory (status {})", + output.status + ); + } + + let resource_dir = String::from_utf8(output.stdout) + .expect("macOS compiler resource directory was not UTF-8") + .trim() + .to_owned(); + let runtime_dir = std::path::PathBuf::from(resource_dir).join("lib").join("darwin"); + if !runtime_dir.join("libclang_rt.osx.a").exists() { + panic!( + "macOS compiler runtime not found at {}", + runtime_dir.display() + ); + } + + println!("cargo:rustc-link-search=native={}", runtime_dir.display()); + println!("cargo:rustc-link-lib=static=clang_rt.osx"); +} + /// cpal → oboe → oboe-sys 会编译 C++;最终 cdylib 需显式链接 NDK libc++。 fn link_android_cpp_runtime() { // oboe-ext 已部分静态链入 libc++;补链 c++abi 提供 __cxa_pure_virtual 等 ABI 符号。