代碼範例#
use std::{borrow::Cow, process::Command};
fn main() {
// 通過 GIT_HASH 環境變量使 git 哈希可用於編譯時:
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 命令執行失敗,狀態碼: {}", o.status);
Cow::from("unknown")
},
Err(err) => {
println!("cargo:warning=執行 git 命令失敗: {}", 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");
}
代碼解釋#
這段代碼的目的是使用 Rust 的 std::process::Command
模組來執行 Git 命令,以獲取當前程式庫的 Git 哈希值並將其設置為 GIT_HASH 環境變量。這段代碼是通過在 Rust 專案的根目錄下創建 build.rs 檔案來實現的。
以下是這段代碼的工作原理:
- 在 build.rs 檔案中,定義了一個名為
output_git_short_hash()
的函式,它使用 Rust 的std::process::Command
模組來執行 Git 命令,並將執行結果賦值給 output 變數。 - 如果 Git 命令成功執行,該函式將從 output.stdout 中獲取 Git 哈希值,並將其保存在 git_hash 變數中。
Cow 是 Rust 中的一種字串類型,用於在運行時決定使用 String 還是 &str 來表示字串。 - 如果 Git 命令未成功執行,該函式將輸出一條警告訊息,並將 git_hash 設置為 "unknown"。
- 最後,該函式將 GIT_HASH 環境變量設置為 git_hash 變數的值,並使用
cargo:rerun-if-changed
指令告訴 Cargo 何時需要重新執行構建腳本。
在本例中,當../.git/HEAD
、../.git/refs
或 build.rs 檔案發生變化時,Cargo 將重新執行構建腳本。 - 在 main.rs 或其他 Rust 檔案中,您可以使用
std::env::var("GIT_HASH")
來訪問GIT_HASH
環境變量並獲取 Git 哈希值。
總之,這段代碼可以在 Rust 專案中通過執行 Git 命令獲取 Git 哈希值並將其設置為環境變量,從而方便其他 Rust 檔案訪問該值。
第四步使用了 cargo 指令來告訴 Cargo 何時需要重新執行構建腳本。
這個指令是 Rust 的編譯器 Cargo 提供的一個特殊註釋,用於控制專案的構建和重新構建行為。
具體來說,cargo 指令的作用是告訴 Cargo 某些檔案的改動會導致專案需要重新構建,這樣 Cargo 就可以在這些檔案變化時自動重新執行構建腳本。指令的語法如下:
cargo:rerun-if-changed=<filename>;
其中 <filename> 表示需要監視的檔案名或資料夾名,可以使用相對或絕對路徑。
在這個例子中,cargo 指令告訴 Cargo 在以下情況下需要重新執行構建腳本:
- 當
../.git/HEAD
檔案變化時。 - 當
../.git/refs
資料夾下的任何檔案變化時。 - 當
build.rs
檔案變化時。 - 這些檔案的變化通常意味著 Git 程式庫發生了變化,因此需要重新獲取 Git 哈希值並重新編譯專案。
需要注意的是,cargo:rerun-if-changed
指令只能在 build.rs 檔案中使用,而且必須放在一個單獨的行中,不能和其他程式碼混在一起。這是因為指令實際上是一種註釋,不是 Rust 程式碼,所以不能包含在函式、結構體或其他 Rust 語言結構中。