检查条件配置
rustc
支持检查每个可达的1 #[cfg]
是否与预期的配置名称和值列表匹配。
这有助于验证 crate 是否正确处理了针对不同目标平台或功能的条件编译。它可以确保 cfg 设置在预期用途和实际使用之间保持一致,从而帮助在开发过程的早期捕获潜在的错误或问题。
为了实现这个目标,rustc
接受 --check-cfg
标志,该标志指定是否检查条件以及如何检查条件。
注意: 要通过 Cargo 与此交互,请参阅 Cargo Specifics 页面。
rustc
承诺至少检查可达的 #[cfg]
,虽然目前不检查不可达的 #[cfg]
,但将来很可能会检查它们,而这不会构成破坏性更改。
指定预期的名称和值
要指定预期的名称和值,check cfg 规范提供了 cfg(...)
选项,该选项允许为预期的配置名称及其预期值进行指定。
注意: 使用
--cfg
时不会添加隐式期望。用户需要使用 check cfg 规范传递所有预期的名称和值。
它具有以下基本形式
rustc --check-cfg 'cfg(name, values("value1", "value2", ... "valueN"))'
其中 name
是裸标识符(没有引号),每个 "value"
项都是带引号的字面字符串。name
指定条件的名称,例如 feature
或 my_cfg
。"value"
指定该条件名称的值之一。
当指定 cfg(...)
选项时,rustc
将检查每个1
#[cfg(name = "value")]
属性#[cfg_attr(name = "value")]
属性#[link(name = "a", cfg(name = "value"))]
属性cfg!(name = "value")
宏调用
命令行
--cfg
参数目前未被检查,但将来很可能会被检查。
rustc
将检查指定的 "value"
是否在预期值列表中。如果 "value"
不在列表中,则 rustc
将报告 unexpected_cfgs
lint 诊断。此 lint 的默认诊断级别为 Warn
。
要检查 none 值(即 #[cfg(foo)]
),可以使用 values()
内的 none()
谓词:values(none())
。它可以后跟或前跟任意数量的 "value"
。
要启用值的检查,但提供 none/空预期值集(即期望 #[cfg(name)]
),请使用以下形式
rustc --check-cfg 'cfg(name)'
rustc --check-cfg 'cfg(name, values(none()))'
要启用名称的检查但不检查值,请使用以下形式之一
-
没有预期值(将对
name
的每个值进行 lint 提示)rustc --check-cfg 'cfg(name, values())'
-
未知的预期值(永远不会对
name
的值进行 lint 提示)rustc --check-cfg 'cfg(name, values(any()))'
要避免重复相同的值集,请使用以下形式
rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
要在不指定任何名称或值的情况下启用检查,请使用以下形式
rustc --check-cfg 'cfg()'
--check-cfg cfg(...)
选项可以重复使用,既可以用于相同的条件名称,也可以用于不同的名称。如果对相同的条件名称重复使用,则该条件的值集将合并在一起(优先级给予 values(any())
)。
为了提供
--cfg
参数和--check-cfg
之间的等效性表格,下方 提供了一个表格。
众所周知的名称和值
rustc
维护一个众所周知的名称及其对应值的列表,以避免手动指定它们的需求。
只要存在至少一个 --check-cfg
参数,就会隐式添加众所周知的名称和值。
截至 2025-01-02T
,已知名称列表如下
clippy
debug_assertions
doc
doctest
fmt_debug
miri
overflow_checks
panic
proc_macro
relocation_model
rustfmt
sanitize
sanitizer_cfi_generalize_pointers
sanitizer_cfi_normalize_integers
target_abi
target_arch
target_endian
target_env
target_family
target_feature
target_has_atomic
target_has_atomic_equal_alignment
target_has_atomic_load_store
target_os
target_pointer_width
target_thread_local
target_vendor
ub_checks
unix
windows
从 1.85.0 版本开始,
test
cfg 被认为是“用户空间”配置,尽管它也由rustc
设置,并且应该由构建系统自身管理。
与 values(any())
类似,可以通过传递 cfg(any())
作为 --check-cfg
的参数来禁用众所周知的名称检查。
与 --cfg
的等效性表格
此表格描述了 --cfg
参数与 --check-cfg
参数之间的等效性。
--cfg | --check-cfg |
---|---|
nothing | nothing 或 --check-cfg=cfg() (启用检查) |
--cfg foo | --check-cfg=cfg(foo) 或 --check-cfg=cfg(foo, values(none())) |
--cfg foo="" | --check-cfg=cfg(foo, values("")) |
--cfg foo="bar" | --check-cfg=cfg(foo, values("bar")) |
--cfg foo="1" --cfg foo="2" | --check-cfg=cfg(foo, values("1", "2")) |
--cfg foo="1" --cfg bar="2" | --check-cfg=cfg(foo, values("1")) --check-cfg=cfg(bar, values("2")) |
--cfg foo --cfg foo="bar" | --check-cfg=cfg(foo, values(none(), "bar")) |
示例
示例:类似 Cargo 的 feature
示例
考虑以下命令行
rustc --check-cfg 'cfg(feature, values("lion", "zebra"))' \
--cfg 'feature="lion"' example.rs
此命令行表明此 crate 有两个 feature:
lion
和zebra
。lion
feature 已启用,而zebra
feature 已禁用。
#[cfg(feature = "lion")] // This condition is expected, as "lion" is an
// expected value of `feature`
fn tame_lion(lion: Lion) {}
#[cfg(feature = "zebra")] // This condition is expected, as "zebra" is an expected
// value of `feature` but the condition will evaluate
// to false since only --cfg feature="lion" was passed
fn ride_zebra(z: Zebra) {}
#[cfg(feature = "platypus")] // This condition is UNEXPECTED, as "platypus" is NOT
// an expected value of `feature` and will cause a
// the compiler to emit the `unexpected_cfgs` lint
fn poke_platypus() {}
#[cfg(feechure = "lion")] // This condition is UNEXPECTED, as 'feechure' is NOT
// a expected condition name, no `cfg(feechure, ...)`
// was passed in `--check-cfg`
fn tame_lion() {}
#[cfg(windows = "unix")] // This condition is UNEXPECTED, as the well known
// 'windows' cfg doesn't expect any values
fn tame_windows() {}
示例:多个名称和值
rustc --check-cfg 'cfg(is_embedded, has_feathers)' \
--check-cfg 'cfg(feature, values("zapping", "lasers"))' \
--cfg has_feathers --cfg 'feature="zapping"'
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was
// provided in --check-cfg and doesn't take any value
fn do_embedded() {}
#[cfg(has_feathers)] // This condition is expected, as 'has_feathers' was
// provided in --check-cfg and doesn't take any value
fn do_features() {}
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz'
// was NEVER provided in any --check-cfg arguments
fn do_mumble_frotz() {}
#[cfg(feature = "lasers")] // This condition is expected, as "lasers" is an
// expected value of `feature`
fn shoot_lasers() {}
#[cfg(feature = "monkeys")] // This condition is UNEXPECTED, as "monkeys" is NOT
// an expected value of `feature`
fn write_shakespeare() {}
示例:没有值的条件名称
rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \
--cfg has_feathers
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was
// provided in --check-cfg as condition name
fn do_embedded() {}
#[cfg(has_feathers)] // This condition is expected, as "has_feathers" was
// provided in --check-cfg as condition name
fn do_features() {}
#[cfg(has_feathers = "zapping")] // This condition is expected, as "has_feathers"
// was provided and because *any* values is
// expected for 'has_feathers' no
// warning is emitted for the value "zapping"
fn do_zapping() {}
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz'
// was not provided in any --check-cfg arguments
fn do_mumble_frotz() {}