Bootstrap

2411rust,编译时自动检查配置

原文

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",unixdebug_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
foocfg(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"))
foofoo="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-19Cargo现在提供[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.77Rust1.79(含)会静默忽略它.在Rust1.76更低版本中,在没有不稳定的Cargo标志-Zcheck-cfg时使用时会发出警告.

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;