rust cfg
Rust中的cfg是条件编译(Configuration)的缩写,用于根据不同编译条件选择性地包含或排除代码。
基本用法
使用#[cfg(name)]属性标记代码块,其中name为条件编译表达式。例如:
#[cfg(target_os = “linux”)]:仅在Linux系统编译时包含该代码块
#[cfg(not(target_os = “windows”))]:在非Windows系统编译时包含该代码块
常用预定义属性操作系统:target_os(如”linux”、”windows”)
架构:target_arch(如”x86_64”)
环境:target_env(如”gnu”(Linux)或”msvc”(Windows))
特性:feature(需在Cargo.toml中定义并启用)
查看所有内置cfg通过命令rustc –print cfg查看当前平台支持的配置选项,指定目标平台可用–target参数(如rustc –print cfg –target x86_64-unknown-linux-musl)。
测试相关用法
使用#[cfg(test)]标记测试代码,仅在Cargo测试时编译。例如:
1 |
|
测试代码需放在tests目录下,并通过cargo test –test test_example.rs运行。
查看自己有哪些内置 cfg?
1 | rustc --print cfg # 当前主机 |
全部内置 cfg
类别 | 说明 / 典型用途 | 代表 cfg |
---|---|---|
A. 构建模式 & panic | 开 debug 断言?写单元测试?想把 panic 改为 crash? | debug_assertions test panic=”unwind” / “abort” |
B. 平台家族 | 一行判断 “有没有 fork()” 或 “路径分隔符是 \ 还是 /” | unix windows target_family=”unix” |
C. 具体 OS / 发行商 / 环境 | 区分 Linux-glibc / Linux-musl / macOS / Android… | target_os=”linux” target_vendor=”apple” |
D. CPU 架构 & 数据布局 | 写裸机 / FFI / 内存映射时决定字节序、指针大小 | target_arch=”x86_64” target_pointer_width=”64” target_endian=”little” |
E. CPU 指令特性 | 写 SIMD、加速 AES/SHA、Run-time feature detection | target_feature=”sse2” target_feature=”neon” … |
F. 原子指令支持 | 在 no-std/嵌入式里判断能否安全使用 AtomicU64/128 | target_has_atomic=”64” “128” “ptr” |
想看自己电脑的真实列表?直接跑 rustc –print cfg,结果大概就和你贴的一样。
A. 构建模式 & panic
cfg | 何时为真 | 用来干啥 |
---|---|---|
debug_assertions | cargo build(debug profile | 保留开销较大的检测:debug_assert!() / 额外日志 |
test | cargo test 时 | 在测试代码里启用内部 helper |
panic=”unwind” vs “abort” | 由 panic = “…” (Cargo.toml [profile]) 决定 | 依赖栈展开的接口(catch_unwind、C++ FFI) |
B. 平台家族 (最粗粒度)
cfg | 平台 | 常见 if 分支 |
---|---|---|
unix / target_family=”unix” | Linux, macOS, *BSD, Android, iOS… | 使用 libc、std::os::unix::fs::PermissionsExt |
windows / target_family=”windows” | Windows | 路径分隔 \、WinAPI FFI |
wasm / target_family=”wasm”(夜版) | WebAssembly | no-std + wasm-bindgen |
C. OS / vendor / env / abi
cfg | 例子 | 什么时候才需要 |
---|---|---|
target_os | “linux”、”macos”、”android”… | 系统调用号、socket 特性、文件权限 |
target_vendor | “apple” “pc” “unknown” | 很少单独用;偶尔区分 Apple vs. PC BSD |
target_env | “gnu” “musl” “msvc” | 选 glibc / musl / MSVC CRT,或链接方式不同 |
target_abi | “eabi” “gnueabihf” | 裸机 ARM,决定调用约定 & 浮点规则 |
1 |
|
D. CPU 架构 & 数据布局
cfg | 例子 | 何用 |
---|---|---|
target_arch | “x86_64” “aarch64” “riscv64” | 包含对应 core::arch::* 模块 |
target_pointer_width | “32” “64” | 数据结构 on-disk 格式是否需要固定 64-bit |
target_endian | “little” “big” | 网络协议、读写 mmap 文件 |
target_cpu(nightly) | native / znver4 | 生成汇编时推断微架构 |
E. CPU 指令特性 (target_feature)
这些是 “默认就启用” 的特性;若想手动开关,可用 RUSTFLAGS=’-C target-feature=+aes,+neon’ cargo build
常见 ARM (aarch64):
- neon – SIMD 基础
- aes / sha2 / sha3 – 专用加密指令
- lse – 更强的原子读改写
- fp16 – 半精度浮点
- rdm – carry-less multiply 常见 x86_64:
- sse2, avx, avx2, aes, pclmulqdq, sha, bmi2… 示例
1 |
|
F. 原子指令宽度
cfg 值 | 意义 |
---|---|
target_has_atomic=”8” / “16” / “32” / “64” / “128” | CPU 原生支持该位宽的 Atomic* |
target_has_atomic=”ptr” | 保障 AtomicUsize 可用 |
嵌入式裸机经常碰到 没有 64-bit 原子 的情况:
1 |
|
写法小抄
3.1 代码里裁剪
1 |
|
3.2 Cargo 里裁剪依赖
1 | [target.'cfg(target_os = "linux")'.dependencies] |
3.3 批量宏(自定义)
1 | macro_rules! cfg_unix { |