use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
fn main() {
println!("cargo:rerun-if-env-changed=SUPERMACHINE_KERNEL_PATH");
println!("cargo:rerun-if-env-changed=SUPERMACHINE_INIT_OCI_PATH");
let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").expect("OUT_DIR set by cargo"));
stage(
"kernel",
"SUPERMACHINE_KERNEL_PATH",
&out_dir.join("kernel"),
);
stage(
"init-oci",
"SUPERMACHINE_INIT_OCI_PATH",
&out_dir.join("init-oci"),
);
}
fn stage(name: &str, env_var: &str, dest: &Path) {
println!("cargo:rerun-if-changed={name}.xz");
if let Some(p) = std::env::var_os(env_var) {
let p = PathBuf::from(p);
if !p.is_file() {
fail(&format!(
"{env_var}={} but the file does not exist",
p.display()
));
}
copy_or_fail(&p, dest);
return;
}
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let xz_path = manifest_dir.join(format!("{name}.xz"));
if !xz_path.is_file() {
fail(&format!(
"{name}.xz not found at {}.\n\
This crate ships compressed kernel + init-oci assets in the\n\
published .crate. If you're building from a fresh git\n\
checkout, run the kernel-build pipeline (see\n\
kernel-build/scripts/) and `xz -k -9` the outputs into\n\
this directory; or set {env_var} to a local file.",
xz_path.display()
));
}
decompress_xz(&xz_path, dest);
}
fn copy_or_fail(src: &Path, dest: &Path) {
if let Some(parent) = dest.parent() {
let _ = fs::create_dir_all(parent);
}
if let Err(e) = fs::copy(src, dest) {
fail(&format!(
"failed to copy {} -> {}: {e}",
src.display(),
dest.display()
));
}
}
fn decompress_xz(src: &Path, dest: &Path) {
if let Some(parent) = dest.parent() {
let _ = fs::create_dir_all(parent);
}
let dest_file = match fs::File::create(dest) {
Ok(f) => f,
Err(e) => fail(&format!("failed to create {}: {e}", dest.display())),
};
let status = Command::new("xz")
.arg("-d")
.arg("-c")
.arg(src)
.stdout(dest_file)
.status();
match status {
Ok(s) if s.success() => {}
Ok(s) => {
let _ = fs::remove_file(dest);
fail(&format!(
"`xz -d -c {}` exited with status {s}\n\
(xz is required to decompress bundled kernel assets;\n\
install via your package manager: `brew install xz`,\n\
`apt install xz-utils`, `dnf install xz`)",
src.display()
));
}
Err(e) => fail(&format!(
"failed to spawn xz: {e}\n\
xz is required to decompress bundled kernel assets;\n\
install via your package manager: `brew install xz`,\n\
`apt install xz-utils`, `dnf install xz`"
)),
}
}
fn fail(msg: &str) -> ! {
eprintln!("supermachine-kernel build.rs: {msg}");
std::process::exit(1);
}