#semver #git #git-version #build-script #no-std

no-std build git-tags-semver

Tool to extract SemVer Version Information from annotated git tags

1 unstable release

0.3.0 Apr 19, 2024

#1001 in Embedded development

OLFL-1.3

24KB
238 lines

git-tags-semver

Tool to extract SemVer Version Information from annotated git tags This package allows to extract SemVer version information from annotated git tags in the format "vX.Y.Z". It is used from build.rs build scripts. For usage details, see the API documentation.

This crate is made to call and parse the git describe command. It is assumed that the repo uses annotated git tags in the format "vX.Y.Z" or "vX.Y.Z-rc". So for example, the first commit of the release candidate branch for 1.0.0 should be tagged with "v1.0.0-rc" and the actual 1.0.0 release should be tagged with "v1.0.0". This information has to be extracted at compile time so it needs to be done in a build.rs. Since the build.rs is run in the directory of the crate it belongs to, your project itself should contain that build.rs, i.e. it should not be done in a git submodule or a dependency of your project. The following build.rs will write the version information to version.rs in the current OUT_DIR directory which is "the folder in which all output and intermediate artifacts should be placed" by build scripts:

use std::env;
use std::fs;
use std::path::Path;
use std::process::Command;

fn main() {
    // Tell Cargo that if the given file changes, to rerun this build script (adjust the path
    // to the .git directory accordingly if required, e.g. when the crate is in a workspace)
    println!("cargo:rerun-if-changed=.git/index");
    println!("cargo:rerun-if-changed=.git/HEAD");
    println!("cargo:rerun-if-changed=.git/logs/HEAD");
    println!("cargo:rerun-if-changed=build.rs");

    // Extract the version information and generate the corresponding code
    let out = git_tags_semver::generate_version_file().unwrap();

    // Write the generated version information code to version.rs in the OUT_DIR directory
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("version.rs");
    fs::write(&dest_path, &out).unwrap();

    // Touch build.rs to force recompilation on every workspace build. This may be desirable
    // because it ensures that the information is guaranteed to be up-to-date. On the other
    // hand, it may slow down your development process a tiny little bit because it enforces
    // a rebuild all the time. For example, your crate will be rebuilt before each `cargo run`
    // which does not happen normally (if the crate was built before, it can normally be run
    // immediately).
    Command::new("touch")
        .args(&["build.rs"])
        .output()
        .expect("Could not touch build.rs!");

}

Afterwards, <OUT_DIR>/version.rs contains a pub const GitVersion<'static>. Specifically, that file looks like:

pub const VERSION: git_tags_semver::GitVersion<'static> = git_tags_semver::GitVersion {
    semver: Some(git_tags_semver::SemanticVersion {
        major: 1,
        minor: 0,
        patch: 0,
        rc: false,
        commits: 0
    }),
    hash: [
        0x12,
        0x34,
        0xab,
        0xcd,
    ],
    dirty: false,
    git_string: "v1.0.0-00-g1234abcd"
};

To use it in your application, you can include the generated code like that:

include!(concat!(env!("OUT_DIR"), "/version.rs"));

fn main() {
    println!("{:?}", VERSION);
}

Cargo.toml / Feature-Gates

This tool is especially designed to be used in no_std contexts, e.g. bare-metal firmwares. Therefore, it is generally no_std (the type definitions) but for extracting and writing the version information to an intermediate file, it needs the standard library (and build.rs is run with std, even for no_std packages). Thus, the standard library usage which enables the part required in the build.rs has to be enabled with the "build" feature. So, for a no_std package, you need to add it as a dependency twice, the corresponding part in your Cargo.toml could look like this:

[dependencies]
git-tags-semver = { version = "1.0.0" }

[build-dependencies]
git-tags-semver = { version = "1.0.0", features = ["build"] }

Note that this additionally requires to use feature resolver version 2 for your project which is the default since Rust's 2021 edition or can be specified with resolver = "2" in your Cargo.toml (if using a workspace, this must be done in the top-level/workspace Cargo.toml).

License

Open Logistics Foundation License Version 1.3, January 2023
See the LICENSE file in the top-level directory.

Contact

Fraunhofer IML Embedded Rust Group - embedded-rust@iml.fraunhofer.de

Dependencies

~0–510KB