use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, fs};
fn preflight_checks() {
if let Ok(output) = Command::new("xcrun").args(["--find", "cc"]).output() {
if output.status.code() == Some(69) {
println!(
"cargo:warning=Xcode license has not been accepted. \
Run `sudo xcodebuild -license` and retry the build."
);
}
}
match Command::new("xcrun")
.args(["-sdk", "macosx", "--find", "metal"])
.output()
{
Ok(output) if !output.status.success() => {
let stderr = String::from_utf8_lossy(&output.stderr);
if stderr.contains("missing Metal Toolchain")
|| stderr.contains("unable to find utility")
{
println!(
"cargo:warning=Metal Toolchain is not installed. \
Run `xcodebuild -downloadComponent MetalToolchain` and retry the build."
);
}
}
Err(_) => {
println!(
"cargo:warning=Could not run `xcrun` — is Xcode or the \
Command Line Tools installed?"
);
}
_ => {} }
}
fn find_metallib(build_dir: &Path) -> Option<PathBuf> {
let build_root = build_dir
.parent()? .parent()?;
let entries = fs::read_dir(build_root).ok()?;
for entry in entries.flatten() {
let name = entry.file_name();
let name_str = name.to_string_lossy();
if name_str.starts_with("mlx-sys-") {
let candidates = [
entry.path().join("out/build/lib/mlx.metallib"),
entry
.path()
.join("out/build/_deps/mlx-build/mlx/backend/metal/kernels/mlx.metallib"),
];
for candidate in &candidates {
if candidate.exists() {
return Some(candidate.clone());
}
}
}
}
None
}
fn stable_metallib_dir() -> Option<PathBuf> {
let home = env::var("HOME").ok()?;
Some(PathBuf::from(home).join(".mlx").join("lib"))
}
fn main() {
preflight_checks();
let out_dir = match env::var("OUT_DIR") {
Ok(d) => PathBuf::from(d),
Err(_) => return,
};
let metallib_src = match find_metallib(&out_dir) {
Some(p) => p,
None => {
println!(
"cargo:warning=Could not find mlx.metallib in build output. \
`cargo install` users may need to copy it manually."
);
return;
}
};
let stable_dir = match stable_metallib_dir() {
Some(d) => d,
None => return,
};
if let Err(e) = fs::create_dir_all(&stable_dir) {
println!(
"cargo:warning=Failed to create {}: {}",
stable_dir.display(),
e
);
return;
}
let target = stable_dir.join("mlx.metallib");
match fs::copy(&metallib_src, &target) {
Ok(_) => {
println!(
"cargo:warning=Copied mlx.metallib to {} for runtime discovery",
target.display()
);
}
Err(e) => {
println!(
"cargo:warning=Failed to copy mlx.metallib to {}: {}",
target.display(),
e
);
}
}
}