bigywater.tech
Rust · 153

Feature Flag 条件编译

Cargo feature 是条件编译和可选依赖的基础,却有一个出名的坑:feature 统一。这篇用自己写的小库逐个验证 default、可选依赖、转发,以及两个依赖启用不同 feature 时到底发生什么、互斥 feature 为什么不行。

并集
left 与 right 各启用一个 feature 时,fmtx 实际启用的 feature 集合
1 份
fmtx 被编译的次数(feature 统一)
compile_error
互斥 feature 被统一后同时启用时的结果

feature 与可选依赖

实测 · 本机执行输出
  default-features = false(不启用任何)          → fmtx 编译时启用的 feature:[];int(42) = 42
  --features use-std                       → fmtx 编译时启用的 feature:["std-fmt"];int(42) = 42
  --features use-fast                      → fmtx 编译时启用的 feature:["fast"];int(42) = 42
  --features use-fast,use-extra            → fmtx 编译时启用的 feature:["fast", "extra"];int(42) = 42 | extra 功能存在

依赖版本的解析见Cargo.toml 依赖解析;条件编译的 cfg 更多用法见跨平台路径差异。

可选依赖出现在哪

实测 · 本机执行输出
  app v0.1.0 (<实验目录>/proj/u153/app)
  └── fmtx v0.1.0 (<实验目录>/proj/u153/fmtx)
      └── itoa feature "default"
          └── itoa v1.0.18

feature 统一

实测 · 本机执行输出
  app 自己没有启用任何 feature,但 fmtx 实际启用了:["fast", "extra"]
  left 用到 fast:1;right 用到 extra:extra 功能存在
  cargo tree -e features -i fmtx:
    fmtx v0.1.0 (<实验目录>/proj/u153/fmtx)
    └── both v0.1.0 (<实验目录>/proj/u153/both)
        └── both feature "default" (command-line)
    ├── fmtx feature "extra"
    │   └── right v0.1.0 (<实验目录>/proj/u153/right)
    │       └── right feature "default"
    │           └── both v0.1.0 (<实验目录>/proj/u153/both) (*)
    └── fmtx feature "fast"
        └── left v0.1.0 (<实验目录>/proj/u153/left)
            └── left feature "default"
                └── both v0.1.0 (<实验目录>/proj/u153/both) (*)

resolver = "2" 对 build-dependencies 与 dev-dependencies 的 feature 分开统一,本文没有验证。

互斥 feature

实测 · 本机执行输出
  两个依赖各启用一个互斥 feature,统一后同时启用:
    error: backend-a 与 backend-b 不能同时启用
    1 | #[cfg(all(feature = "backend-a", feature = "backend-b"))] compile_error!("backend-a 与 backend-b 不能同时启用");
    error: could not compile `excl` (lib) due to 1 previous error

关掉默认 feature

实测 · 本机执行输出
  cargo tree --no-default-features(fmtx): ['    Updating crates.io index', '     Locking 1 package to latest Rust 1.98.1 compatible version', 'fmtx v0.1.0 (<实验目录>/proj/u153/fmtx)']
  cargo tree --features fast(fmtx): ['fmtx v0.1.0 (<实验目录>/proj/u153/fmtx)', '└── itoa v1.0.18']

工作区里统一管理见Workspace 依赖管理。

分步演示

Feature Flag
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / rustc 1.98.1(brew)/ cargo 1.98.1;单个文件用 rustc 直接编译,需要依赖时用 cargo(经代理从 crates.io 下载);计时用 std::time::Instant,数字每次运行会有小幅抖动。库与应用是本地 path crate,itoa 来自 crates.io
    • 没有验证:resolver 1 与 2 的差别、dev-dependencies 对 feature 统一的影响、--all-features 的行为、feature 对编译时间与二进制体积的影响、cargo-hack 对 feature 组合的测试
    京ICP备2026067502号-1京公网安备11010502063487号