条件编译
语法
配置断言 :
配置选项
| 配置All
| 配置Any
| 配置Not配置选项 :
标识符 (=(字符串字面值 | 原始字符串字面值))?配置All
all(配置断言列表?)配置Any
any(配置断言列表?)配置Not
not(配置断言)配置断言列表
配置断言 (,配置断言)*,?
条件编译源码 是指根据某些条件来排除部分源码,或者包含部分源码。
条件编译,使用内置的 cfg cfg_attr 属性 和 cfg 宏 来实现。
条件包括: 编译 crate 时的目标架构、传递给编译器的参数,其他一些可选项。
条件编译会进行 配置断言 ,断言的结果为 true 或 false 。 断言有以下几种形式:
- 配置选项: 如果该选项被设置则为 true ,否则为 false 。
all(): 以逗号分隔的配置断言列表。如果至少有一项断言为 false ,则结果为 false 。如果没有断言,则为 true 。any(): 以逗号分隔的配置断言列表。如果至少有一项断言为 true ,则结果为 true 。如果没有断言,则为 false 。not(): 有一个配置断言。如果其断言为 false ,则为 true ,如果其断言为 true ,则为 false 。
配置选项 是被设置或未设置的名称与键值对。
名称是单个标识符,例如 unix 。
键值对是一个标识符,后跟一个字符串 。
例如, target_arch = "x86_64" 配置选项。
注意: 等号周围的空白将被忽略。
foo="bar"和foo = "bar"是等价的配置选项。
键在键值对配置选项的集合中不是唯一的。例如,可以同时设置 feature = "std" 和 feature = "serde" 。
设置配置选项
哪些配置选项被设置是在编译期确定。 某些配置选项是由编译器的状态来确定,称为编译器设置。 其他选项由用户设置,非源码中,而由外部输入给编译器。 正在编译的 crate 无法通过源码设置配置选项。
注意: 对于
rustc,用户输入的配置选项可以使用--cfg标志设置。
注意: 键为
feature的配置选项通常通过 Cargo 配置清单设置,可参阅 Cargo 文档。
警告:输入的配置选项有可能与编译器的值相同。
例如,在 Windows 平台编译目标时输入 rustc --cfg "unix" program.rs,这将同时设置 unix 和 windows 配置选项。
这不是一个良好的做法。
target_arch
目标 CPU 架构。 该值类似于 '目标平台三元组' 的第一个元素,但并不完全一致。
示例值:
"x86""x86_64""mips""powerpc""powerpc64""arm""aarch64"
target_feature
当前编译目标平台所提供的特性。
示例值:
"avx""avx2""crt-static""rdrand""sse""sse2""sse4.1"
详见 target_feature 属性 。
crt-static 表示可用的 静态 C 运行时库 。
target_os
是编译时目标平台操作系统,仅可设定一次。 该值类似于 '平台目标三元组' 的第二个和第三个元素。
示例值:
"windows""macos""ios""linux""android""freebsd""dragonfly""openbsd""netbsd"
target_family
是目标平台更一般的描述,目标平台所处的操作系统或体系结构。 该键可以设置多个。
示例值:
"unix""windows""wasm"
unix 和 windows
如果设置了 target_family = "unix",则意味着 unix 被设置。
如果设置了 target_family = "windows",则意味着 windows 被设置。
target_env
是目标平台进一步的区分信息,例如有关所使用的 ABI 或 libc 的信息。
由于历史原因,只有在实际需要区分时,此值才会被定义为非空字符串。
因而,比如在许多 GNU 平台上,此值将为空。此值类似于平台目标三元组的第四个元素。
有所不同的是,像 gnueabihf 这样的嵌入式 ABI 将简单地将 target_env 定义为 "gnu"。
示例值:
"""gnu""msvc""musl""sgx"
target_endian
用于描述目标平台的字节序,取值为 "little" 或 "big" ,即 '大端' 或 '小端' ,根据目标机器的 CPU 决定。
target_pointer_width
该值只设置一次,为目标平台的指针宽度 (以位为单位) 。
示例值:
"16""32""64"
target_vendor
该值只设置一次,其键是目标平台的供应商 (vendor) 。
示例值:
"apple""fortanix""pc""unknown"
target_has_atomic
目标平台支持每个比特宽度原子加载、存储和比较交换操作时,将设置该值。
当这个配置项存在时,所有适用于相关原子宽度的稳定的 core::sync::atomic API 可用。
可能值:
"8""16""32""64""128""ptr"
test
该值在执行测试时启用,即 rustc 添加 --test 标志。
可参阅 测试 部分。
debug_assertions
在未开启优化时,默认启用。
这可以用于在开发时包含额外的调试代码,发布时排除。
比如,标准库中 debug_assert! 宏的行为受到该值控制。
proc_macro
当编译的 crate 时,使用 proc_macro crate 类型 而设置。
panic
根据 panic 策略而设置。需注意,将来可能会添加更多可选值。
示例值:
"abort""unwind"
条件编译的形式
cfg 属性
语法
CfgAttr属性 :
cfg(配置断言)
cfg 属性 根据 配置断言 决定是否排除所附着的条目。
语法为 cfg ( 配置断言 ) 。
如果断言为 true,则将重新编写所附条目,移除 cfg 属性。
如果断言为 false,则排除对应条目源码。
一些示例:
#![allow(unused)] fn main() { // 仅为 macOS 平台编译时,包含该函数源码。 #[cfg(target_os = "macos")] fn macos_only() { // ... } // 只有在定义了 foo 或 bar 的时,包含该函数源码 #[cfg(any(foo, bar))] fn needs_foo_or_bar() { // ... } // 只有在 32 位架构的 unixish 操作系统编译时,包含该函数源码。 #[cfg(all(unix, target_pointer_width = "32"))] fn on_32bit_unix() { // ... } // 只有未定义 foo 的情况下,包含该函数源码。 #[cfg(not(foo))] fn needs_not_foo() { // ... } // 仅在恐慌策略被设置为 unwind 时,包含该函数源码。 #[cfg(panic = "unwind")] fn when_unwinding() { // ... } }
cfg 属性可在任何允许属性的位置使用。
cfg_attr 属性
语法
CfgAttr属性 :
cfg_attr(_配置断言,CfgAttr组?)
cfg_attr 属性 可根据条件断言来选择性为所属条目添加其他属性。
当配置断言为真,将展开断言部分后面所列出的属性。
例如,以下模块将基于目标平台在 linux.rs 或 windows.rs 中找到:
#[cfg_attr(target_os = "linux", path = "linux.rs")]
#[cfg_attr(windows, path = "windows.rs")]
mod os;
所列出的属性可以是 0 个、 1 个或多个。多个属性将会分别展开为单独的属性。比如:
#[cfg_attr(feature = "magic", sparkles, crackles)]
fn bewitched() {}
// 当 `magic` 特性标志启用时,上述源码将展开为:
#[sparkles]
#[crackles]
fn bewitched() {}
注意:
cfg_attr可以去展开另一个cfg_attr。 比如,#[cfg_attr(target_os = "linux", cfg_attr(feature = "multithreaded", some_other_attribute))]是有效的。 这个例子等价于#[cfg_attr(all(target_os = "linux", feature ="multithreaded"), some_other_attribute)]。
cfg_attr 属性可在任何允许属性的地方使用。
cfg 宏
内置的 cfg 宏经过配置断言,展开为 true 或 false 的字面值源码。
示例:
#![allow(unused)] fn main() { let machine_kind = if cfg!(unix) { "unix" } else if cfg!(windows) { "windows" } else { "unknown" }; println!("I'm running on a {} machine!", machine_kind); }