#![expect(
clippy::disallowed_methods,
reason = "a build script is told what to build by cargo through its environment"
)]
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
#[path = "src/runtime/version/provenance.rs"]
mod provenance;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo::rustc-check-cfg=cfg(emulator_absent)");
println!("cargo::rustc-check-cfg=cfg(fuzzing)");
if env::var_os("CARGO_CFG_MIRI").is_some() {
println!("cargo::rustc-cfg=emulator_absent");
}
let manifest = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("cargo sets it"));
let out = PathBuf::from(env::var("OUT_DIR").expect("cargo sets it"));
write_version(&manifest, &out);
}
fn write_version(manifest: &Path, out: &Path) {
let version = env::var("CARGO_PKG_VERSION").expect("cargo sets it");
let source = source_of(manifest, &version);
let written = provenance::describe(&version, &source);
fs::write(out.join("version.rs"), format!("{written:?}")).expect("the version file");
}
fn source_of(manifest: &Path, version: &str) -> provenance::Provenance {
let record = manifest.join(".cargo_vcs_info.json");
if let Ok(json) = fs::read_to_string(&record) {
println!("cargo:rerun-if-changed={}", record.display());
return provenance::from_vcs_info(&json);
}
let git = |args: &[&str]| {
Command::new("git")
.arg("--no-optional-locks")
.arg("-C")
.arg(manifest)
.args(args)
.output()
.ok()
.filter(|output| output.status.success())
.map(|output| String::from_utf8_lossy(&output.stdout).trim().to_owned())
};
let Some(commit) = git(&["rev-parse", "HEAD"]) else {
return provenance::Provenance::Unknown;
};
let mut watched: Vec<String> = ["HEAD", "index", "packed-refs", "refs/tags"]
.iter()
.map(|&path| path.to_owned())
.collect();
watched.extend(git(&["symbolic-ref", "-q", "HEAD"]));
for path in watched {
let Some(found) = git(&["rev-parse", "--git-path", &path]) else {
continue;
};
let found = manifest.join(found);
if found.exists() {
println!("cargo:rerun-if-changed={}", found.display());
}
}
for builds in ["src", "Cargo.toml", "Cargo.lock"] {
println!("cargo:rerun-if-changed={}", manifest.join(builds).display());
}
let changed = git(&[
"status",
"--porcelain",
"--untracked-files=no",
"--",
"src",
"build.rs",
"Cargo.toml",
"Cargo.lock",
]);
let dirty = changed.is_none_or(|changes| !changes.is_empty());
let tags = git(&["tag", "--points-at", "HEAD"]).unwrap_or_default();
provenance::from_checkout(version, &commit, &tags, dirty)
}