Include git commit hash as string in Rust program

I host a Rust project in a git repository and I want it to print a version for some command. How to include the version in the program? I thought that the build script could set environment variables that could be used when compiling the project itself, but it does not work:

build.rs

use std::env;

fn get_git_hash() -> Option<String> {
    use std::process::Command;

    let branch = Command::new("git")
                         .arg("rev-parse")
                         .arg("--abbrev-ref")
                         .arg("HEAD")
                         .output();
    if let Ok(branch_output) = branch {
        let branch_string = String::from_utf8_lossy(&branch_output.stdout);
        let commit = Command::new("git")
                             .arg("rev-parse")
                             .arg("--verify")
                             .arg("HEAD")
                             .output();
        if let Ok(commit_output) = commit {
            let commit_string = String::from_utf8_lossy(&commit_output.stdout);

            return Some(format!("{}, {}",
                        branch_string.lines().next().unwrap_or(""),
                        commit_string.lines().next().unwrap_or("")))
        } else {
            panic!("Can not get git commit: {}", commit_output.unwrap_err());
        }
    } else {
        panic!("Can not get git branch: {}", branch.unwrap_err());
    }
    None
}

fn main() {
    if let Some(git) = get_git_hash() {
        env::set_var("GIT_HASH", git);
    }
}

SRC / main.rs:

pub const GIT_HASH: &'static str = env!("GIT_HASH");

fm main() {
    println!("Git hash: {}", GIT_HASH);
}

Error message:

error: environment variable `GIT_HASH` not defined
  --> src/main.rs:10:25
   |
10 | pub const GIT_HASH: &'static str = env!("GIT_HASH");
   |   
                                        ^^^^^^^^^^^^^^^^

Is there any way to pass such data at compile time? How can I communicate between script assembly and source code, if not environment variables? I can only think of writing data to some file, but I think this is too much for this case.

+6
source share
4 answers

- , , .

, . , "" , - .

Cargo , [1].

script

+6

Rust 1.19 ( 0.20.0), https://github.com/rust-lang/cargo/pull/3929, (env!(…)) rustc rustdoc :

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

, OP :

// 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
}

, , 1.18 .

+8

vergen, git script. @DK answer, script Rust 1.19, vergen , OUT_DIR (.. vergen OP, ).


:

# 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
}
+6

. ( , , ?)

const REF: &str = include_str!("../.git/HEAD");
const REF_MASTER: &str = include_str!("../.git/refs/heads/master");

// (elsewhere)
if REF == "ref: refs/heads/master" { REF_MASTER } else { REF }

( , codegolf. , 100% .)

0

Source: https://habr.com/ru/post/1016951/


All Articles