Summary
When a binary using mlx-rs is installed via cargo install <crate>, it fails at runtime with:
MLX error: Failed to load the default metallib. library not found library not found library not found
The issue is that mlx-sys's CMake build defines METAL_PATH as an absolute path to the metallib inside Cargo's temp build directory:
-DMETAL_PATH="/var/folders/.../T/cargo-installXXXX/release/build/mlx-sys-.../mlx.metallib"
This path is compiled into device.cpp.o. When cargo install finishes, only the binary is copied to ~/.cargo/bin/ — the temp build dir (and the metallib in it) is deleted.
MLX's metallib search order
From device.cpp, MLX searches in order:
- Co-located with the binary (
get_binary_directory() / mlx.metallib)
- Bundle resources
- SwiftPM bundle
- Compile-time
METAL_PATH (the broken fallback)
Workaround
Copying the metallib next to the installed binary works because of search path #1:
cp target/release/build/mlx-sys-*/out/build/_deps/mlx-build/mlx/backend/metal/kernels/mlx.metallib ~/.cargo/bin/
Building from source (where target/ persists) also works fine because METAL_PATH still points to a valid location.
Potential fix
The build.rs in mlx-sys could copy mlx.metallib to a location that cargo install preserves. However, cargo install only copies the final binary — it doesn't preserve any other build artifacts.
Some ideas:
- Use
include_bytes! to embed the metallib in the binary and write it to disk at runtime (it's ~84MB though, so this bloats the binary significantly)
- Set
METAL_PATH to a well-known stable location like ~/.local/share/mlx/mlx.metallib and copy it there during build
- Document that downstream crates using mlx-rs should be installed from source
Environment
- macOS 26.3 (arm64, Apple Silicon)
- Rust 1.93.0
- mlx-rs 0.25.3 / mlx-sys 0.2.0
Reproduction
cargo install voice # any crate that uses mlx-rs
voice "hello" # fails with metallib error
This affects the voice TTS crate (and likely any binary crate using mlx-rs).
Summary
When a binary using mlx-rs is installed via
cargo install <crate>, it fails at runtime with:The issue is that
mlx-sys's CMake build definesMETAL_PATHas an absolute path to the metallib inside Cargo's temp build directory:This path is compiled into
device.cpp.o. Whencargo installfinishes, only the binary is copied to~/.cargo/bin/— the temp build dir (and the metallib in it) is deleted.MLX's metallib search order
From
device.cpp, MLX searches in order:get_binary_directory()/mlx.metallib)METAL_PATH(the broken fallback)Workaround
Copying the metallib next to the installed binary works because of search path #1:
Building from source (where
target/persists) also works fine becauseMETAL_PATHstill points to a valid location.Potential fix
The
build.rsin mlx-sys could copymlx.metallibto a location thatcargo installpreserves. However,cargo installonly copies the final binary — it doesn't preserve any other build artifacts.Some ideas:
include_bytes!to embed the metallib in the binary and write it to disk at runtime (it's ~84MB though, so this bloats the binary significantly)METAL_PATHto a well-known stable location like~/.local/share/mlx/mlx.metalliband copy it there during buildEnvironment
Reproduction
This affects the voice TTS crate (and likely any binary crate using mlx-rs).