条件编译
语法
配置断言 :
配置选项
| 配置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); }