コード例#
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コマンドがステータス{}で失敗しました。", 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 は、実行時に String または & str を使用して文字列を表すための Rust の文字列型です。 - もし 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 ファイルがその値にアクセスできるようにするものです。
4 番目のステップでは、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 のコードではないためです。