build.rs 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. //! Build script: embeds the short git commit hash as `WH_GIT_HASH` and the commit count
  2. //! (build number) as `WH_BUILD_NUMBER`.
  3. use std::process::Command;
  4. /// Name of the compile-time environment variable holding the commit hash.
  5. const GIT_HASH_ENV: &str = "WH_GIT_HASH";
  6. /// Name of the compile-time environment variable holding the build number (commit count).
  7. const BUILD_NUMBER_ENV: &str = "WH_BUILD_NUMBER";
  8. /// Value used when the hash cannot be read (no git, not a repository).
  9. const UNKNOWN_HASH: &str = "unknown";
  10. /// Value used when the build number cannot be read (no git, not a repository).
  11. const UNKNOWN_BUILD_NUMBER: &str = "0";
  12. /// Purpose: export the short commit hash and the build number (commit count) to the crate
  13. /// and rebuild when the commit changes.
  14. /// Inputs: none (runs `git` in the package directory).
  15. /// Output: none.
  16. /// Side effects: prints cargo directives on stdout.
  17. fn main() {
  18. println!("cargo:rerun-if-changed=.git/HEAD");
  19. println!("cargo:rerun-if-changed=.git/refs");
  20. println!("cargo:rerun-if-changed=.git/packed-refs");
  21. let hash =
  22. git_output(&["rev-parse", "--short", "HEAD"]).unwrap_or_else(|| UNKNOWN_HASH.to_owned());
  23. println!("cargo:rustc-env={GIT_HASH_ENV}={hash}");
  24. let build_number = git_output(&["rev-list", "--count", "HEAD"])
  25. .unwrap_or_else(|| UNKNOWN_BUILD_NUMBER.to_owned());
  26. println!("cargo:rustc-env={BUILD_NUMBER_ENV}={build_number}");
  27. }
  28. /// Purpose: run `git` with the given arguments and return its trimmed output.
  29. /// Inputs: `args` - the arguments passed to `git`.
  30. /// Output: the trimmed stdout, or `None` when git is missing, fails or prints nothing.
  31. /// Side effects: runs the `git` command.
  32. fn git_output(args: &[&str]) -> Option<String> {
  33. let output = Command::new("git").args(args).output().ok()?;
  34. if !output.status.success() {
  35. return None;
  36. }
  37. let text = String::from_utf8(output.stdout).ok()?.trim().to_owned();
  38. (!text.is_empty()).then_some(text)
  39. }