条件编译
语法
配置谓词 :
配置选项
| 配置全部
| 配置任意
| 配置非配置选项 :
标识符 (=
(字符串字面量 | 原始字符串字面量))?配置全部
all
(
配置谓词列表?)
配置任意
any
(
配置谓词列表?)
配置非
not
(
配置谓词)
配置谓词列表
配置谓词 (,
配置谓词)*,
?
条件编译的源代码是指根据特定条件可能被视为源代码一部分,也可能不被视为源代码一部分的代码。可以使用 属性 cfg
和 cfg_attr
以及内置的 cfg
宏 对源代码进行条件编译。这些条件基于编译包的目标架构、传递给编译器的任意值,以及下面将详细描述的其他一些杂项内容。
每种形式的条件编译都采用一个求值为真或假的配置谓词。谓词是以下之一
- 配置选项。如果选项已设置,则为真;如果未设置,则为假。
all()
,带有一个以逗号分隔的配置谓词列表。如果至少有一个谓词为假,则为假。如果没有谓词,则为真。any()
,带有一个以逗号分隔的配置谓词列表。如果至少有一个谓词为真,则为真。如果没有谓词,则为假。not()
,带有一个配置谓词。如果其谓词为假,则为真;如果其谓词为真,则为假。
配置选项是已设置或未设置的名称和键值对。名称写成单个标识符,例如 unix
。键值对写成标识符、=
和字符串。例如,target_arch = "x86_64"
是一个配置选项。
注意:
=
周围的空格将被忽略。foo="bar"
和foo = "bar"
是等效的配置选项。
键在键值配置选项集中不是唯一的。例如,feature = "std"
和 feature = "serde"
可以同时设置。
设置配置选项
哪些配置选项会被设置是在 crate 编译期间静态确定的。某些选项是基于编译数据的*编译器设置*。其他选项是*任意设置*,根据传递给编译器的代码外部输入进行设置。无法从正在编译的 crate 的源代码中设置配置选项。
**注意**:对于
rustc
,任意设置的配置选项使用--cfg
标志进行设置。
**注意**:键为
feature
的配置选项是 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
属性。target_feature
选项还提供了一个额外的功能 crt-static
,用于指示 静态 C 运行时 可用。
target_os
使用目标操作系统设置一次的键值选项。此值类似于平台目标三元组的第二个和第三个元素。
示例值
“windows”
“macos”
“ios”
“linux”
“android”
“freebsd”
“dragonfly”
“openbsd”
“netbsd”
"none"
(通常用于嵌入式目标)
target_family
提供目标更通用描述的键值选项,例如目标通常所属的操作系统或体系结构系列。可以设置任意数量的 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_abi
使用有关目标 ABI 的信息设置的键值选项,用于进一步消除 target_env
的歧义。出于历史原因,仅当实际需要消除歧义时,此值才定义为非空字符串。因此,例如,在许多 GNU 平台上,此值将为空。
示例值
""
“llvm”
“eabihf”
“abi64”
target_endian
根据目标 CPU 的字节序,使用值“little”或“big”设置一次的键值选项。
target_pointer_width
使用目标指针宽度(以位为单位)设置一次的键值选项。
示例值
"16"
"32"
"64"
target_vendor
使用目标供应商设置一次的键值选项。
示例值
“apple”
“fortanix”
“pc”
“unknown”
target_has_atomic
为目标支持原子加载、存储和比较并交换操作的每个位宽设置的键值选项。
如果存在此 cfg,则所有稳定的 core::sync::atomic
API 都可用于相关的原子宽度。
可能的值
"8"
"16"
"32"
"64"
"128"
“ptr”
test
在编译测试工具时启用。使用 rustc
时,可以使用 --test
标志完成。有关测试支持的更多信息,请参阅 测试。
debug_assertions
在没有优化的情况下编译时默认启用。这可用于在开发中启用额外的调试代码,但在生产中不启用。例如,它控制标准库的 debug_assert!
宏的行为。
proc_macro
在使用 proc_macro
crate 类型 编译 crate 时设置。
panic
根据紧急策略设置的键值选项。请注意,将来可能会添加更多值。
示例值
“abort”
“unwind”
条件编译的形式
cfg
属性
语法
CfgAttrAttribute :
cfg
(
ConfigurationPredicate)
cfg
属性 根据配置谓词有条件地包含它所附加的内容。
它的写法是 cfg
、(
、配置谓词,最后是 )
。
如果谓词为真,则将内容重写为不带 cfg
属性。如果谓词为假,则从源代码中删除该内容。
当 crate 级别的 cfg
具有假谓词时,行为略有不同:保留 cfg
之前的任何 crate 属性,并删除 cfg
之后的任何 crate 属性。这允许 #![no_std]
和 #![no_core]
crate 避免链接 std
/core
,即使 #![cfg(...)]
已删除整个 crate。
函数上的一些示例
#![allow(unused)] fn main() { // The function is only included in the build when compiling for macOS #[cfg(target_os = "macos")] fn macos_only() { // ... } // This function is only included when either foo or bar is defined #[cfg(any(foo, bar))] fn needs_foo_or_bar() { // ... } // This function is only included when compiling for a unixish OS with a 32-bit // architecture #[cfg(all(unix, target_pointer_width = "32"))] fn on_32bit_unix() { // ... } // This function is only included when foo is not defined #[cfg(not(foo))] fn needs_not_foo() { // ... } // This function is only included when the panic strategy is set to unwind #[cfg(panic = "unwind")] fn when_unwinding() { // ... } }
允许在允许使用属性的任何地方使用 cfg
属性。
cfg_attr
属性
语法
CfgAttrAttribute :
cfg_attr
(
ConfigurationPredicate,
CfgAttrs?)
当配置谓词为真时,此属性将扩展为谓词之后列出的属性。例如,以下模块将根据目标位于 linux.rs
或 windows.rs
。
#[cfg_attr(target_os = "linux", path = "linux.rs")]
#[cfg_attr(windows, path = "windows.rs")]
mod os;
可以列出零个、一个或多个属性。多个属性将分别扩展为单独的属性。例如
#[cfg_attr(feature = "magic", sparkles, crackles)]
fn bewitched() {}
// When the `magic` feature flag is enabled, the above will expand to:
#[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); }