跳到主要内容

Cargo 深入

问题

Cargo 有哪些进阶用法?

答案

Features(条件编译)

Cargo.toml
[package]
name = "my-lib"

[features]
default = ["json"]
json = ["dep:serde_json"] # 可选依赖
full = ["json", "yaml", "toml"] # 组合 feature
yaml = ["dep:serde_yaml"]
toml = ["dep:toml"]

[dependencies]
serde = "1"
serde_json = { version = "1", optional = true }
serde_yaml = { version = "0.9", optional = true }
toml = { version = "0.8", optional = true }
// 代码中条件编译
#[cfg(feature = "json")]
pub fn parse_json(s: &str) -> serde_json::Value {
serde_json::from_str(s).unwrap()
}

重要的 Cargo.toml 配置

Cargo.toml
[profile.release]
opt-level = 3 # 最高优化
lto = true # 链接时优化
codegen-units = 1 # 单代码生成单元,更慢编译但更优产物
strip = true # 去除调试符号

[profile.dev]
opt-level = 0 # 不优化(快速编译)

[profile.dev.package."*"]
opt-level = 2 # 依赖用优化编译(推荐)

常用命令

命令作用
cargo build --release发布构建
cargo check快速检查(不生成二进制)
cargo clippyLint 检查
cargo fmt格式化
cargo doc --open生成并打开文档
cargo audit安全漏洞检查
cargo tree依赖树
cargo update更新依赖
cargo bloat二进制大小分析

常见面试问题

Q1: cargo checkcargo build 的区别?

答案

cargo check 只做类型检查和借用检查,不生成二进制文件,比 cargo build 快 2-3 倍。日常开发推荐用 cargo check,只在需要运行时才 cargo build

Q2: 如何减小 Rust 二进制文件大小?

答案

[profile.release]
opt-level = "z" # 优化大小
lto = true # LTO
codegen-units = 1
strip = true # 去除符号
panic = "abort" # 不生成 unwind 代码

还可以用 cargo bloat 分析哪些函数占空间最大,用 #[inline(never)] 避免过度内联。

相关链接