Cargo
和编译器
团队很高兴地宣布
,从Rust1.80
(或nightly-2024-05-05
)开始,会自动检查
每个可访问的#[cfg]
,看看是否与期望的配置名和值
匹配.
这帮助验证crate
,是否正确处理不同目标平台或函数
的条件编译
.它确保在期望和使用设置
的配置
间保持一致
,帮助在开发过程的早期
抓住潜在的错误
.
特征一览
每次声明Cargo
特征时,都会按传递给rustc
(Rust
编译器)的配置转换
,这样可与周知的配置
一起验证#[cfg],#![cfg_attr]
和cfg!
的配置是否有意外,并使用unexpected_cfgs
检查来报告警告
.
Cargo.toml
中:
[package]
name = "foo"
[features]
lasers = []
zapping = []
src/lib.rs:
#[cfg(feature = "lasers")] //此条件是期望的,因为`"lasers"`是`'feature'`cfg`的期望值
fn shoot_lasers() {}
#[cfg(feature = "monkeys")] //它是意外的,因为`"monkeys"`不是`'feature'cfg`的期望值
fn write_shakespeare() {}
#[cfg(windosw)] //它是意外的,它应该是`"窗口"`
fn win() {}
需要自定义配置
更新:此节是在nightly-2024-05-19
的发布中添加的.
从Cargo
来看:自定义配置
既不是由rustc
定义的,也不是由Cargo
函数定义的.想想tokio_unstable,has_foo......
.但不是feature="lasers",unix
或debug_assertions
.
一些crate
可用自定义配置
,如loom,fuzzing
或期望从环境
中取得(RUSTFLAGS
或其他方式)且在编译时
总是是静态已知
的tokio_unstable
.
对这些,Cargo
通过[lints]
表来如期
静态声明这些配置
.
通过在[lints.rust.unexpected_cfgs]
下的特殊check-cfg
配置,如期定义这些自定义配置
:
Cargo.toml
文件
[lints.rust]
unexpected_cfgs = { level = "warn", checkcfg = ['cfg(loom)', 'cfg(fuzzing)'] }
构建脚本中的自定义配置
另一方面,一些crate
使用由build.rs
中的某些逻辑
启用的自定义配置
.对这些crate
,Cargo
提供了一个新指令
:cargo::rustc-check-cfg
(或较旧的Cargo
版本的cargo:rustc-check-cfg
).
在rustcbook
检查配置节描述了使用的语法
,总之,--check-cfg
的基本语法
是:
cfg(name, values("value1", "value2", ..., "valueN"))
注意,无论配置
是否活动,每个自定义配置
都必须总是是期望
的!
build.rs
示例
build.rs:
fn main() {
println!("cargo::rustccheckcfg=cfg(has_foo)");
//^^^^^^^^^^^^^^^^^^^^^^`Cargo1.80`的新功能
if has_foo() {
println!("cargo::rustccfg=has_foo");
}
}
每个cargo::rustccfg
都应该有一个附带的无条件cargo::rustc-check-cfg
指令,以避免此警告:未期望的条件名:has_foo
.
等价表
第一列 | 第二列 |
---|---|
货物::rustc-cfg | 货物::rustc-check-cfg |
foo | cfg(foo) 或cfg(foo,values(none())) |
foo="" | cfg(foo,values("")) |
foo="bar" | cfg(foo,values("bar")) |
foo="1" 和foo="2" | cfg(foo,values("1","2")) |
foo="1" 和bar="2" | cfg(foo,values("1")) 和cfg(bar,values("2")) |
foo 和foo="bar" | cfg(foo,values(none(),"bar")) |
常见问题解答
可禁止吗
对Cargo
用户,该功能总是打开
且无法禁止
,但与其他检查
一样,可控制它:#![warn(unexpected_cfgs)]
.
检查
是否会影响依赖
不会,和大多数检查
一样,因为cap-lints
,unexpected_cfgs
只会报告本地包
.
它如何与RUSTFLAGS
环境交互
应该可如前
使用RUSTFLAGS
环境变量.当前不检查--配置
参数,只检查代码中的用法
.
即RUSTFLAGS="--cfg tokio_unstable" cargo check
不会报告警告,除非在本地crate
中使用tokio_unstable
,此时,crate
作者需要确保该crate
的`build.
rs中带
cargo::rustccheckcfg的自定义
配置`.
如何在没有build.rs
时期待自定义配置
更新:nightly-2024-05-19
的Cargo
现在提供[lints.rust.unexpected_cfgs.checkcfg]
配置来定位静态已知
的自定义配置
.
如果Crate
作者不想使用build.rs
且不能[lints.rust.unexpected_cfgs.checkcfg]
,鼓励他们改用Cargo
特征.
它如何与其他构建系统交互
默认,不基于Cargo
的构建系统
不受检查
的影响.想拥有相同特征的构建系统作者
应该查看rustc
文档中的--checkcfg
标志,以取如何实现相同功能
的详细说明
.
稳定实现
和RFC3013
有很大的不同
,特别是--check-cfg
只有一个形式:cfg()
而不是values()
和names()
不完整且彼此不兼容
.
cargo::rustccheckcfg
将在Rust1.80
(或nightly-2024-05-05
)中开始工作
.从Rust1.77
到Rust1.79
(含)会静默忽略它
.在Rust1.76
及更低版本
中,在没有不稳定的Cargo
标志-Zcheck-cfg
时使用时会发出警告
.