Rust的#[cfg()]属性是一个强大的功能,它允许开发人员在编译时根据指定的条件有条件地编译代码。它支持在编译过程中对代码进行细粒度控制,从而产生更高效和优化的程序。
条件
Rust提供了几个内置选项,可以与#[cfg()]一起使用,以定义哪些条件可以允许将代码包含在构建中。
目标操作系统
#[cfg(target_os = "android")]
fn connect_to_instant_apps() {
// ...
}
目标架构
#[cfg(target_arch = "x86_64")]
fn target_system_config() -> Option<SystemConfig> {
// ...
}
功能标志
#[cfg(feature = "server")]
fn render(nodes: Vec<Node>) -> impl View {
// ...
}
调试模式
#[cfg(debug_assertions)]
fn debug_payload(payload: &Payload) {
// Code runs only in debug mode
}
#[cfg(test)]
fn save(&self) {
// Don't persist since this isn't production code
}
组合
#[cfg()]具有使用各种组合处理复杂条件的能力,同时仍然保持可读。
All
// 仅在为32位体系结构的类unix操作系统时编译
#[cfg(all(unix, target_pointer_width = "32"))]
fn on_32bit_unix() {
// ...
}
Any
// 这将在针对Android或iOS时编译
#[cfg(any(target_os = "android", target_os = "ios"))]
fn on_mobile() {
// ...
}
Not
// 当不是Android或iOS时将编译
#[cfg(not(any(target_os = "android", target_os = "ios")))]
fn not_on_mobile() {
// ...
}
表达式
// 确定Windows的缓存目录
#[cfg(target_os = "windows")]
const fn default_cache_dir() -> &'static str {
"C:/cache"
}
// 确定Linux的缓存目录
#[cfg(target_os = "linux")]
const fn default_cache_dir() -> &'static str {
"/mnt/c/cache"
}
generate_cache_items_from(default_cache_dir());
Rust确保任何未使用的变量或不支持的函数调用都被检测和适当处理。例如,如果一个函数只在Linux目标上运行时可用,那么调用该函数也必须被标记为条件以匹配。但是如果有处理其他目标的函数,那么在编译时将知道调用哪个函数。
#[cfg(any(target_os = "windows", target_os = "linux"))]
generate_cache_items_from(default_cache_dir());
#[cfg(target_os = "macos")]
println!("Caching is not supported on MacOS");
此属性不限于特定的代码构造。它可以应用于语句、函数、块、导入语句等。这种多功能性允许开发人员根据他们的特定需求,在不同粒度级别上选择性地包含或排除代码。
Modules
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn insert_and_get() {
// ...
}
}
代码块
#[cfg(not(vendor_testing))]
{
trace!("Starting payment processing");
if let Ok(details) = process_payment(&transaction) {
db.store(&details);
}
trace!("Ending payment processing");
}
#[cfg(vendor_testing)]
{
debug!("Starting mock payment processing");
if let Ok(details) = mock_process_payment(&transaction) {
debug!("Payment details", &details);
}
debug!("Ending mock payment processing");
}
#[non_exhaustive]
pub enum Tab {
Dashboard,
Settings,
#[cfg(feature = "admin")]
Admin,
}
向量中的元素
impl Tab {
pub fn all() -> Vec<Self> {
vec![
Self::Dashboard,
Self::Settings,
#[cfg(feature = "admin")]
Self::Admin,
]
}
}
结构体
#[cfg(debug_assertions)]
#[derive(Default)]
pub struct DevBuildState {
dev_id: Mutex<Option<String>>,
}
导入语句
#[cfg(debug_assertions)]
use crate::state::DevBuildState;
Cargo
[target."cfg(not(target_os = "macos"))".dependencies]
some-crate = "0.53.1"
[target."cfg(target_os = "macos")".dependencies]
some-crate-macos-patch = { git = "https://github.com/some-org/some-crate", branch = "macos-patch" }
相关特性
宏操作
除了#[cfg()]属性,Rust还提供了一个名为cfg!()的宏版本。该宏可用于根据编译时条件执行内联if语句。
window.set_title(if cfg!(feature = "admin") && user.is_admin {
"Admin User Settings"
} else {
"User Settings"
});
属性扩展
#[cfg_attr(feature = "magic", sparkles, crackles)]
fn bewitched() {}
// 当启用' magic '特性标志时,上述内容将扩展为
#[sparkles]
#[crackles]
fn bewitched() {}
习惯用法
rustc --cfg "foobar" main.rs
println!("cargo:rustc-cfg=foobar");
#[cfg(foobar)]
总结