Learning phase Alert
I am developing an AI chat desktop application targeting Apple M chips. The app utilizes embedding models and reranker models, for which I chose Rust-Bert due to its capability to handle such models efficiently. Rust-Bert relies on tch, the Rust bindings for LibTorch.
To enhance the user experience, I want to bundle the LibTorch library, specifically for the MPS (Metal Performance Shaders) backend, with the application. This would prevent users from needing to install LibTorch separately, making the app more user-friendly.
However, I am having trouble locating precompiled binaries of LibTorch for the MPS backend that can be bundled directly into the application via the cargo build.rs file. I need help finding the appropriate binaries or an alternative solution to bundle the library with the app during the build process.
This is the build.rs file
use std::env;
use dirs::home_dir;
fn main() {
// Path to the LibTorch binaries on macOS (custom location)
println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=11.0");
// Link necessary macOS system frameworks
println!("cargo:rustc-link-arg=-framework");
println!("cargo:rustc-link-arg=CoreML");
println!("cargo:rustc-link-arg=-framework");
println!("cargo:rustc-link-arg=Foundation");
println!("cargo:rustc-link-arg=-framework");
println!("cargo:rustc-link-arg=CoreFoundation");
if let Some(home_dir) = home_dir() {
// Specify the SDK path
let sdk_path = std::process::Command::new("xcrun")
.args(&["--show-sdk-path"])
.output()
.expect("Failed to execute xcrun")
.stdout;
let sdk_path = String::from_utf8(sdk_path).unwrap().trim().to_string();
println!("cargo:rustc-link-arg=-isysroot");
println!("cargo:rustc-link-arg={}", sdk_path);
let libtorch_path = home_dir.join(".pyano").join("binaries");
let libtorch_path_str = libtorch_path.to_str().expect("Invalid libtorch path");
// Ensure the dynamic linker knows where to find the LibTorch libraries
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", libtorch_path_str);
// Ensure the dynamic linker knows where to find the LibTorch libraries
println!("cargo:rustc-link-search=native={}", libtorch_path_str);
println!("cargo:rustc-link-search={}", libtorch_path_str);
// Set DYLD_LIBRARY_PATH without overwriting if it already exists
let current_dyld_path = env::var("DYLD_LIBRARY_PATH").unwrap_or_default();
let new_dyld_path = format!("{}:{}", libtorch_path.display(), current_dyld_path);
println!("cargo:rustc-env=DYLD_LIBRARY_PATH={}", new_dyld_path);
// Avoid adding duplicate `-ltorch` link argument
println!("cargo:rustc-link-arg=-ltorch");
// Link static libraries
println!("cargo:rustc-link-lib=static=XNNPACK");
println!("cargo:rustc-link-lib=static=clog");
println!("cargo:rustc-link-lib=static=cpuinfo");
println!("cargo:rustc-link-lib=static=cpuinfo_internals");
println!("cargo:rustc-link-lib=static=fmt");
println!("cargo:rustc-link-lib=static=foxi_loader");
println!("cargo:rustc-link-lib=static=gloo");
println!("cargo:rustc-link-lib=static=kineto");
println!("cargo:rustc-link-lib=static=nnpack");
println!("cargo:rustc-link-lib=static=nnpack_reference_layers");
println!("cargo:rustc-link-lib=static=onnx");
println!("cargo:rustc-link-lib=static=onnx_proto");
println!("cargo:rustc-link-lib=static=protobuf-lite");
println!("cargo:rustc-link-lib=static=protobuf");
println!("cargo:rustc-link-lib=static=protoc");
println!("cargo:rustc-link-lib=static=pthreadpool");
println!("cargo:rustc-link-lib=static=pytorch_qnnpack");
println!("cargo:rustc-link-lib=static=tensorpipe");
println!("cargo:rustc-link-lib=static=tensorpipe_uv");
println!("cargo:rustc-link-lib=static=uv_a");
// Link dynamic libraries
println!("cargo:rustc-link-lib=dylib=torch_cpu"); // Add any other required libraries
println!("cargo:rustc-link-lib=dylib=torch");
println!("cargo:rustc-link-lib=dylib=c10"); // Add any other required libraries
println!("cargo:rustc-link-lib=dylib=fbjni"); // Add any other required libraries
println!("cargo:rustc-link-lib=dylib=omp"); // Add any other required libraries
println!("cargo:rustc-link-lib=dylib=pytorch_jni"); // Add any other required libraries
println!("cargo:rustc-link-lib=dylib=shm"); // Add any other required libraries
println!("cargo:rustc-link-lib=dylib=torch_global_deps"); // Add any other required libraries
println!("cargo:rustc-link-lib=dylib=torch_python"); // Add any other required libraries
// println!("cargo:rustc-env=TORCH_USE_MPS=1");
} else {
panic!("Home directory not found");
}
}
all the static and dynamic libs for Libtorch has been downloaded from Pytorch official https://download.pytorch.org/libtorch/cpu/libtorch-macos-arm64-2.4.1.zip
and unzippped at the desired location ~/.pyano/binaries
When I am building with this command
cargo build --target aarch64-apple-darwin
I am getting these errors
= note: ld: warning: ignoring duplicate libraries: '-lc++', '-lc10', '-liconv', '-ltorch', '-ltorch_cpu'
Undefined symbols for architecture arm64:
"at::_ops::empty_like::call(at::Tensor const&, c10::optional<c10::ScalarType>, c10::optional<c10::Layout>, c10::optional<c10::Device>, c10::optional<bool>, c10::optional<c10::MemoryFormat>)", referenced from:
at::empty_like(at::Tensor const&, c10::TensorOptions, c10::optional<c10::MemoryFormat>) in libtorch_sys-e3bcd271e4210a45.rlib[4](19072f24a82f85ae-torch_api.o)
"at::_ops::layer_norm::call(at::Tensor const&, c10::ArrayRef<c10::SymInt>, c10::optional<at::Tensor> const&, c10::optional<at::Tensor> const&, double, bool)", referenced from:
at::layer_norm(at::Tensor const&, c10::ArrayRef<long long>, c10::optional<at::Tensor> const&, c10::optional<at::Tensor> const&, double, bool) in libtorch_sys-e3bcd271e4210a45.rlib[5](19072f24a82f85ae-torch_api_generated.o)
"at::_ops::zeros_like::call(at::Tensor const&, c10::optional<c10::ScalarType>, c10::optional<c10::Layout>, c10::optional<c10::Device>, c10::optional<bool>, c10::optional<c10::MemoryFormat>)", referenced from:
```
```
I have tried everything, Updating xcode to latest version, setting the env inside the main function too but none of them is working and still getting the same error.
Any help is deeply appreciated .!!!