built 0.8.1

repository·master·Indexed 41 days ago

https://github.com/lukaslueg/built

A Rust build-time dependency tool that collects environment metadata—including Git info, compiler versions, target architecture, CI status, and dependency trees—and serializes it into a Rust module for use within an application. It supports overriding metadata via environment variables and provides feature-specific data for Cargo.lock, Git, and build timestamps.

Tokens
3K
Snippets
7
Records
13
Agent score
52%

What's inside built

  1. Set up built as a build-time dependency

    master

    To use built, you must call built::write_built_file() within your build.rs script. This collects build-environment information and serializes it into a Rust file in your OUT_DIR.

    // In build.rs
    fn main() {
        built::write_built_file().expect("Failed to acquire build-time information")
    }
  2. Access build-time information in your code

    master

    After running the build script, you can include the generated information as a module in your lib.rs or main.rs using the include! macro pointing to the file in OUT_DIR. This provides access to metadata such as PKG_VERSION, TARGET, RUSTC_VERSION, and CI_PLATFORM.

    // In lib.rs or main.rs
    
    // Include the generated-file as a separate module
    pub mod built_info {
        include!(concat!(env!("OUT_DIR"), "/built.rs"));
    }
    
    println!(
        "This is version {}, built for {} by {}.",
        built_info::PKG_VERSION,
        built_info::TARGET,
        built_info::RUSTC_VERSION
    );
  3. Override build-time metadata with environment variables

    master

    You can manually set the values collected by built using environment variables. This is useful for automated build systems or achieving reproducible builds.

    Naming Convention: Override variables must be prefixed with BUILT_OVERRIDE_{PKG_NAME}_, where {PKG_NAME} is your package name (with hyphens replaced by underscores). For example, if your package is my-cool-app, the prefix is BUILT_OVERRIDE_my_cool_app_.

    Parsing Rules:

    • Strings: Used as-is.
    • Integers/Booleans: Must implement std::str::FromStr.
    • Options (Option<T>): Use BUILT_OVERRIDE_NONE to force None. Any other value must parse as T.
    • Lists: Parsed as comma-separated values.

    If an override variable cannot be parsed, the build will panic.

  4. Override environment variables during build

    master

    You can force specific values for environment variables during the build process by using the BUILT_OVERRIDE_ prefix. The prefix is dynamically generated based on your package name (with hyphens replaced by underscores).

    Pattern: BUILT_OVERRIDE_<package_name_with_underscores>_<VARIABLE_NAME>

    Example: If your package name is example-project, the prefix is BUILT_OVERRIDE_example_project_. To override the RUSTC path, set the environment variable: BUILT_OVERRIDE_example_project_RUSTC=/path/to/custom/rustc

  5. Setup `built` in your Rust project

    master

    To use built to collect build-time metadata, follow these three steps:

    1. Add as a build dependency: Add built to your [build-dependencies] in Cargo.toml.
    2. Configure build script: Create or modify build.rs to call built::write_built_file().
    3. Include generated code: In your crate (e.g., main.rs or lib.rs), use the include! macro to pull in the generated built.rs file from the OUT_DIR.

    Note: built does not add runtime dependencies unless you explicitly enable features like chrono or semver and include them in your runtime dependency list.

    [package]
    build = "build.rs"
    
    [build-dependencies]
    built = "0.8"
    // build.rs
    fn main() {
        built::write_built_file().expect("Failed to acquire build-time information");
    }
    // main.rs
    pub mod built_info {
       include!(concat!(env!("OUT_DIR"), "/built.rs"));
    }
  6. Detect CI platforms and execution environment

    master

    The generated built_info module contains a CI_PLATFORM field (an Option<&str>) indicating if the crate was built on a platform like Github Actions, Travis CI, or AppVeyor. Additionally, you can use built::util::detect_ci() to check if the code is currently executing on a CI platform.

    match built_info::CI_PLATFORM {
        None => print!("It seems I've not been built on a continuous integration platform,"),
        Some(ci) => print!("I've been built on CI-platform {},", ci),
    }
    
    if built::util::detect_ci().is_some() {
        println!(" but I'm currently executing on one!");
    } else {
        println!(" and I'm currently not executing on one!");
    }
  7. Detect CI platforms

    master

    The detect_ci() method on EnvironmentMap attempts to identify the Continuous Integration environment by checking for specific environment variables.

    It returns an Option<CIPlatform>. Supported platforms include:

    • GitHubActions (GITHUB_ACTIONS)
    • GitLab (GITLAB_CI)
    • Circle (CIRCLECI)
    • Travis (TRAVIS)
    • Jenkins (JENKINS_URL)
    • Buildkite (BUILDKITE)
    • ...and many others (AppVeyor, Drone, TeamCity, etc.).

    If no specific platform is recognized but a generic CI variable is present, it returns CIPlatform::Generic.

  8. Write build-time information to a file

    master

    The built crate provides two main functions to generate the built.rs file during the build process:

    1. write_built_file(): A shorthand that writes to [OUT_DIR]/built.rs using CARGO_MANIFEST_DIR as the manifest location. This is the recommended function for most users.
    2. write_built_file_with_opts(manifest_location: Option<&Path>, dst: &Path): Allows specifying a custom manifest location and a custom destination path.

    Both functions return io::Result<()>.

    // Standard usage in build.rs
    fn main() {
        built::write_built_file().expect("Failed to write built file");
    }
  9. Write build information to a file using EnvironmentMap

    master

    The EnvironmentMap provides several methods to serialize build-time information into a file (typically for generating a metadata file that can be embedded in a binary). These methods use internal macros to write structured data.

    Available writing methods:

    • write_env(&mut File): Writes standard Cargo variables (version, authors, target, profile, etc.).
    • write_features(&mut File): Writes enabled features as arrays and comma-separated strings.
    • write_cfg(&mut File): Writes target configuration (arch, endian, os, etc.).
    • write_compiler_version(&mut File): Writes the RUSTC_VERSION and RUSTDOC_VERSION.
    • write_ci(&mut File): Writes the detected CI_PLATFORM.

    Note: These methods require a std::fs::File and return std::io::Result<()>.

    use std::fs::File;
    
    let env_map = EnvironmentMap::new();
    let mut file = File::create("build_info.txt")?;
    
    env_map.write_env(&mut file)?;
    env_map.write_features(&mut file)?;
    env_map.write_cfg(&mut file)?;
    env_map.write_compiler_version(&mut file)?;
    env_map.write_ci(&mut file)?;
  10. Use EnvironmentMap to access build-time environment variables

    master

    The EnvironmentMap struct provides a way to query environment variables present during the compilation of the project. It can retrieve standard Cargo environment variables (like CARGO_PKG_VERSION) or custom override variables.

    To use overrides, prefix the environment variable name with BUILT_OVERRIDE_<CARGO_PKG_NAME>_. For example, if your package name is my-crate, you can override CARGO_PKG_VERSION by setting BUILT_OVERRIDE_my_crate_CARGO_PKG_VERSION in your environment.

    // Initialize the map with current environment variables
    let env_map = EnvironmentMap::new();
    
    // Get a standard environment variable
    if let Some(version) = env_map.get("CARGO_PKG_VERSION") {
        println!("Version: {}", version);
    }
    
    // Get an override variable with a specific type
    // Note: T must implement util::ParseFromEnv
    if let Some(opt_level) = env_map.get_override_var::<String>("OPT_LEVEL") {
        println!("Override Opt Level: {}", opt_level);
    }
  11. Reference: Always available build-time metadata

    master

    The following static variables are always available in the generated built.rs file, regardless of enabled features:

    VariableTypeDescription
    CI_PLATFORMOption<&str>The detected CI platform
    PKG_VERSION&strFull version string
    PKG_VERSION_MAJOR&strMajor version
    PKG_VERSION_MINOR&strMinor version
    PKG_VERSION_PATCH&strPatch version
    PKG_VERSION_PRE&strPre-release version
    PKG_AUTHORS&strColon-separated list of authors
    PKG_NAME&strPackage name
    PKG_DESCRIPTION&strPackage description
    PKG_HOMEPAGE&strHomepage URL
    PKG_LICENSE&strLicense
    PKG_REPOSITORY&strRepository URL
    TARGET&strTarget triple
    HOST&strHost triple
    PROFILE&strrelease or debug
    RUSTC&strCompiler name
    RUSTC_VERSION&strOutput of rustc -V
    RUSTDOC&strDocumentation generator name
    RUSTDOC_VERSION&strOutput of rustdoc -V
    OPT_LEVEL&strOptimization level
    NUM_JOBSu32Parallelism used
    DEBUGboolDebug flag status
    FEATURES[&str; 0]Enabled features
    FEATURES_STR&strFeatures as comma-separated string
    CFG_TARGET_ARCH&strTarget architecture
    CFG_ENDIAN&strTarget endianness
    CFG_ENV&strTarget environment
    CFG_FAMILY&strTarget OS family
    CFG_OS&strTarget operating system
    CFG_POINTER_WIDTH&strPointer width
    OVERRIDE_VARIABLES_USED[&str; N]List of override variables used during compilation