fn main() {
build_ui();
embed_assets();
}
fn build_ui() {
for path in [
"ui/src/",
"ui/index.html",
"ui/package.json",
"ui/pnpm-lock.yaml",
"ui/vite.config.js",
"ui/svelte.config.js",
"src/ui.rs",
] {
println!("cargo:rerun-if-changed={path}");
}
let path = std::env::var("PATH").unwrap_or_default();
let path = format!("/opt/homebrew/bin:/usr/local/bin:{path}");
let manifest_dir = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
if manifest_dir.join("Cargo.toml.orig").exists() {
if !manifest_dir.join("ui/dist/index.html").exists() {
panic!("the package is missing ui/dist; it was published without a built UI");
}
return;
}
let pnpm_found = std::process::Command::new("pnpm")
.arg("--version")
.env("PATH", &path)
.output()
.map(|o| o.status.success())
.unwrap_or(false);
if !pnpm_found {
if !std::path::Path::new("ui/dist/index.html").exists() {
panic!(
"pnpm not found and ui/dist/index.html is missing; \
run: pnpm --dir ui install && pnpm --dir ui build"
);
}
return;
}
let run = |args: &[&str]| {
std::process::Command::new("pnpm")
.args(args)
.env("PATH", &path)
.status()
.map(|s| s.success())
.unwrap_or(false)
};
let built =
run(&["--dir", "ui", "install", "--frozen-lockfile"]) && run(&["--dir", "ui", "build"]);
if !built {
panic!("UI build failed; run manually: pnpm --dir ui install && pnpm --dir ui build");
}
}
fn embed_assets() {
let dir =
std::path::Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("ui/dist/assets");
let mut names: Vec<String> = std::fs::read_dir(&dir)
.unwrap_or_else(|e| panic!("reading {}: {e}; build the UI first", dir.display()))
.filter_map(|entry| entry.ok())
.filter(|entry| entry.path().is_file())
.map(|entry| entry.file_name().to_string_lossy().into_owned())
.collect();
names.sort();
let mut out = String::from("pub static UI_ASSETS: &[(&str, &[u8])] = &[\n");
for name in &names {
out.push_str(&format!(
" ({name:?}, include_bytes!({:?})),\n",
dir.join(name).display().to_string()
));
}
out.push_str("];\n");
let dest = std::path::Path::new(&std::env::var("OUT_DIR").unwrap()).join("ui_assets.rs");
std::fs::write(&dest, out).unwrap_or_else(|e| panic!("writing {}: {e}", dest.display()));
}