Crate vergen

source ·
Expand description

vergen - Emit cargo instructions from a build script

vergen, when used in conjunction with cargo build scripts can emit the following:

Usage

  1. Ensure you have build scripts enabled via the build configuration in your Cargo.toml
[package]
#..
build = "build.rs"
  1. Add vergen as a build dependency in Cargo.toml, specifying the features you wish to enable.
[dependencies]
#..

[build-dependencies]
# All features enabled
vergen = { version = "8.0.0", features = ["build", "cargo", "git", "gitcl", "rustc", "si"] }
# or
vergen = { version = "8.0.0", features = ["build", "git", "gitcl"] }
# if you wish to disable certain features
  1. Create a build.rs file that uses vergen to emit cargo instructions. Configuration starts with EmitBuilder. Eventually you will call emit to output the cargo instructions. See the emit documentation for more robust examples.
use std::error::Error;
use vergen::EmitBuilder;

fn main() -> Result<(), Box<dyn Error>> {
    // Emit the instructions
    EmitBuilder::builder().emit()?;
    Ok(())
}
  1. Use the env! macro in your code to read the environment variables.
println!("Build Timestamp: {}", env!("VERGEN_BUILD_TIMESTAMP"));
println!("git describe: {}", env!("VERGEN_GIT_DESCRIBE"));

Features

vergen has five main feature toggles allowing you to customize your output. No features are enabled by default.
You must specifically enable the features you wish to use.

FeatureEnables
buildVERGEN_BUILD_* instructions
cargoVERGEN_CARGO_* instructions
gitVERGEN_GIT_* instructions and the cargo:rerun-if-changed instructions
rustcVERGEN_RUSTC_* instructions
siVERGEN_SYSINFO_* instructions
Configuring the git feature

If you wish to use the git feature, you must also enable one of the git implementations. The gitcl features is lightweight, but depends on git being on the path. The other implementations allow for git instructions to be emitted without a reliance on the git binary. The git2 library are bindings over the libgit2 library, while gitoxide is entirely implemented in Rust.

NOTE - These 3 features are mutually exclusive. Only one can be chosen. If you select multiple, vergen intentionally will not compile.

FeaturesEnables
gitclVERGEN_GIT_ instructions emitted via the git binary at the command line
git2VERGEN_GIT_ instructions emitted via git git2 library
gitoxideVERGEN_GIT_ instructions emitted via the gitoxide library

A common configuration would be as follows:

[build-dependencies]
vergen = { version = "8.0.0", features = [ "build", "git", "gitcl" ]}
# ...

Environment Variables

vergen currently recognizes the following environment variables

VariableFunctionality
VERGEN_IDEMPOTENTIf this environment variable is set vergen will use the idempotent output feature regardless of the configuration set in build.rs. This exists mainly to allow package maintainers to force idempotent output to generate deterministic binary output.
SOURCE_DATE_EPOCHIf this environment variable is set vergen will use the value (unix time since epoch) as the basis for a time based instructions. This can help emit deterministic instructions.
VERGEN_BUILD_*If this environment variable is set vergen will use the value you specify for the output rather than generating it.
VERGEN_CARGO_*If this environment variable is set vergen will use the value you specify for the output rather than generating it.
VERGEN_GIT_*If this environment variable is set vergen will use the value you specify for the output rather than generating it.
VERGEN_RUSTC_*If this environment variable is set vergen will use the value you specify for the output rather than generating it.
VERGEN_SYSINFO_*If this environment variable is set vergen will use the value you specify for the output rather than generating it.

Goals

I initially wrote vergen (version generator, so original) so I could embed a some git information in my personal projects. Now, usage has grown to the point that vergen needs to fit better in the rust ecosystem.

The current goals are as follows:

Minimize the tool footprint
  • Adopt an opt-in, rather than opt-out strategy for the features. The default feature set is empty and no instructions will be emitted.
  • The instructions you have configured will be emitted. If there are errors or idempotentcy has been configured, some of those instructions may be defaulted.
  • Allow overriding configurtion set in build.rs through environment variables. This will allow package maintainers to force sane defaults when packaging rust binaries for distribution.
Minimize the compile time impact
  • git2 and gitoxide are large features. These are opt-in now. I’ve also added back support for generating git instructions via the git binary.
  • I’ve removed some extraneous libraries. Any libraries added in the future will be checked against the current standard compile times to ensure the impact is not too great.
  • vergen should compile and test from a source tarball.
Support deterministic output

Compilations run from the same source oftentimes need to generate identical binaries. vergen now supports this determinism in a few ways.

  • An idempotent configuration option has been added. When this is enabled in a build script, each build via cargo against the same source code should generate identical binaries. Instructions that output information that may change between builds (i.e. timestamps, sysinfo) will be defaulted.
  • Recognize common environment variables that support deterministic builds (i.e. SOURCE_DATE_EPOCH)
  • Allow build.rs configuration overrides though environment variables to allow users building a binary, but not controlling the source to generate deterministic binaries.

Use Cases

I generally use vergen for the following two cases

  1. Generating verbose output describing a command line application.
~/p/r/app λ app -vv
app 0.1.0

Build Timestamp:     2021-02-23T20:14:46.558472672+00:00
Describe:            0.1.0-9-g46f83e1
Commit SHA:          46f83e112520533338245862d366f6a02cef07d4
Commit Date:         2021-02-23T08:08:02-05:00
Commit Branch:       master
rustc Version:       1.52.0-nightly
rustc Channel:       nightly
rustc Host Triple:   x86_64-unknown-linux-gnu
rustc Commit SHA:    3f5aee2d5241139d808f4fdece0026603489afd1
cargo Target Triple: x86_64-unknown-linux-musl
cargo Profile:       release
  1. Information endpoints in web apis
~/p/r/app λ curl https://some.app.com/info | jq
{
  "build_timestamp": "2021-02-19T21:32:22.932833758+00:00",
  "git_describe": "0.0.0-7-gc96c096",
  "git_sha": "c96c0961c3b7b749eab92f6f588b67915889c4cd",
  "git_commit_date": "2021-02-19T16:29:06-05:00",
  "git_branch": "master",
  "rustc_semver": "1.52.0-nightly",
  "rustc_channel": "nightly",
  "rustc_host_triple": "x86_64-unknown-linux-gnu",
  "rustc_commit_sha": "3f5aee2d5241139d808f4fdece0026603489afd1",
  "cargo_target_triple": "x86_64-unknown-linux-musl",
  "cargo_profile": "release"
}

Structs

  • Build the vergen configuration to enable specific cargo instruction output