尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Bosion:为 Rust CLI 生成 rustc -Vv 风格的长版本信息的构建期收集器

Bosion:为 Rust CLI 生成 rustc -Vv 风格的长版本信息的构建期收集器 开发工具CLI【免费下载链接】watchexecExecutes commands in response to file modifications项目地址https://gitcode.com/gh_mirrors/wa/watchexec点击查看免费下载Bosion 是一个运行在 Cargo 构建脚本build.rs中的 Rust 库用于在编译期采集 crate 版本、启用的 features、构建日期/时间以及 Git 提交信息并生成可直接嵌入二进制程序的版本常量。本文以 crates/bosion/README.md 为主线结合 lib.rs、info.rs 的源码实现讲解其接入方式、四种输出形态、配置项与原理并演示 Watchexec 是如何用它打造出--version的长版本输出的。Bosion 解决什么问题CLI 工具在排查问题时--version输出越详细越有价值。rustc -Vv就是一个范例除了版本号还列出 commit-hash、commit-date、host、release、LLVM version 等字段。Bosion 的目标就是Gather build information for verbose versions flags——在构建期收集这些信息供 verbose 版本标志使用。它特别适合通过多种方式分发安装的 Rust 程序cargo install、预编译二进制、带 Git 仓库的源码编译、以及不带 Git 的源码包如 tarball等。无论以哪种方式构建都能生成合理可用的版本信息。Watchexec 的 CLI 正是它的实际使用者见 crates/cli/Cargo.toml 中的[build-dependencies.bosion]。快速上手三步接入1. 在 Cargo.toml 添加构建期依赖在 crate 的[build-dependencies]中加入[build-dependencies] bosion 2.0.0注意必须是build-dependencies而不是dependencies——Bosion 只在构建期运行不会进入最终二进制。2. 在 build.rs 调用 gatherfn main() { bosion::gather(); }gather()是 lib.rs 中定义的便捷封装它把收集结果写入OUT_DIR/bosion.rsCargo 约定的输出目录生成一个pub(crate)可见、名为Bosion的零大小结构体并通过cargo:rustc-envBOSION_PATH...把生成文件的绝对路径暴露给编译单元。3. 在 src/main.rs 引入生成代码include!(env!(BOSION_PATH)); fn main() { // 默认输出格式类似 rustc -Vv println!({}, Bosion::LONG_VERSION); // 追加自定义字段 println!({}, Bosion::long_version_with([ (custom data, value), (LLVM version, 15.0.6), ])); // 启用的 features如 feature an-other println!({}, Bosion::CRATE_FEATURE_STRING); // 原始数据 println!({}, Bosion::GIT_COMMIT_HASH); println!({}, Bosion::GIT_COMMIT_SHORTHASH); println!({}, Bosion::GIT_COMMIT_DATE); println!({}, Bosion::GIT_COMMIT_DATETIME); println!({}, Bosion::CRATE_VERSION); println!({:?}, Bosion::CRATE_FEATURES); println!({}, Bosion::BUILD_DATE); println!({}, Bosion::BUILD_DATETIME); }include!(env!(BOSION_PATH))在编译期把生成的结构体源码直接嵌入因此所有常量都是static str或静态切片运行时零开销。生成代码的成员一览从 lib.rs 的代码生成模板可以看出Bosion结构体包含以下常量成员类型含义LONG_VERSIONstatic strclap 可直接使用的长版本字符串含版本、features、构建日期有 Git 信息时还包含 commitCRATE_VERSIONstatic strcrate 版本来自 Cargo也可直接读CARGO_PKG_VERSION环境变量CRATE_FEATURESstatic [static str]构建时启用的 feature 列表小写、下划线转连字符CRATE_FEATURE_STRINGstatic strfeatures 的字符串形式格式feature feature2BUILD_DATEstatic str构建日期YYYY-MM-DDBUILD_DATETIMEstatic str构建日期时间YYYY-MM-DD HH:MM:SSGIT_COMMIT_HASHstatic str完整 commit 哈希启用gitfeature 且有仓库时GIT_COMMIT_SHORTHASHstatic str8 字符短哈希GIT_COMMIT_DATEstatic strcommit 日期YYYY-MM-DDGIT_COMMIT_DATETIMEstatic strcommit 日期时间long_version_with(extra)方法需stdfeature在LONG_VERSION末尾按相同格式追加key: value对日期与时间均为 UTC 格式见 info.rs 中的format_description!宏定义。生成代码自带完整文档注释若使用公开可见性还会出现在 docs.rs 的文档中。与 clap 集成LONG_VERSION被设计为 clap 的long_version直接可用use clap::Parser; include!(env!(BOSION_PATH)); #[derive(Parser)] #[clap(version, long_version Bosion::LONG_VERSION)] struct Args { /* ... */ }这正是 examples/clap/src/main.rs 中官方示例的做法也是 crates/cli/src/args.rs 中 Watchexec CLI 的真实用法long_version Bosion::LONG_VERSION。clap 的行为是短-V输出version长--version输出long_version。高级用法生成公开可见的结构体// build.rs bosion::gather_pub();gather_pub()lib.rs与gather()的唯一区别是生成pub struct Bosion而非pub(crate)便于在库 crate 中跨模块使用并让生成代码出现在公开文档中。自定义输出文件名与结构体名// build.rs bosion::gather_to(buildinfo.rs, Build, /* public? */ false);gather_tolib.rs是底层实现三个参数分别控制文件名、结构体名和可见性。文件总是写入OUT_DIR目录同时把路径通过BOSION_PATH环境变量告知 rustc。输出到环境变量替代源码生成// build.rs bosion::gather_to_env(); // src/main.rs fn main() { println!({}, env!(BOSION_GIT_COMMIT_HASH)); println!({}, env!(BOSION_GIT_COMMIT_SHORTHASH)); println!({}, env!(BOSION_GIT_COMMIT_DATE)); println!({}, env!(BOSION_GIT_COMMIT_DATETIME)); println!({}, env!(BOSION_BUILD_DATE)); println!({}, env!(BOSION_BUILD_DATETIME)); println!({}, env!(BOSION_CRATE_VERSION)); println!({}, env!(BOSION_CRATE_FEATURES)); // 逗号分隔 }这种方式不生成任何新代码也不会把未使用的信息带进二进制适合只用到少量字段的场景。它的局限是没有 clap 现成的LONG_VERSION字符串需要自行拼接。自定义环境变量前缀// build.rs bosion::gather_to_env_with_prefix(MYAPP_);gather_to_env_with_prefixlib.rs接受任意前缀约定俗成用全大写并以_结尾例如MYAPP_会产出MYAPP_GIT_COMMIT_HASH等变量。Features 配置Bosion 自身有三个 feature见 Cargo.tomlreproducible默认开启读取SOURCE_DATE_EPOCH环境变量可复现构建标准存在时用其时间戳替代当前时间同时输出cargo:rerun-if-env-changedSOURCE_DATE_EPOCH环境变化即触发重建。git默认开启启用 Git 信息收集。这会引入可选的flate2依赖——Git 对象以 zlib 压缩存储读取 loose 对象与 packfile 时需要解压。std默认开启提供long_version_with方法。注意它控制的是使用方 crate的 std 支持Bosion 自身始终依赖 std它运行在 build.rs 中。需要指出的是git与reproducible这两个默认 feature 的组合意味着默认配置下Bosion 构建时若找不到SOURCE_DATE_EPOCH就采用当前时间作为构建日期这会破坏可复现构建——因此需要可复现构建的发布流程应当显式设置该环境变量。底层原理从源码结构看收集过程信息从哪来info.rs 中的Info::gather()定义了所有数据的来源crate_version读CARGO_PKG_VERSION环境变量Cargo 构建脚本注入crate_features遍历环境变量中所有CARGO_FEATURE_*前缀将下划线替换为连字符并转小写info.rsbuild_date/build_datetimeUTC 当前时间或SOURCE_DATE_EPOCH指定的时间戳gitGit 仓库信息读取失败时置为None并打印cargo:warninggit info gathering failed: ...警告info.rs。不依赖 git CLI 的 Git 读取这是 Bosion 与同类工具的关键差异。从 info.rs 的GitInfo::gather()可以看出它不使用git可执行文件而是直接解析.git目录结构定位仓库从当前目录向上逐级查找.gitinfo.rs支持.git为文件时的 git worktree 情形读取其中的gitdir: path指向解析 HEAD读取HEAD文件若为ref: refs/heads/...则解析引用的哈希否则为 detached HEAD 直接使用哈希引用可能位于 loose ref 文件或packed-refs中info.rs读取 commit 时间戳先在objects/xx/yyyy...中解压 loose 对象zlib未命中则遍历objects/pack/*.idx二分查找对象再读取 packfileinfo.rsread_commit_timestamp从 commit 对象内容中解析committer行的时间戳info.rs。短哈希固定截取前 8 个字符info.rs。需要说明的是pack 读取对 delta 压缩对象类型 6/7暂不支持会返回None。重新构建的触发条件set_reruns()info.rs输出 Cargo 的 rerun 指令cargo:rerun-if-env-changedSOURCE_DATE_EPOCH启用reproducible时cargo:rerun-if-changedgit_root/HEAD存在 Git 信息时即仓库 HEAD 变化会触发重建。这保证了版本信息不会陈旧。gather_to还通过println!(cargo:rustc-envBOSION_PATH...)lib.rs把生成文件路径暴露给 rustc。真实输出效果README 给出了 Watchexec CLI 的--version输出watchexec 1.21.1 (5026793 2023-03-05) commit-hash: 5026793a12ff895edf2dafb92111e7bd1767650e commit-date: 2023-03-05 build-date: 2023-03-05 release: 1.21.1 features:与rustc -Vv对比rustc 1.67.1 (d5a82bbd2 2023-02-07) binary: rustc commit-hash: d5a82bbd26e1ad8b7401f6a718a9c57c96905483 commit-date: 2023-02-07 host: x86_64-unknown-linux-gnu release: 1.67.1 LLVM version: 15.0.6LONG_VERSION的生成逻辑在 lib.rs 中有 Git 信息时首行为版本 (短哈希 提交日期) features无 Git 时退化为版本 (构建日期) features随后的key: value行固定包含 commit-hash/commit-date 或 build-date、release、features。features 字段来自CRATE_FEATURES的逗号拼接含default。long_version_with可以继续追加如LLVM version: 15.0.6这样的自定义行。仓库的集成测试通过快照机制验证了这一点examples/default/src/main.rs 与 examples/no-git/src/main.rs 将各常量与 snapshots 下的模板比对模板中以{git hash}、{today date}等占位符动态替换实际值。例如 default_long_version.txt 记录了带 Git 时的长版本模板no_git_long_version.txt 记录了无 Git 时的退化形态run-tests.sh 会对每个示例子 crate 依次执行cargo check与cargo test。与同类库的取舍README 的 Why not...? 一节列出了 Bosion 与常见替代品的差异bugreport / human-panic运行期库用于收集 bug 报告或 panic 信息与构建期版本信息用途不同git-testament / vergen通过调用gitCLI 获取信息而 Bosion 直接解析.git目录不依赖环境中是否存在 git 可执行文件shadow-rs底层使用 libgit2且不会在 Git 提交变化时自动重建。Bosion 在 build.rs 之外零依赖这也是它能覆盖cargo install、预编译二进制、带/不带 Git 的源码编译等多种安装方式的原因。选择哪款工具取决于具体场景若你的构建环境保证有 git 可用vergen 等也是合理选择若追求构建环境无关性Bosion 的纯目录解析方案更有优势。适用场景与注意事项适用需要rustc -Vv风格长版本输出的 CLI/库 crate以多种方式分发安装的 Rust 程序使用 clap 的--version增强。版本与运行环境Bosion 2.x 要求 Rust 1.64.0 与 edition 2021见 Cargo.toml并依赖time0.3 crate 处理日期时间。dirty 工作区commit 相关常量取自 HEAD 提交本身不感知未提交的改动源码注释与生成的文档均已说明此限制。delta 压缩对象当前实现对 packfile 中的 delta 对象暂不解析极端情况下可能读不到提交时间戳此时 Git 字段整体为None并发出构建警告。可复现构建发布构建请设置SOURCE_DATE_EPOCH否则默认使用当前时间。按上述步骤接入后运行cargo build时构建脚本会自动完成信息收集、代码生成与重跑触发cargo run -- --version即可看到完整的版本信息。赞分享开发工具CLI【免费下载链接】watchexecExecutes commands in response to file modifications项目地址https://gitcode.com/gh_mirrors/wa/watchexec点击查看免费下载相关推荐Bosion 构建信息收集指南从 CHANGELOG 读懂 watchexec 生态的 clap 兼容版本信息生成方案Bosion 构建信息收集指南从 CHANGELOG 读懂 watchexec 生态的 clap 兼容版本信息生成方案 Bosion 是 watchexec开发工具CLIDeepSeek Coder 33B Instruct性能评测在HumanEval、MBPP等基准测试中的表现DeepSeek Coder 33B Instruct性能评测在HumanEval、MBPP等基准测试中的表现 DeepSeek Coder 33B Instfastfetch版本信息软件版本与构建信息fastfetch版本信息软件版本与构建信息 概述 fastfetch作为一款高性能的系统信息工具其自身的版本信息管理机制体现了开发者对软件质量和用户体验的CLI上一篇Wayback Machine网页存档扩展你的终极互联网时光机使用指南下一篇告别臃肿Windows 11一键优化让电脑重获新生的终极方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表