一 Rust 程序如何访问其 Cargo 包的元数据?

268

如何在Rust代码中访问Cargo包的元数据(例如版本)?在我的情况下,我正在构建一个命令行工具,我希望有一个标准的--version标志,并且我希望实现从Cargo.toml读取包的版本,以便我不必在两个地方维护它。我可以想象其他人也可能因为其他原因需要从程序中访问Cargo元数据。

3个回答

392
Cargo通过环境变量向编译器传递一些元数据,可以在Cargo文档页面中找到列表。
编译器环境由Cargo代码中的fill_env填充。自早期版本以来,此代码已变得更加复杂,并且整个变量列表不再显而易见,因为它可能是动态的。但是,至少设置了以下变量(来自文档中的列表):
CARGO_MANIFEST_DIR
CARGO_PKG_AUTHORS
CARGO_PKG_DESCRIPTION
CARGO_PKG_HOMEPAGE
CARGO_PKG_NAME
CARGO_PKG_REPOSITORY
CARGO_PKG_VERSION
CARGO_PKG_VERSION_MAJOR
CARGO_PKG_VERSION_MINOR
CARGO_PKG_VERSION_PATCH
CARGO_PKG_VERSION_PRE

您可以使用env!()宏访问环境变量。要插入程序的版本号,可以执行以下操作:
const VERSION: &str = env!("CARGO_PKG_VERSION");

// ...

println!("MyProgram v{}", VERSION);

如果您希望程序即使没有Cargo也能编译,可以使用option_env!():
const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION");

// ...

println!("MyProgram v{}", VERSION.unwrap_or("unknown"));

6
这是运行时还是编译时? - debuti
7
在文档中所述的情况下,@debuti指的是编译时。 - tamasfe
1
只是想告诉搜索者,由于这是一个编译时解决方案并使用环境变量,因此它将无法解析工作区成员的子箱的元数据。 - Eray Erdin

28

built crate可帮助您在不需要繁琐的样板代码的情况下对Cargo环境进行序列化。


1
built 还会添加 git sha-1(以及许多其他有用的东西) - Graham King

8
在构建时(例如在build.rs中),cargo_metadata可能会很有用。例如:
let path = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let meta = MetadataCommand::new()
    .manifest_path("./Cargo.toml")
    .current_dir(&path)
    .exec()
    .unwrap();

let root = meta.root_package().unwrap();
let option = root.metadata["my"]["option"].as_str().unwrap();
let version = &root.version;
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接