use std::path::Path;
use std::process::{Command, Output};
fn run(cmd: &mut Command) -> Result<Output, String> {
let prog = cmd.get_program().to_string_lossy().into_owned();
let out = cmd
.output()
.map_err(|e| format!("{prog} could not be started: {e}"))?;
if !out.status.success() {
let stderr = String::from_utf8_lossy(&out.stderr);
return Err(format!(
"{prog} failed with exit status {}\n{}",
out.status.code().unwrap_or(-1),
stderr.trim()
));
}
Ok(out)
}
fn main() {
let out_dir = std::env::var("OUT_DIR").expect("cargo sets OUT_DIR for build scripts");
let out_so = Path::new(&out_dir).join("dstest_clock.so");
println!("cargo:rerun-if-changed=shim/clock.c");
let host = std::env::var("TARGET").unwrap_or_default();
let result = if host.starts_with("x86_64-unknown-linux") || host.starts_with("x86_64-linux") {
let cc = std::env::var("CC").unwrap_or_else(|_| "cc".to_string());
run(Command::new(&cc)
.args(["-shared", "-fPIC", "-Werror"])
.arg("-o")
.arg(&out_so)
.arg("shim/clock.c"))
} else {
let target = "x86_64-linux-gnu";
match Command::new("zig")
.args(["cc", "-shared", "-fPIC", "-Werror"])
.args(["-target", target])
.arg("-o")
.arg(&out_so)
.arg("shim/clock.c")
.output()
{
Ok(out) if out.status.success() => Ok(out),
Ok(out) => {
let stderr = String::from_utf8_lossy(&out.stderr);
Err(format!(
"zig cc failed to compile the clock shim (target {target})\n{}",
stderr.trim()
))
}
Err(e) => Err(format!(
"zig is required to cross-compile the clock shim but was not found: {e}"
)),
}
};
if let Err(e) = result {
panic!("{e}");
}
}