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::Command
module to execute a Git command and assigns the result to theoutput
variable. - If the Git command is executed successfully, the function retrieves the Git hash from
output.stdout
and stores it in thegit_hash
variable.
Cow
is a string type in Rust that allows runtime determination of whether to useString
or&str
to represent the string. - If the Git command fails to execute, the function outputs a warning message and sets
git_hash
to "unknown". - Finally, the function sets the GIT_HASH environment variable to the value of
git_hash
and uses thecargo:rerun-if-changed
directive 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_HASH
environment 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/HEAD
file changes. - Any file in the
../.git/refs
folder changes. - The
build.rs
file 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.