Cargo 自行激活功能

NoK*_*Key 0 cargo rust

我有一个依赖于库的二进制文件。在库中,我指定了这些功能:

[features]
default = []
fet = []
Run Code Online (Sandbox Code Playgroud)

我希望功能fet只有在使用功能标志编译时才会被激活。在我的二进制文件中,它Cargo.toml看起来像这样:

[dependencies]
a = { path = "./a" }

[features]
default = []
Run Code Online (Sandbox Code Playgroud)

我没有指定fet的功能Cargo.toml,但是这给了我在我的二进制编译错误:

fn main() {
    if cfg!(feature = "fet") {
        compile_error!("not expected");
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么fet我的二进制文件中的功能仍处于激活状态?我执行了这些命令并得到相同的错误:

cargo run
cargo run --features=default
Run Code Online (Sandbox Code Playgroud)

理想情况下,我希望我的二进制文件从依赖项中激活某些功能,如果它们在cargo run命令中(在--features标志中)明确提及。这可能吗?我希望这能在我的二进制文件中工作Cargo.toml

[features]
default = []
fet = ["a/fet"]
Run Code Online (Sandbox Code Playgroud)

fet如果我运行此命令,则功能将被激活:

cargo run --features=fet
Run Code Online (Sandbox Code Playgroud)

Frx*_*rem 6

cfg!宏将扩大到true或者false取决于如果条件是真的还是假的,所以,如果没有设置功能标志,它仍然会扩展成:

fn main() {
    if false {
        compile_error!("not expected");
    }
}
Run Code Online (Sandbox Code Playgroud)

compile_error!宏将仍然被调用,所以你会得到编译器错误两种方式。

cfg!当您可以依靠编译器优化永远不会被采用的if false分支(例如分支)时,该宏最有用。但是,代码在优化之前仍然需要编译,因此当代码仅在条件为真或为假时才编译时,它的用处不大。

您想要使用的是#[cfg]属性或cfg_if::cfg_if!宏:

// with #[cfg] attribute

fn main() {
    #[cfg(feature = "fet")]
    compile_error!("not expected");
}

// with cfg_if!
use cfg_if::cfg_if;

fn main() {
    cfg_if!{
        if #[cfg(feature = "fet")] {
            compile_error!("not expected");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @NoKey 如果您希望 dev-dependencies 的功能不影响常规依赖项(以额外构建为代价),请使用 `resolver = "2"`:https://doc.rust-lang.org/cargo/reference/features .html#feature-resolver-version-2 (2认同)