有的时候我们在发布一些Cli工具时,除了明确的版本号之外,还想要添加对应的Git CommitId号;
这个功能可以通过 build.rs 脚本实现;
源代码:
为Cargo编译的可执行文件增加commit版本号
build.rs简要说明
一些项目希望编译第三方的非 Rust 代码,例如 C 依赖库;一些希望链接本地或者基于源码构建的 C 依赖库;还有一些项目需要功能性的工具,例如在构建之前执行一些代码生成的工作等;
此时,可以使用项目根目录下的 build.rs 创建构建脚本;
例如:
build.rs
1 | fn main() { |
关于构建脚本的一些使用场景如下:
- 构建 C 依赖库;
- 在操作系统中寻找指定的 C 依赖库;
- 根据某个说明描述文件生成一个 Rust 模块;
- 执行一些平台相关的配置等等;
更详细见:
增加Commit版本号
对于在可执行文件中增加commit版本号,我们可以:
首先,在 build.rs 中读取 Cargo.toml 里定义好的版本号,并执行 git 命令获取最新的 CommitId 写入到编译目录中的一个文件;
随后在源代码里中定义一个字符串常量,读取上面文件中的内容即可!
例如:
build.rs
1 | use std::env; |
上面通过 get_git_version 函数获取到 version 字符串,并最后写入到 ${OUT_DIR}/VERSION 文件中;
在 get_git_version 函数中:
- 首先,通过
CARGO_PKG_VERSION环境变量获取到了 Cargo.toml 中定义的版本; - 然后,调用
git describe --always命令读取当前的 commitId;当然,如果获取失败则直接使用 Cargo 中的 version;
在二进制中读取版本号
上面在编译之前生成了版本号,因此我们可以在代码中读取到这个记录版本号的文件;
例如:
src/main.rs
1 | pub const VERSION: &str = include_str!(concat!(env!("OUT_DIR"), "/VERSION")); |
上面的 VERSION 常量字符串, 就包含了 $OUT_DIR/VERSION 文件中的内容;
其中:
include_str!()宏用于读取 UTF-8 编码的文本文件,默认路径相对于当前源文件;concat!()宏用于合并字符串;env!()宏用于展开编译时的环境变量;
最终测试结果:
1 | $ cargo run |
附录
文章参考:
- https://blog.biofan.org/2019/08/cargo-build-script/
- https://course.rs/cargo/reference/build-script/intro.html
源代码: