use std::env;
use std::path::Path;
use std::process::Command;
use walkdir::WalkDir;
fn main() {
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let baml_src = Path::new(&manifest_dir).join("baml_src");
let baml_client_dir = Path::new(&manifest_dir).join("baml_client");
println!("cargo:rerun-if-changed=baml_src/");
let needs_regen = should_regenerate(&baml_src, &baml_client_dir);
if needs_regen {
eprintln!("Generating BAML client code...");
let status = Command::new("npx")
.args([
"@boundaryml/baml",
"generate",
"--from",
baml_src.to_str().unwrap(),
])
.current_dir(&manifest_dir)
.status();
match status {
Ok(s) if s.success() => {
eprintln!("BAML client generated successfully");
}
Ok(s) => {
panic!("BAML generate failed with status: {}", s);
}
Err(e) => {
let fallback = Command::new("baml")
.args(["generate", "--from", baml_src.to_str().unwrap()])
.current_dir(&manifest_dir)
.status();
match fallback {
Ok(s) if s.success() => {
eprintln!("BAML client generated successfully (via baml cli)");
}
_ => {
panic!(
"Failed to run BAML generator. \
Install with: npm install -g @boundaryml/baml\n\
Original error: {}",
e
);
}
}
}
}
}
}
fn should_regenerate(baml_src: &Path, baml_client: &Path) -> bool {
if !baml_client.exists() {
return true;
}
let newest_baml = WalkDir::new(baml_src)
.into_iter()
.filter_map(|e| e.ok())
.map(|e| e.into_path())
.filter(|p| p.extension().map(|e| e == "baml").unwrap_or(false))
.filter_map(|p| p.metadata().ok()?.modified().ok())
.max();
let oldest_generated = WalkDir::new(baml_client)
.into_iter()
.filter_map(|e| e.ok())
.map(|e| e.into_path())
.filter(|p| p.extension().map(|e| e == "rs").unwrap_or(false))
.filter_map(|p| p.metadata().ok()?.modified().ok())
.min();
match (newest_baml, oldest_generated) {
(Some(baml_time), Some(gen_time)) => baml_time > gen_time,
(Some(_), None) => true, (None, _) => false, }
}