use std::path::Path;
use std::process::Command;
fn main() {
emit_git_commit();
emit_git_commit_date();
emit_target_triple();
emit_rerun_directives();
}
fn emit_git_commit() {
if !workspace_has_git_dir() {
return;
}
if let Some(full) = run_git(&["rev-parse", "HEAD"]) {
println!("cargo:rustc-env=CABIN_BUILD_COMMIT={full}");
}
}
fn emit_git_commit_date() {
if !workspace_has_git_dir() {
return;
}
if let Some(raw) = run_git(&[
"-c",
"log.showSignature=false",
"log",
"-1",
"--date=short",
"--pretty=%cd",
]) {
let date = raw.trim();
if !date.is_empty() {
println!("cargo:rustc-env=CABIN_BUILD_COMMIT_DATE={date}");
}
}
}
fn emit_target_triple() {
if let Ok(target) = std::env::var("TARGET")
&& !target.is_empty()
{
println!("cargo:rustc-env=CABIN_BUILD_HOST={target}");
}
}
fn emit_rerun_directives() {
println!("cargo:rerun-if-changed=build.rs");
if workspace_has_git_dir() {
for relative in [".git/HEAD", ".git/packed-refs", ".git/logs/HEAD"] {
let path = workspace_root().join(relative);
if path.is_file() {
println!("cargo:rerun-if-changed={}", path.display());
}
}
}
}
fn run_git(args: &[&str]) -> Option<String> {
let output = Command::new("git")
.args(args)
.current_dir(workspace_root())
.output()
.ok()?;
if !output.status.success() {
return None;
}
let raw = String::from_utf8(output.stdout).ok()?;
let trimmed = raw.trim().to_owned();
if trimmed.is_empty() {
None
} else {
Some(trimmed)
}
}
fn workspace_root() -> std::path::PathBuf {
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_owned());
let manifest_path = Path::new(&manifest_dir);
manifest_path
.parent()
.and_then(Path::parent)
.map_or_else(|| manifest_path.to_path_buf(), Path::to_path_buf)
}
fn workspace_has_git_dir() -> bool {
workspace_root().join(".git").exists()
}