条件编译
Syntax
ConfigurationPredicate →
ConfigurationOption
| ConfigurationAll
| ConfigurationAny
| ConfigurationNot
| true
| false
ConfigurationOption →
IDENTIFIER ( = ( STRING_LITERAL | RAW_STRING_LITERAL ) )?
ConfigurationAll →
all ( ConfigurationPredicateList? )
ConfigurationAny →
any ( ConfigurationPredicateList? )
ConfigurationNot →
not ( ConfigurationPredicate )
ConfigurationPredicateList →
ConfigurationPredicate ( , ConfigurationPredicate )* ,?
条件编译的源代码是仅在某些条件下编译的源代码。
源代码可以使用 cfg 和 cfg_attr 以及内置的 cfg! 和 cfg_select! 宏进行条件编译。
是否编译可以取决于编译的 crate 的目标架构、传递给编译器的任意值以及下面进一步描述的其他内容。
每种形式的条件编译都接受一个_配置谓词_,该谓词求值为 true 或 false。谓词是以下之一:
- 配置选项。如果选项已设置,则谓词为 true;如果未设置,则为 false。
all()带有逗号分隔的配置谓词列表。如果所有给定谓词都为 true,或列表为空,则为 true。
any()带有逗号分隔的配置谓词列表。如果至少一个给定谓词为 true,则为 true。如果没有谓词,则为 false。
not()带有配置谓词。如果其谓词为 false,则为 true;如果其谓词为 true,则为 false。
true或false字面量,分别始终为 true 或 false。
_配置选项_是名称或键值对,可以是已设置或未设置。
名称写为单个标识符,例如 unix。
键值对写为标识符、=,然后是字符串,例如 target_arch = "x86_64"。
Note
=周围的空白被忽略,因此foo="bar"和foo = "bar"是等效的。
键不需要是唯一的。例如,feature = "std" 和 feature = "serde" 可以同时设置。
已设置的配置选项
哪些配置选项已设置是在 crate 编译期间静态确定的。
某些选项是基于编译数据的_编译器设置_。
其他选项是基于传递给编译器的代码外部输入的_任意设置_。
无法从正在编译的 crate 的源代码内部设置配置选项。
Note
对于
rustc,任意设置的配置选项使用--cfg标志设置。指定目标的配置值可以通过rustc --print cfg --target $TARGET显示。
Note
键为
feature的配置选项是 Cargo 用于指定编译时选项和可选依赖项的约定。
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"和"wasm"
unix 和 windows
如果设置了 target_family = "unix",则设置 unix。
如果设置了 target_family = "windows",则设置 windows。
target_env
键值选项,设置有关目标平台的进一步消歧信息,包括 ABI 或使用的 libc 信息。由于历史原因,此值仅在实际需要消歧时定义为非空字符串。因此,例如,在许多 GNU 平台上,此值将为空。该值类似于平台目标三元组的第四个元素。一个区别是嵌入式 ABI(如 gnueabihf)将简单地将 target_env 定义为 "gnu"。
示例值:
"""gnu""msvc""musl""sgx""sim""macabi"
target_abi
键值选项,设置有关目标 ABI 的信息以进一步消歧目标。
由于历史原因,此值仅在实际需要消歧时定义为非空字符串。因此,例如,在许多 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"
target_has_atomic_primitive_alignment
键值选项,为[原子]atomic类型与相应整数类型具有相同对齐的每个位宽设置。
Note
对于给定的位宽,对齐通常相同。然而,在某些目标(如 32 位 x86)上,64 位原子类型(如
AtomicI64)的对齐为 8 字节,而i64仅对齐到 4 字节。在这种情况下,不设置target_has_atomic_primitive_alignment = "64"。
可能的值:
"8""16""32""64""128""ptr"
test
编译测试工具时启用。使用 rustc 时通过 --test 标志完成。有关测试支持的更多信息,请参阅测试。
debug_assertions
在没有优化编译时默认启用。这可用于在开发中启用额外的调试代码,但在生产中不启用。例如,它控制标准库的 debug_assert! 宏的行为。
proc_macro
当正在编译的 crate 使用 proc_macrocrate 类型编译时设置。
panic
键值选项,根据 panic 策略设置。请注意,将来可能会添加更多值。
示例值:
"abort""unwind"
条件编译的形式
cfg 属性
*cfg [属性]*根据配置谓词有条件地包含附加到的形式。
Example
#![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 属性的语法是:
Syntax
CfgAttribute → cfg ( ConfigurationPredicate )
cfg 属性可以在允许属性的任何地方使用。
cfg 属性可以在一个形式上使用任意次数。如果任何 cfg 谓词为 false,则附加属性的形式将不被包含,但 cfg.attr.crate-level-attrs 中描述的除外。
如果谓词为 true,则该形式被重写为不带 cfg 属性。如果任何谓词为 false,则该形式从源代码中移除。
当 crate 级别的 cfg 具有 false 谓词时,crate 本身仍然存在。cfg 之前的任何 crate 属性被保留,cfg 之后的任何 crate 属性以及所有以下 crate 内容被移除。
Example
不移除前面属性的行为允许您执行诸如包含
#![no_std]以避免链接std的操作,即使#![cfg(...)]已经以其他方式移除了 crate 的内容。例如:// This `no_std` attribute is kept even though the crate-level `cfg` // attribute is false. #![no_std] #![cfg(false)] // This function is not included. pub fn example() {}
cfg_attr 属性
*cfg_attr [属性]*根据配置谓词有条件地包含属性。
Example
以下模块将根据目标在
linux.rs或windows.rs中找到。#[cfg_attr(target_os = "linux", path = "linux.rs")] #[cfg_attr(windows, path = "windows.rs")] mod os;
cfg_attr 属性的语法是:
Syntax
CfgAttrAttribute → cfg_attr ( ConfigurationPredicate , CfgAttrs? )
cfg_attr 属性可以在允许属性的任何地方使用。
cfg_attr 属性可以在一个形式上使用任意次数。
crate_type 和 crate_name 属性不能与 cfg_attr 一起使用。
当配置谓词为 true 时,cfg_attr 展开为谓词之后列出的属性。
可以列出零个、一个或多个属性。多个属性将各自展开为单独的属性。
Example
#[cfg_attr(feature = "magic", sparkles, crackles)] fn bewitched() {} // When the `magic` feature flag is enabled, the above will expand to: #[sparkles] #[crackles] fn bewitched() {}
Note
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 宏
内置的 cfg 宏接受单个配置谓词,当谓词为 true 时求值为 true 字面量,当为 false 时求值为 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);
}
cfg_select 宏
内置的 cfg_select! 宏可用于在编译时根据多个配置谓词选择代码。
Example
#![allow(unused)] fn main() { cfg_select! { unix => { fn foo() { /* unix specific functionality */ } } target_pointer_width = "32" => { fn foo() { /* non-unix, 32-bit functionality */ } } _ => { fn foo() { /* fallback implementation */ } } } let is_unix_str = cfg_select! { unix => "unix", _ => "not unix", }; }
Syntax
CfgSelect → CfgSelectArms?
CfgSelectArms →
CfgSelectConfigurationPredicate =>
(
{ ^ TokenTree } ,? CfgSelectArms?
| ExpressionWithBlockNoAttrs ,? CfgSelectArms?
| ExpressionWithoutBlockNoAttrs ( , CfgSelectArms? )?
)
CfgSelectConfigurationPredicate →
ConfigurationPredicate | _
cfg_select 展开为第一个配置谓词求值为 true 的分支的有效负载。
如果整个有效负载用花括号括起来,则在展开期间移除花括号。
配置谓词 _ 始终求值为 true。
如果没有谓词求值为 true,则是编译错误。
每个右侧必须是宏调用位置的语法有效展开。