Rust: 新手看的 内置 cfg 速查表

732 阅读4分钟

读完这篇,你应该能:

  • 知道 什么叫 cfg,它和 feature 有何区别;
  • 会用 rustc --print cfg 找到自己目标平台的 “开关”;
  • 大概记住 什么时候 才需要写 #[cfg(...)]——其余时候就让编译器自动干活。

cfg 是什么?为什么要管它?

cfg = configuration,

Rust 的 条件编译 机制。

编译期根据真假裁剪代码 / 依赖,而 不会 增加运行时代码路径。

语法入口:

  • #[cfg(name)] / #[cfg(name = "value")]
  • cfg!(name)(编译时求值,返回 bool)
  • Cargo 专用:[target.'cfg(...)'.dependencies]

怎么查看自己有哪些内置 cfg?

rustc --print cfg                              # 当前主机
rustc --print cfg --target x86_64-unknown-linux-musl   # 指定目标

全部内置 cfg——按“你可能关心的顺序”分 6 类

类别代表 cfg说明 / 典型用途
A. 构建模式 & panicdebug_assertions test panic="unwind" / "abort"开 debug 断言?写单元测试?想把 panic 改为 crash?
B. 平台家族unix windows target_family="unix"一行判断 “有没有 fork()” 或 “路径分隔符是 \ 还是 /”
C. 具体 OS / 发行商 / 环境target_os="linux" target_vendor="apple"区分 Linux-glibc / Linux-musl / macOS / Android…
D. CPU 架构 & 数据布局target_arch="x86_64" target_pointer_width="64" target_endian="little"写裸机 / FFI / 内存映射时决定字节序、指针大小
E. CPU 指令特性target_feature="sse2" target_feature="neon" …写 SIMD、加速 AES/SHA、Run-time feature detection
F. 原子指令支持target_has_atomic="64" "128" "ptr"在 no-std/嵌入式里判断能否安全使用 AtomicU64/128

想看自己电脑的真实列表?直接跑 rustc --print cfg,结果大概就和你贴的一样。

A. 构建模式 & panic

cfg何时为真用来干啥
debug_assertionscargo build(debug profile保留开销较大的检测:debug_assert!() / 额外日志
testcargo 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"(夜版)WebAssemblyno-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,决定调用约定 & 浮点规则
#[cfg(all(target_os = "linux", target_env = "musl"))]
static LIBC_PATH: &str = "/lib/ld-musl-x86_64.so.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… 示例

#[cfg(target_feature = "neon")]
pub fn mul_matrix_neon(a: &[f32], b: &[f32]) { … }

#[cfg(not(target_feature = "neon"))]
pub fn mul_matrix_scalar(a: &[f32], b: &[f32]) { … }

F. 原子指令宽度

cfg 值意义
target_has_atomic="8" / "16" / "32" / "64" / "128"CPU 原生支持该位宽的 Atomic*
target_has_atomic="ptr"保障 AtomicUsize 可用

嵌入式裸机经常碰到 没有 64-bit 原子 的情况:

#[cfg(target_has_atomic = "64")]
static CNT: AtomicU64 = AtomicU64::new(0);

#[cfg(not(target_has_atomic = "64"))]
static CNT: core::cell::Cell<u64> = Cell::new(0); // 退化实现

写法小抄

3.1 代码里裁剪

#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;

#[cfg(windows)]
use std::os::windows::fs::MetadataExt;

3.2 Cargo 里裁剪依赖

[target.'cfg(target_os = "linux")'.dependencies]
nix = "0.27"

[target.'cfg(target_arch = "aarch64")'.dependencies]
faster-aarch64 = "2"

3.3 批量宏(自定义)

macro_rules! cfg_unix {
    ($($item:item)*) => {
        $(
            #[cfg(unix)]
            $item
        )*
    }
}

cfg_unix! {
    pub fn only_unix() { /* … */ }
}

我到底什么时候才需要手写 cfg?

  • 跨平台库:同一份源码想在 Windows、Linux、WASM 都编过。
  • 性能极限:在支持 AVX2 的机器上走 SIMD,不支持就退纯标量。
  • no-std / bare-metal:32-bit MCU 没有 64-bit 原子,必须降级实现。
  • 区分 debug / release:调试版打开额外检查。
  • 挑 libc:Docker alpine (musl) 静态链接 vs. 普通 glibc。
  • 如果你的项目只在 单一 平台运行(比如 WebAssembly + wasm-bindgen),理论上可以一行 cfg 都不写——Rust 会按默认三元组把代码全部编进来。

参考命令 & 资料

rustc --print cfg                           # 当前 cfg 列表
rustc --print target-spec-json --target …   # 夜ly可用,查看详细 target
RUSTFLAGS='-C target-feature=?' rustc -      # 查看可选特性
Rust Reference – Conditional Compilation
Cargo Book – Target-specific Dependencies
The Rustonomicon – Unstable Features & target_feature

结语 cfg 像一把“手术刀”: 用它,可以把同一套代码精准切割给不同平台;不用时,也不会带来任何运行时成本。 只要记得这 6 大类常用 cfg,遇到跨平台场景再回来查表就足够了。Pomelo_刘金 ,转载请注明出处,感谢! Happy hacking!