#![allow(
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_sign_loss,
clippy::map_unwrap_or
)]
use std::process::Command;
use std::time::{SystemTime, UNIX_EPOCH};
fn main() {
println!("cargo:rustc-env=VANE_COMMIT={}", git_short_commit());
println!("cargo:rustc-env=VANE_BUILD_DATE={}", format_yyyymmdd(build_date_unix()));
println!("cargo:rustc-env=VANE_RUSTC={}", rustc_version());
println!("cargo:rustc-env=VANE_CARGO={}", cargo_version());
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=../../.git/HEAD");
println!("cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH");
}
fn git_short_commit() -> String {
Command::new("git")
.args(["rev-parse", "--short=9", "HEAD"])
.output()
.ok()
.filter(|o| o.status.success())
.map_or_else(|| "unknown".to_owned(), |o| String::from_utf8_lossy(&o.stdout).trim().to_owned())
}
fn build_date_unix() -> i64 {
if let Ok(s) = std::env::var("SOURCE_DATE_EPOCH")
&& let Ok(n) = s.trim().parse::<i64>()
{
return n;
}
if let Some(n) = git_commit_unix() {
return n;
}
SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_secs() as i64).unwrap_or(0)
}
fn git_commit_unix() -> Option<i64> {
Command::new("git")
.args(["log", "-1", "--format=%ct", "HEAD"])
.output()
.ok()
.filter(|o| o.status.success())
.and_then(|o| String::from_utf8(o.stdout).ok())
.and_then(|s| s.trim().parse::<i64>().ok())
}
fn format_yyyymmdd(unix: i64) -> String {
let days = unix.div_euclid(86_400);
let (y, m, d) = civil_from_days(days);
format!("{y:04}-{m:02}-{d:02}")
}
fn civil_from_days(z: i64) -> (i64, u32, u32) {
let z = z + 719_468;
let era = if z >= 0 { z } else { z - 146_096 } / 146_097;
let doe = (z - era * 146_097) as u64;
let yoe = (doe - doe / 1_460 + doe / 36_524 - doe / 146_096) / 365;
let y = yoe as i64 + era * 400;
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
let mp = (5 * doy + 2) / 153;
let d = (doy - (153 * mp + 2) / 5 + 1) as u32;
let m = (if mp < 10 { mp + 3 } else { mp - 9 }) as u32;
let y = if m <= 2 { y + 1 } else { y };
(y, m, d)
}
fn rustc_version() -> String {
tool_version_tail("rustc")
}
fn cargo_version() -> String {
tool_version_tail("cargo")
}
fn tool_version_tail(tool: &str) -> String {
Command::new(tool)
.arg("--version")
.output()
.ok()
.filter(|o| o.status.success())
.and_then(|o| String::from_utf8(o.stdout).ok())
.map_or_else(
|| "unknown".to_owned(),
|s| {
let prefix = format!("{tool} ");
s.trim().strip_prefix(&prefix).unwrap_or_else(|| s.trim()).to_owned()
},
)
}