Expand description
Provides a crate with information from the time it was built.
built
is used as a build-time dependency to collect various information
about the build-environment, serialize this information into Rust-code and
provide that to the crate. The information collected by built
include:
- Various metadata like version, authors, homepage etc. as set by
Cargo.toml
- The tag or commit id if the crate was being compiled from within a Git repository.
- The values of
CARGO_CFG_*
build script environment variables, likeCARGO_CFG_TARGET_OS
andCARGO_CFG_TARGET_ARCH
. - The features the crate was compiled with.
- The various dependencies, dependencies of dependencies and their versions Cargo ultimately chose to compile.
- The presence of a CI-platform like
Github Actions
,Travis CI
andAppVeyor
. - The compiler and it’s version; the documentation-generator and it’s version.
built
does not add any further runtime-dependencies to a crate; all information
is serialized as types from stdlib
. One can include built
as a
runtime-dependency and use it’s convenience functions.
To add built
to a crate, add it as a build-time dependency, use a build-script
to collect and serialize the build-time information, and include!
the generated code.
Add this to Cargo.toml
:
[package]
build = "build.rs"
[build-dependencies]
built = "0.7"
Add or modify a build-script. In build.rs
:
fn main() {
built::write_built_file().expect("Failed to acquire build-time information");
}
The build-script will by default write a file named built.rs
into Cargo’s output
directory. It can be picked up in main.rs
(or anywhere else) like this:
// Use of a mod or pub mod is not actually necessary.
pub mod built_info {
// The file has been placed there by the build script.
include!(concat!(env!("OUT_DIR"), "/built.rs"));
}
…and then used somewhere in the crate’s code:
/// Determine if current version is a pre-release or was built from a git-repo
fn release_is_unstable() -> bool {
return !built_info::PKG_VERSION_PRE.is_empty() || built_info::GIT_VERSION.is_some()
}
/// Default log-level, enhanced on CI
fn default_log_level() -> LogLevel {
if built_info::CI_PLATFORM.is_some() {
LogLevel::TRACE
} else {
LogLevel::ERROR
}
}
/// The time this crate was built
#[cfg(feature = "chrono")]
fn built_time() -> built::chrono::DateTime<built::chrono::Local> {
built::util::strptime(built_info::BUILT_TIME_UTC)
.with_timezone(&built::chrono::offset::Local)
}
/// If another crate pulls in a dependency we don't like, print a warning
#[cfg(feature = "semver")]
fn check_sane_dependencies() {
if built::util::parse_versions(&built_info::DEPENDENCIES)
.any(|(name, ver)| name == "DeleteAllMyFiles"
&& ver < built::semver::Version::parse("1.1.4").unwrap()) {
eprintln!("DeleteAllMyFiles < 1.1.4 may not delete all your files. Beware!");
}
}
§Overrides
Most values otherwise detected by built
can be manually set using environment variables. The
primary use-case for this is to allow automated build-systems and package-managers to enforce
certain values, e.g. to hide the presence of a CI-platform and/or allow for reproducible
builds.
The values set via the environment take precedence over what built
would otherwise detect.
There is no mechanism to ensure that values derived from override-variables are sensible,
besides enforcing the correct type.
Override-variables are prefixed by BUILT_OVERRIDE_{PKG_NAME}_
, where {PKG_NAME}
is the name
of the package as reported by cargo
. For example, if the package is named “mypkg”, and the value
to be overridden is named “CI_PLATFORM”, then the override variable is named
“BUILT_OVERRIDE_mypkg_CI_PLATFORM”. Remember that more than one package in a dependency-graph
might use built
internally, so you might have to override multiple instances of the same
value.
Unused override variables result in a warning at compile time, albeit cargo only reports those
for path-specific (e.g. local) packages.
An override-variable’s text-presentation must parse to the value’s respective type:
- Strings are used as-is.
- Integers and
bool
must parse via theirstd::str::FromStr
-implementation. std::option::Option<T>
parses the stringBUILT_OVERRIDE_NONE
asOption::None
; every other value must parse asT
. For example,BUILT_OVERRIDE_mypkg_CI_PLATFORM=BUILT_OVERRIDE_NONE
forcesCI_PLATFORM.is_none()
.- List-like values are parsed as comma-separated values.
If an override-variable can’t be parsed, the build-process will abort with a panic!()
.
Notice that values that were overridden are recorded in OVERRIDE_VARIABLES_USED
.
Please refer to the respective item’s documentation for more information on overrides.
§Feature flags
The information that built
collects and makes available in built.rs
depends
on the features that were enabled on the build-time dependency.
§Always available
The following information is available regardless of feature-flags.
/// The Continuous Integration platform detected during compilation.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CI_PLATFORM`.
pub static CI_PLATFORM: Option<&str> = None;
/// The full version.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_VERSION`.
pub static PKG_VERSION: &str = "0.1.0";
/// The major version.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_MAJOR`.
pub static PKG_VERSION_MAJOR: &str = "0";
/// The minor version.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_MINOR`.
pub static PKG_VERSION_MINOR: &str = "1";
/// "The patch version.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_PATCH`.
pub static PKG_VERSION_PATCH: &str = "0";
/// "The pre-release version.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_PRE`.
pub static PKG_VERSION_PRE: &str = "";
/// "A colon-separated list of authors.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_AUTHORS`.
pub static PKG_AUTHORS: &str = "Lukas Lueg <lukas.lueg@gmail.com>";
/// The name of the package.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_NAME`.
pub static PKG_NAME: &str = "example_project";
/// "The description.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_DESCRIPTION`.
pub static PKG_DESCRIPTION: &str = "";
/// "The homepage.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_HOMEPAGE`.
pub static PKG_HOMEPAGE: &str = "";
/// "The license.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_LICENSE`.
pub static PKG_LICENSE: &str = "MIT";
/// The source repository as advertised in Cargo.toml.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PKG_REPOSITORY`.
pub static PKG_REPOSITORY: &str = "";
/// The target triple that was being compiled for.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_TARGET`.
pub static TARGET: &str = "x86_64-unknown-linux-gnu";
/// The host triple of the rust compiler.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_HOST`.
pub static HOST: &str = "x86_64-unknown-linux-gnu";
/// `release` for release builds, `debug` for other builds.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_PROFILE`.
pub static PROFILE: &str = "debug";
/// The compiler that cargo resolved to use.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_RUSTC`; notice that
/// if `RUSTC` is overridden, `RUSTC_VERSION` *must* also be overridden.
pub static RUSTC: &str = "rustc";
/// The documentation-generator that cargo resolved to use.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_RUSTDOC`; notice that if `RUSTDOC`
/// is overridden, `RUSTDOC_VERSION` *must* also be overridden.
pub static RUSTDOC: &str = "rustdoc";
/// The output of `rustc -V`
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_RUSTC_VERSION`.
pub static RUSTC_VERSION: &str = "rustc 1.43.1 (8d69840ab 2020-05-04)";
/// The output of `rustdoc -V`
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_RUSTDOC_VERSION`.
pub static RUSTDOC_VERSION: &str = "rustdoc 1.43.1 (8d69840ab 2020-05-04)";
/// Value of OPT_LEVEL for the profile used during compilation.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_OPT_LEVEL`.
pub static OPT_LEVEL: &str = "0";
/// The parallelism that was specified during compilation.
/// If `SOURCE_DATE_EPOCH` is set, `NUM_JOBS` is forced to `1`.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_NUM_JOBS`.
pub static NUM_JOBS: u32 = 8;
/// "Value of DEBUG for the profile used during compilation.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_NUM_DEBUG`.
pub static DEBUG: bool = true;
/// The features that were enabled during compilation.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_FEATURES`.
pub static FEATURES: [&str; 0] = [];
/// The features as a comma-separated string.
pub static FEATURES_STR: &str = "";
/// The features as above, as lowercase strings.
pub static FEATURES_LOWERCASE: [&str; 0] = [];
/// The feature-string as above, from lowercase strings.
pub static FEATURES_LOWERCASE_STR: &str = "";
/// The target architecture, given by `CARGO_CFG_TARGET_ARCH`.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_TARGET_ARCH`.
pub static CFG_TARGET_ARCH: &str = "x86_64";
/// The endianness, given by `CARGO_CFG_TARGET_ENDIAN`.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_ENDIAN`.
pub static CFG_ENDIAN: &str = "little";
/// The toolchain-environment, given by `CARGO_CFG_TARGET_ENV`.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_ENV`.
pub static CFG_ENV: &str = "gnu";
/// The OS-family, given by `CARGO_CFG_TARGET_FAMILY`.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_FAMILY`.
pub static CFG_FAMILY: &str = "unix";
/// The operating system, given by `CARGO_CFG_TARGET_OS`.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_OS`.
pub static CFG_OS: &str = "linux";
/// The pointer width, given by `CARGO_CFG_TARGET_POINTER_WIDTH`.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_CFG_POINTER_WIDTH`.
pub static CFG_POINTER_WIDTH: &str = "64";
/// The override-variables that were used during compilation.
pub static OVERRIDE_VARIABLES_USED: [&str; 0] = [];
§cargo-lock
Parses Cargo.lock
and generates representations of dependencies and their versions.
For this to work, Cargo.lock
needs to actually be there; this is (usually)
only true for executables and not for libraries. Cargo will only create a
Cargo.lock
for the top-level crate in a dependency-tree. In case
of a library, the top-level crate will decide which crate/version
combination to compile and there will be no Cargo.lock
while the library
gets compiled as a dependency.
Parsing Cargo.lock
instead of Cargo.toml
allows to serialize the
precise versions Cargo chose to compile. One can’t, however, distinguish
build-dependencies
, dev-dependencies
and dependencies
. Furthermore,
some dependencies never show up if Cargo had not been forced to
actually use them (e.g. dev-dependencies
with cargo test
never
having been executed).
Note that if the dependency-tree
-feature is not active, the list of dependencies
contains the root-package(s) as well.
/// An array of effective dependencies as documented by `Cargo.lock`.
pub static DEPENDENCIES: [(&str, &str); 37] = [("autocfg", "1.0.0"), ("bitflags", "1.2.1"), ("built", "0.4.1"), ("cargo-lock", "4.0.1"), ("cc", "1.0.54"), ("cfg-if", "0.1.10"), ("chrono", "0.4.11"), ("example_project", "0.1.0"), ("git2", "0.13.6"), ("idna", "0.2.0"), ("jobserver", "0.1.21"), ("libc", "0.2.71"), ("libgit2-sys", "0.12.6+1.0.0"), ("libz-sys", "1.0.25"), ("log", "0.4.8"), ("matches", "0.1.8"), ("num-integer", "0.1.42"), ("num-traits", "0.2.11"), ("percent-encoding", "2.1.0"), ("pkg-config", "0.3.17"), ("proc-macro2", "1.0.17"), ("quote", "1.0.6"), ("semver", "1.0.0"), ("serde", "1.0.110"), ("serde_derive", "1.0.110"), ("smallvec", "1.4.0"), ("syn", "1.0.25"), ("time", "0.1.43"), ("toml", "0.5.6"), ("unicode-bidi", "0.3.4"), ("unicode-normalization", "0.1.12"), ("unicode-xid", "0.2.0"), ("url", "2.1.1"), ("vcpkg", "0.2.8"), ("winapi", "0.3.8"), ("winapi-i686-pc-windows-gnu", "0.4.0"), ("winapi-x86_64-pc-windows-gnu", "0.4.0")];
/// The effective dependencies as a comma-separated string.
pub static DEPENDENCIES_STR: &str = "autocfg 1.0.0, bitflags 1.2.1, built 0.4.1, cargo-lock 4.0.1, cc 1.0.54, cfg-if 0.1.10, chrono 0.4.11, example_project 0.1.0, git2 0.13.6, idna 0.2.0, jobserver 0.1.21, libc 0.2.71, libgit2-sys 0.12.6+1.0.0, libz-sys 1.0.25, log 0.4.8, matches 0.1.8, num-integer 0.1.42, num-traits 0.2.11, percent-encoding 2.1.0, pkg-config 0.3.17, proc-macro2 1.0.17, quote 1.0.6, semver 1.0.0, serde 1.0.110, serde_derive 1.0.110, smallvec 1.4.0, syn 1.0.25, time 0.1.43, toml 0.5.6, unicode-bidi 0.3.4, unicode-normalization 0.1.12, unicode-xid 0.2.0, url 2.1.1, vcpkg 0.2.8, winapi 0.3.8, winapi-i686-pc-windows-gnu 0.4.0, winapi-x86_64-pc-windows-gnu 0.4.0";
§dependency-tree
(implies cargo-lock
)
Solve the dependency-graph in Cargo.lock
to discern direct and indirect
dependencies.
“Direct” dependencies are those which the root-package(s) depends on. “Indirect” dependencies are those which are not direct dependencies.
/// An array of direct dependencies as documented by `Cargo.lock`.
pub static DIRECT_DEPENDENCIES: [(&str, &str); 1] = [("built", "0.6.1")];
/// The direct dependencies as a comma-separated string.
pub static DIRECT_DEPENDENCIES_STR: &str = r"built 0.6.1";
/// An array of indirect dependencies as documented by `Cargo.lock`.
pub static INDIRECT_DEPENDENCIES: [(&str, &str); 64] = [("android-tzdata", "0.1.1"), ("android_system_properties", "0.1.5"), ("autocfg", "1.1.0"), ("bitflags", "2.4.0"), ("bumpalo", "3.13.0"), ("cargo-lock", "9.0.0"), ("cc", "1.0.83"), ("cfg-if", "1.0.0"), ("chrono", "0.4.29"), ("core-foundation-sys", "0.8.4"), ("equivalent", "1.0.1"), ("example_project", "0.1.0"), ("fixedbitset", "0.4.2"), ("form_urlencoded", "1.2.0"), ("git2", "0.18.0"), ("hashbrown", "0.14.0"), ("iana-time-zone", "0.1.57"), ("iana-time-zone-haiku", "0.1.2"), ("idna", "0.4.0"), ("indexmap", "2.0.0"), ("jobserver", "0.1.26"), ("js-sys", "0.3.64"), ("libc", "0.2.147"), ("libgit2-sys", "0.16.1+1.7.1"), ("libz-sys", "1.1.12"), ("log", "0.4.20"), ("memchr", "2.6.3"), ("num-traits", "0.2.16"), ("once_cell", "1.18.0"), ("percent-encoding", "2.3.0"), ("petgraph", "0.6.4"), ("pkg-config", "0.3.27"), ("proc-macro2", "1.0.66"), ("quote", "1.0.33"), ("semver", "1.0.18"), ("serde", "1.0.188"), ("serde_derive", "1.0.188"), ("serde_spanned", "0.6.3"), ("syn", "2.0.31"), ("tinyvec", "1.6.0"), ("tinyvec_macros", "0.1.1"), ("toml", "0.7.6"), ("toml_datetime", "0.6.3"), ("toml_edit", "0.19.14"), ("unicode-bidi", "0.3.13"), ("unicode-ident", "1.0.11"), ("unicode-normalization", "0.1.22"), ("url", "2.4.1"), ("vcpkg", "0.2.15"), ("wasm-bindgen", "0.2.87"), ("wasm-bindgen-backend", "0.2.87"), ("wasm-bindgen-macro", "0.2.87"), ("wasm-bindgen-macro-support", "0.2.87"), ("wasm-bindgen-shared", "0.2.87"), ("windows", "0.48.0"), ("windows-targets", "0.48.5"), ("windows_aarch64_gnullvm", "0.48.5"), ("windows_aarch64_msvc", "0.48.5"), ("windows_i686_gnu", "0.48.5"), ("windows_i686_msvc", "0.48.5"), ("windows_x86_64_gnu", "0.48.5"), ("windows_x86_64_gnullvm", "0.48.5"), ("windows_x86_64_msvc", "0.48.5"), ("winnow", "0.5.15")];
/// The indirect dependencies as a comma-separated string.
pub static INDIRECT_DEPENDENCIES_STR: &str = r"android-tzdata 0.1.1, android_system_properties 0.1.5, autocfg 1.1.0, bitflags 2.4.0, bumpalo 3.13.0, cargo-lock 9.0.0, cc 1.0.83, cfg-if 1.0.0, chrono 0.4.29, core-foundation-sys 0.8.4, equivalent 1.0.1, example_project 0.1.0, fixedbitset 0.4.2, form_urlencoded 1.2.0, git2 0.18.0, hashbrown 0.14.0, iana-time-zone 0.1.57, iana-time-zone-haiku 0.1.2, idna 0.4.0, indexmap 2.0.0, jobserver 0.1.26, js-sys 0.3.64, libc 0.2.147, libgit2-sys 0.16.1+1.7.1, libz-sys 1.1.12, log 0.4.20, memchr 2.6.3, num-traits 0.2.16, once_cell 1.18.0, percent-encoding 2.3.0, petgraph 0.6.4, pkg-config 0.3.27, proc-macro2 1.0.66, quote 1.0.33, semver 1.0.18, serde 1.0.188, serde_derive 1.0.188, serde_spanned 0.6.3, syn 2.0.31, tinyvec 1.6.0, tinyvec_macros 0.1.1, toml 0.7.6, toml_datetime 0.6.3, toml_edit 0.19.14, unicode-bidi 0.3.13, unicode-ident 1.0.11, unicode-normalization 0.1.22, url 2.4.1, vcpkg 0.2.15, wasm-bindgen 0.2.87, wasm-bindgen-backend 0.2.87, wasm-bindgen-macro 0.2.87, wasm-bindgen-macro-support 0.2.87, wasm-bindgen-shared 0.2.87, windows 0.48.0, windows-targets 0.48.5, windows_aarch64_gnullvm 0.48.5, windows_aarch64_msvc 0.48.5, windows_i686_gnu 0.48.5, windows_i686_msvc 0.48.5, windows_x86_64_gnu 0.48.5, windows_x86_64_gnullvm 0.48.5, windows_x86_64_msvc 0.48.5, winnow 0.5.15";
§git2
Try to open the git-repository at manifest_location
and retrieve HEAD
tag or commit id.
Notice that GIT_HEAD_REF
is None
if HEAD
is detached or not valid UTF-8.
Continuous Integration platforms like Travis
and AppVeyor
will
do shallow clones, causing libgit2
to be unable to get a meaningful
result. GIT_VERSION
and GIT_DIRTY
will therefore always be None
if
a CI-platform is detected.
/// If the crate was compiled from within a git-repository,
/// `GIT_VERSION` contains HEAD's tag. The short commit id is used
/// if HEAD is not tagged.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_GIT_VERSION`.
pub static GIT_VERSION: Option<&str> = Some("0.4.1-10-gca2af4f");
/// If the repository had dirty/staged files.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_GIT_DIRTY`.
pub static GIT_DIRTY: Option<bool> = Some(true);
/// If the crate was compiled from within a git-repository,
/// `GIT_HEAD_REF` contains full name to the reference pointed to by
/// HEAD (e.g.: `refs/heads/master`). If HEAD is detached or the branch
/// name is not valid UTF-8 `None` will be stored.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_GIT_HEAD_REF`.
pub static GIT_HEAD_REF: Option<&str> = Some("refs/heads/master");
/// If the crate was compiled from within a git-repository,
/// `GIT_COMMIT_HASH` contains HEAD's full commit SHA-1 hash.
/// Can be overridden with `BUILT_OVERRIDE_{pkg_name}_GIT_GIT_COMMIT_HASH`.
pub static GIT_COMMIT_HASH: Option<&str> = Some("ca2af4f11bb8f4f6421c4cccf428bf4862573daf");
/// If the crate was compiled from within a git-repository,
/// `GIT_COMMIT_HASH_SHORT` contains HEAD's short commit SHA-1 hash.
/// Can be overriden using `BUILT_OVERRIDE_{pkg_name}_GIT_COMMIT_HASH_SHORT`.
pub static GIT_COMMIT_HASH_SHORT: Option<&str> = Some("ca2af4f");
§chrono
The build-time is recorded as BUILT_TIME_UTC
. If built
is included as a runtime-dependency,
it can parse the string-representation into a time:Tm
with the help of
built::util::strptime()
.
built
honors the environment variable SOURCE_DATE_EPOCH
. If the variable is defined and
parses to a valid UTC timestamp, that build-time is used instead of the current local time.
The variable is silently ignored if defined but but does not parse to a valid UTC timestamp.
/// The built-time in RFC2822, UTC
/// Can be overridden with`BUILT_OVERRIDE_BUILT_TIME_UTC`; the override takes precedence
/// over `SOURCE_DATE_EPOCH`; it *must* parse via `chrono::DateTime::parse_from_rfc2822()`.
pub static BUILT_TIME_UTC: &str = "Wed, 27 May 2020 18:12:39 +0000";
Re-exports§
Modules§
- util
- Various convenience functions for
built
at runtime.
Enums§
- CIPlatform
- Various Continuous Integration platforms whose presence can be detected.
Functions§
- write_
built_ file - A shorthand for calling
write_built_file_with_opts()
withCARGO_MANIFEST_DIR
and[OUT_DIR]/built.rs
. - write_
built_ file_ with_ opts - Writes rust-code describing the crate at
manifest_location
to a new file nameddst
.