Include git commit hash as string into Rust program

I can only think about writing data to some file, but I think this is overkill for this case.

That's unfortunate, because that is the only way of doing it. Environment variables can't work because changes to the environment can't "leak" into other, non-child processes.

For simpler things, you can instruct Cargo to define conditional compilation flags, but those aren't powerful enough to communicate a string [1].

The details of generating code from a build script is detailed in the code generation section of the Cargo documentation.


[1]: I mean, unless you feel like breaking the hash into 160 config flags and then re-assembling them in the source being compiled, but that's even more overkill.


Since Rust 1.19 (cargo 0.20.0), thanks to https://github.com/rust-lang/cargo/pull/3929, you can now define a compile-time environment variable (env!(…)) for rustc and rustdoc via:

println!("cargo:rustc-env=KEY=value");

So OP's program can be written as:

// build.rs
use std::process::Command;
fn main() {
    // note: add error checking yourself.
    let output = Command::new("git").args(&["rev-parse", "HEAD"]).output().unwrap();
    let git_hash = String::from_utf8(output.stdout).unwrap();
    println!("cargo:rustc-env=GIT_HASH={}", git_hash);
}
// main.rs
fn main() {
    println!("{}", env!("GIT_HASH"));
    // output something like:
    // 7480b50f3c75eeed88323ec6a718d7baac76290d
}

Note that you still cannot use this if you still want to support 1.18 or below.


There is already an existing crate vergen that can calculate the git commit in the build script. As @DK's answer described, the build script cannot modify environment variable before Rust 1.19, so vergen still works by writing the result into OUT_DIR (i.e. vergen still won't solve OP's question, but it should be easier to use).


Usage:

# Cargo.toml
...
[build-dependencies]
vergen = "0.1"
// build.rs
extern crate vergen;
use vergen::*;
fn main() {
    vergen(SHORT_SHA | COMMIT_DATE).unwrap();
}
mod version {
    include!(concat!(env!("OUT_DIR"), "/version.rs"));
}
fn main() {
    println!("commit: {} {}", version::commit_date(), version::short_sha());
    // output something like:
    //        commit: 2017-05-03 a29c7e5
}