【发布时间】:2018-11-04 02:39:53
【问题描述】:
我想有条件地启用运行时检查和日志记录,它们相互独立,也不受调试和发布模式的影响。所以我开始在我的项目中添加两个features,一个叫做“invariant-checking”,一个叫做“logging”。最终,我希望通过我在项目范围内可见的 crate 中定义的宏来使用它们。
我曾假设,如果我在所有 crate 中以相同方式填写 features section,那么当我在编译 bin crate 时激活该功能时,所有 lib crate 也会启用该功能,但这种情况并非如此!如何跨多个 crate 启用和禁用功能?希望这可以通过仅更改一件事来完成,例如 cargo 的命令行参数。
为了明确我想要什么,here's an example,我还将在下面复制:
共有三个 crate,分别是 main、bin、crate 和两个 lib crate,分别称为“middle”和“common”。以下是相关文件的相关部分:
main.rs
extern crate common;
extern crate middle;
fn main() {
common::check!();
middle::run();
println!("done");
}
主要的Cargo.toml
[dependencies]
[dependencies.common]
path = "libs/common"
[dependencies.middle]
path = "libs/middle"
[features]
default = []
invariant-checking = []
logging = []
中间的lib.rs
extern crate common;
pub fn run() {
common::check!();
common::run();
}
中间的Cargo.toml
[dependencies]
[dependencies.common]
path = "../common"
[features]
default = []
invariant-checking = []
logging = []
common 的 lib.rs
#[macro_export]
macro_rules! check {
() => {{
if cfg!(feature = "invariant-checking") {
println!("invariant-checking {}:{}", file!(), line!());
}
if cfg!(feature = "logging") {
println!("logging {}:{}", file!(), line!());
}
}};
}
pub fn run() {
check!()
}
最后是common的Cargo.toml
[dependencies]
[features]
default = []
invariant-checking = []
logging = []
当我运行cargo run --features "invariant-checking,logging" 时,我得到以下输出
invariant-checking src\main.rs:5
logging src\main.rs:5
done
但也希望它登录中间和普通。我怎样才能改变这个项目,使它能够做到这一点,并且仍然允许我只通过改变一个地方来获得“完成”作为输出?
【问题讨论】:
-
您应该根据
common中选择的功能定义不同的宏,因此功能选择发生在编译时并且仅在common板条箱中。那么你只需要在那个 crate 中声明 features,并且切换 features 将具有全局效果,只要所有 crate 使用相同版本的common。 -
我相信How do I 'pass down' feature flags to subdependencies in Cargo?的答案已经回答了您的问题。如果您不同意,请edit您的问题解释差异。否则,我们可以将此问题标记为已回答。
-
@SvenMarnach 这听起来确实比将标志传递给每个板条箱要少。如果我理解正确,您建议定义多个具有相同名称的宏,并选择使用
#[cfg(feature = "logging")]和#[cfg(not(feature = "logging"))]等属性启用的宏。这样可行。至少在我的玩具示例中,我只需要提及主文件和common的Cargo.toml文件中的功能! -
@Shepmaster 我想以前的答案在技术上可能让我找出答案,但我发现 gnzlbg 的解释比仅仅指出我错过的一小段文档更有帮助。不过,请随意标记这个问题。
-
@Ryan1729 是的,我就是这个意思。既然我在办公桌前,我可以扩展答案(在移动设备上写评论)。
标签: compilation rust rust-cargo