Expand description
§vergen - Emit cargo instructions from a build script
vergen
, when used in conjunction with cargo build scripts can emit the following:
- Will emit
cargo:rustc-env=VAR=VALUE
for each feature you have enabled. These can be referenced with theenv
! oroption_env
! macro in your code. - Can emit
cargo:warning
outputs if thefail_on_error
feature is not enabled and the requested variable is defaulted through error or theidempotent
flag. - Will emit
cargo:rerun-if-changed=build.rs
to rerun instruction emission if thebuild.rs
file changed. - Will emit
cargo:rerun-if-env-changed=VERGEN_IDEMPOTENT
to rerun instruction emission if theVERGEN_IDEMPOTENT
environment variable has changed. - Will emit
cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH
to rerun instruction emission if theSOURCE_DATE_EPOCH
environment variable has changed. - Will emit custom instructions via the
AddCustomEntries
and theadd_custom_instructions
function.
§Usage
- Ensure you have build scripts enabled via the
build
configuration in yourCargo.toml
[package]
#..
build = "build.rs"
- Add
vergen
as a build dependency inCargo.toml
, specifying the features you wish to enable.
[dependencies]
#..
[build-dependencies]
# All features enabled
vergen = { version = "9.0.0", features = ["build", "cargo", "rustc", "si"] }
# or
vergen = { version = "9.0.0", features = ["build"] }
# if you wish to disable certain features
- Create a
build.rs
file that usesvergen
to emit cargo instructions. Configuration starts withEmitter
. Eventually you will callemit
to output the cargo instructions. See theemit
documentation for more robust examples.
§Generate all output
// NOTE: This will output everything, and requires all features enabled.
// NOTE: See the specific builder documentation for configuration options.
let build = BuildBuilder::all_build()?;
let cargo = CargoBuilder::all_cargo()?;
let rustc = RustcBuilder::all_rustc()?;
let si = SysinfoBuilder::all_sysinfo()?;
Emitter::default()
.add_instructions(&build)?
.add_instructions(&cargo)?
.add_instructions(&rustc)?
.add_instructions(&si)?
.emit()?;
§Sample Output
cargo:rustc-env=VERGEN_BUILD_DATE=2024-01-31
cargo:rustc-env=VERGEN_BUILD_TIMESTAMP=2024-01-31T03:26:34.065893658Z
cargo:rustc-env=VERGEN_CARGO_DEBUG=true
cargo:rustc-env=VERGEN_CARGO_FEATURES=
cargo:rustc-env=VERGEN_CARGO_OPT_LEVEL=0
cargo:rustc-env=VERGEN_CARGO_TARGET_TRIPLE=x86_64-unknown-linux-gnu
cargo:rustc-env=VERGEN_CARGO_DEPENDENCIES=anyhow 1.0.79,vergen-pretty 0.3.2
cargo:rustc-env=VERGEN_RUSTC_CHANNEL=nightly
cargo:rustc-env=VERGEN_RUSTC_COMMIT_DATE=2024-01-29
cargo:rustc-env=VERGEN_RUSTC_COMMIT_HASH=5518eaa946291f00471af8b254b2a1715f234882
cargo:rustc-env=VERGEN_RUSTC_HOST_TRIPLE=x86_64-unknown-linux-gnu
cargo:rustc-env=VERGEN_RUSTC_LLVM_VERSION=17.0
cargo:rustc-env=VERGEN_RUSTC_SEMVER=1.77.0-nightly
cargo:rustc-env=VERGEN_SYSINFO_NAME=Arch Linux
cargo:rustc-env=VERGEN_SYSINFO_OS_VERSION=Linux Arch Linux
cargo:rustc-env=VERGEN_SYSINFO_USER=jozias
cargo:rustc-env=VERGEN_SYSINFO_TOTAL_MEMORY=31 GiB
cargo:rustc-env=VERGEN_SYSINFO_CPU_VENDOR=AuthenticAMD
cargo:rustc-env=VERGEN_SYSINFO_CPU_CORE_COUNT=8
cargo:rustc-env=VERGEN_SYSINFO_CPU_NAME=cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7
cargo:rustc-env=VERGEN_SYSINFO_CPU_BRAND=AMD Ryzen Threadripper 1900X 8-Core Processor
cargo:rustc-env=VERGEN_SYSINFO_CPU_FREQUENCY=3792
cargo:rerun-if-changed=build.rs
cargo:rerun-if-env-changed=VERGEN_IDEMPOTENT
cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH
§Generate specific output
// NOTE: This will output only the instructions specified.
// NOTE: See the specific builder documentation for configuration options.
let build = BuildBuilder::default().build_timestamp(true).build()?;
let cargo = CargoBuilder::default().opt_level(true).build()?;
let rustc = RustcBuilder::default().semver(true).build()?;
let si = SysinfoBuilder::default().cpu_core_count(true).build()?;
Emitter::default()
.add_instructions(&build)?
.add_instructions(&cargo)?
.add_instructions(&rustc)?
.add_instructions(&si)?
.emit()?;
§Sample Output
cargo:rustc-env=VERGEN_BUILD_TIMESTAMP=2024-01-31T03:26:34.065893658Z
cargo:rustc-env=VERGEN_CARGO_OPT_LEVEL=0
cargo:rustc-env=VERGEN_RUSTC_SEMVER=1.77.0-nightly
cargo:rustc-env=VERGEN_SYSINFO_CPU_CORE_COUNT=8
cargo:rerun-if-changed=build.rs
cargo:rerun-if-env-changed=VERGEN_IDEMPOTENT
cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH
- Use the
env!
oroption_env!
macro in your code to read the environment variables.
if let Some(timestamp) = option_env!("VERGEN_BUILD_TIMESTAMP") {
println!("Build Timestamp: {timestamp}");
}
if let Some(describe) = option_env!("VERGEN_GIT_DESCRIBE") {
println!("git describe: {describe}");
}
§Features
vergen
has four 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.
There is also a toggle for the emit_and_set
function. This version of emit will also set the instructions you requests as environment variables for use in build.rs
Feature | Enables |
---|---|
build | VERGEN_BUILD_* instructions |
cargo | VERGEN_CARGO_* instructions |
rustc | VERGEN_RUSTC_* instructions |
si | VERGEN_SYSINFO_* instructions |
emit_and_set | Enable the emit_and_set function |
§Environment Variables
vergen
currently recognizes the following environment variables. The full list of the environment variable names can be
found as constants here
Variable | Functionality |
---|---|
VERGEN_IDEMPOTENT | If 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_EPOCH | If 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_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
- 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
- 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
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
- 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",
"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
build
TheVERGEN_BUILD_*
configuration features - Build
Builder build
Builder forBuild
. - Cargo
cargo
Configure the emission ofVERGEN_CARGO_*
instructions - Cargo
Builder cargo
Builder forCargo
. - Used to determine what you want to refresh specifically on the
Cpu
type. - The default configuration to use when an issue has occured generating instructions
- The
Emitter
will emit cargo instructions (i.e. cargo:rustc-env=NAME=VALUE) base on the configuration you enable. - Used to determine which memory you want to refresh specifically.
- Used to determine what you want to refresh specifically on the
Process
type. - Used to determine what you want to refresh specifically on the
System
type. - Rustc
rustc
TheVERGEN_RUSTC_*
configuration features - Rustc
Builder rustc
Builder forRustc
. - Sysinfo
si
TheVERGEN_SYSINFO_*
configuration features - Builder for
Sysinfo
.
Enums§
- Dependency
Kind cargo
Dependencies can come in three kinds
Traits§
- This trait should be implemented to allow the
vergen
emitter to properly emit your custom instructions.
Type Aliases§
- The vector of strings used to emit
cargo:rerun-if-changed=VALUE
cargo instructions - The vector of strings used to emit
cargo:warning=VALUE
cargo instructions