Code example#
use std::{borrow::Cow, process::Command};
fn main() {
// Make git hash available via GIT_HASH build-time env var:
output_git_short_hash();
}
fn output_git_short_hash() {
let output = Command::new("git").args(["rev-parse", "HEAD"]).output();
let git_hash = match output {
Ok(o) if o.status.success() => {
let sha = String::from_utf8_lossy(&o.stdout).trim().to_owned();
Cow::from(sha)
},
Ok(o) => {
println!("cargo:warning=Git command failed with status: {}", o.status);
Cow::from("unknown")
},
Err(err) => {
println!("cargo:warning=Failed to execute git command: {}", err);
Cow::from("unknown")
},
};
println!("cargo:rustc-env=GIT_HASH={}", git_hash);
println!("cargo:rerun-if-changed=../.git/HEAD");
println!("cargo:rerun-if-changed=../.git/refs");
println!("cargo:rerun-if-changed=build.rs");
}
Code Explanation#
The purpose of this code is to use the Rust std::process::Command module to execute a Git command, retrieve the Git hash of the current code repository, and set it as the value of the GIT_HASH environment variable. This code is implemented by creating a build.rs file in the root directory of a Rust project.
Here's how this code works:
- In the build.rs file, a function
output_git_short_hash()is defined. It uses the Ruststd::process::Commandmodule to execute a Git command and assigns the result to theoutputvariable. - If the Git command is executed successfully, the function retrieves the Git hash from
output.stdoutand stores it in thegit_hashvariable.
Cowis a string type in Rust that allows runtime determination of whether to useStringor&strto represent the string. - If the Git command fails to execute, the function outputs a warning message and sets
git_hashto "unknown". - Finally, the function sets the GIT_HASH environment variable to the value of
git_hashand uses thecargo:rerun-if-changeddirective to inform Cargo when to rerun the build script.
In this example, Cargo will rerun the build script when../.git/HEAD,../.git/refs, or build.rs files are changed. - In main.rs or other Rust files, you can access the
GIT_HASHenvironment variable and retrieve the Git hash usingstd::env::var("GIT_HASH").
In summary, this code allows you to retrieve the Git hash of a Rust project by executing a Git command and set it as an environment variable for easy access by other Rust files.
In the fourth step, the cargo:rerun-if-changed directive is used to inform Cargo when to rerun the build script.
This directive is a special comment provided by Cargo, the Rust compiler, to control the build and rebuild behavior of a project.
Specifically, the cargo:rerun-if-changed directive tells Cargo that changes to certain files will require the project to be rebuilt, allowing Cargo to automatically rerun the build script when these files change. The syntax of the directive is as follows:
cargo:rerun-if-changed=<filename>;
where <filename> represents the name or path of the file to monitor, which can be a relative or absolute path.
In this example, the cargo:rerun-if-changed directive tells Cargo to rerun the build script when:
- The
../.git/HEADfile changes. - Any file in the
../.git/refsfolder changes. - The
build.rsfile changes. - These file changes typically indicate changes to the Git code repository, requiring the retrieval of the Git hash and recompilation of the project.
Note that the cargo:rerun-if-changed directive can only be used in the build.rs file and must be on a separate line, not mixed with other code. This is because the directive is actually a comment, not Rust code, and cannot be included within functions, structs, or other Rust language constructs.