Cargo 依赖管理 #
依赖管理概述 #
Cargo 提供了强大而灵活的依赖管理系统,支持多种依赖来源、版本约束和特性配置。本节将详细介绍如何有效管理项目依赖。
依赖类型 #
依赖分类 #
text
依赖类型
├── [dependencies] # 运行时依赖
├── [dev-dependencies] # 开发依赖(测试、示例)
└── [build-dependencies] # 构建依赖(构建脚本)
运行时依赖 #
项目运行所需的依赖:
toml
[dependencies]
serde = "1.0"
tokio = "1.0"
开发依赖 #
仅在开发、测试、示例中使用:
toml
[dev-dependencies]
tokio = { version = "1.0", features = ["full"] }
tempfile = "3.0"
criterion = "0.5"
pretty_assertions = "1.0"
构建依赖 #
仅在构建脚本中使用:
toml
[build-dependencies]
cc = "1.0"
bindgen = "0.69"
prost-build = "0.12"
版本指定 #
语义化版本 #
Cargo 使用语义化版本(SemVer)来管理依赖版本。
text
版本格式:MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD]
示例:
1.0.0
2.1.3
1.0.0-alpha.1
1.0.0+build.123
版本约束语法 #
插入符约束(^) #
默认约束,允许兼容更新:
toml
[dependencies]
serde = "1.0" # 等同于 ^1.0.0,允许 1.x.x
serde = "^1.0" # 同上
serde = "0.1" # 允许 0.1.x
serde = "0.0.1" # 允许 0.0.1(精确)
规则:
^1.2.3→>=1.2.3, <2.0.0^0.2.3→>=0.2.3, <0.3.0^0.0.3→>=0.0.3, <0.0.4
波浪号约束(~) #
允许补丁级别更新:
toml
[dependencies]
serde = "~1.0" # 允许 1.0.x
serde = "~1.0.0" # 允许 1.0.x
serde = "~1.2.3" # 允许 1.2.x(>=1.2.3, <1.3.0)
比较运算符 #
toml
[dependencies]
serde = ">=1.0.0" # 大于等于
serde = "<2.0.0" # 小于
serde = ">1.0.0" # 大于
serde = "<=2.0.0" # 小于等于
serde = "=1.0.193" # 精确版本
范围约束 #
toml
[dependencies]
serde = ">=1.0.0, <2.0.0" # 1.x.x
serde = ">=1.0.0, <=1.5.0" # 1.0.0 到 1.5.0
通配符 #
toml
[dependencies]
serde = "*" # 任意版本(不推荐)
serde = "1.*" # 1.x.x
serde = "1.0.*" # 1.0.x
版本约束最佳实践 #
toml
[dependencies]
# 推荐:使用插入符约束
serde = "1.0"
# 推荐:库项目使用较宽松的约束
tokio = "1"
# 推荐:应用项目可以使用精确版本
my-critical-dep = "=1.0.193"
# 不推荐:使用通配符
# some-dep = "*"
依赖来源 #
crates.io #
默认来源,官方包仓库:
toml
[dependencies]
serde = "1.0"
tokio = { version = "1.0", features = ["full"] }
Git 仓库 #
从 Git 仓库获取依赖:
toml
[dependencies]
# 基本用法
my_lib = { git = "https://github.com/user/my_lib.git" }
# 指定分支
my_lib = { git = "https://github.com/user/my_lib.git", branch = "main" }
my_lib = { git = "https://github.com/user/my_lib.git", branch = "develop" }
# 指定标签
my_lib = { git = "https://github.com/user/my_lib.git", tag = "v1.0.0" }
# 指定提交
my_lib = { git = "https://github.com/user/my_lib.git", rev = "abc123def456" }
# 指定目录(monorepo)
my_lib = { git = "https://github.com/user/monorepo.git", branch = "main", subdirectory = "crates/my_lib" }
本地路径 #
使用本地路径的依赖:
toml
[dependencies]
my_lib = { path = "../my_lib" }
my_lib = { path = "/absolute/path/to/my_lib" }
my_lib = { path = "../my_lib", version = "0.1.0" }
其他注册表 #
使用私有或第三方注册表:
toml
# 首先定义注册表
[registries]
my-registry = { index = "https://my-registry.com/index" }
# 然后使用
[dependencies]
my_private_lib = { version = "1.0", registry = "my-registry" }
多来源组合 #
toml
[dependencies]
# 版本 + 特性
serde = { version = "1.0", features = ["derive"] }
# Git + 特性
my_lib = { git = "https://github.com/user/my_lib.git", features = ["feature1"] }
# 路径 + 版本 + 特性
my_lib = { path = "../my_lib", version = "0.1.0", features = ["feature1"] }
特性管理 #
定义特性 #
toml
[features]
default = ["feature1", "feature2"]
feature1 = []
feature2 = ["feature1"]
feature3 = ["dep:optional_dep"]
启用可选依赖 #
toml
[dependencies]
serde = { version = "1.0", optional = true }
serde_json = { version = "1.0", optional = true }
[features]
default = ["serde"]
serde = ["dep:serde"]
json = ["dep:serde_json", "serde"]
full = ["json"]
依赖特性 #
启用依赖的特性:
toml
[features]
# 启用依赖的特性
async = ["tokio/rt", "tokio/net"]
full = ["tokio/full", "serde/derive"]
使用特性 #
bash
# 使用默认特性
cargo build
# 禁用默认特性
cargo build --no-default-features
# 启用特定特性
cargo build --features "feature1,feature2"
# 启用所有特性
cargo build --all-features
特性最佳实践 #
toml
[features]
# 默认特性:大多数用户需要的
default = ["std"]
# 标准库支持
std = []
# 可选依赖
serde = ["dep:serde"]
json = ["dep:serde_json", "serde"]
# 功能分组
async = ["tokio/rt", "tokio/net"]
sync = ["tokio/sync"]
# 完整功能
full = ["std", "serde", "json", "async", "sync"]
平台特定依赖 #
cfg 条件 #
toml
[target.'cfg(windows)'.dependencies]
winapi = "0.3"
[target.'cfg(unix)'.dependencies]
libc = "0.2"
[target.'cfg(target_os = "linux")'.dependencies]
inotify = "0.10"
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9"
[target.'cfg(target_arch = "x86_64")'.dependencies]
x86 = "0.52"
[target.'cfg(target_arch = "aarch64")'.dependencies]
aarch64 = "0.0.7"
目标三元组 #
toml
[target.x86_64-pc-windows-msvc.dependencies]
winapi = "0.3"
[target.x86_64-unknown-linux-gnu.dependencies]
openssl = "0.10"
[target.aarch64-apple-darwin.dependencies]
core-foundation = "0.9"
[target.wasm32-unknown-unknown.dependencies]
web-sys = "0.3"
组合条件 #
toml
[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies]
openssl = "0.10"
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
inotify = "0.10"
[target.'cfg(all(target_arch = "x86_64", target_os = "linux"))'.dependencies]
x86 = "0.52"
常用 cfg 条件 #
| 条件 | 描述 |
|---|---|
windows |
Windows 系统 |
unix |
Unix 系统(Linux、macOS 等) |
linux |
Linux 系统 |
macos |
macOS 系统 |
android |
Android 系统 |
ios |
iOS 系统 |
target_arch = "x86_64" |
64 位 x86 架构 |
target_arch = "aarch64" |
ARM64 架构 |
target_pointer_width = "64" |
64 位指针 |
feature = "xxx" |
特性启用 |
依赖覆盖 #
[patch] 覆盖 #
临时替换依赖:
toml
# 覆盖 crates.io 上的包
[patch.crates-io]
serde = { git = "https://github.com/serde-rs/serde.git" }
serde = { path = "../serde" }
# 覆盖 Git 依赖
[patch."https://github.com/user/my_lib"]
my_lib = { path = "../my_local_lib" }
[replace] 替换(已弃用) #
toml
[replace]
"serde:1.0.193" = { git = "https://github.com/serde-rs/serde.git" }
覆盖注册表 #
toml
[patch.crates-io]
my_lib = { git = "https://github.com/user/my_lib.git" }
[patch.my-registry]
my_private_lib = { path = "../my_private_lib" }
Cargo.lock #
锁定文件作用 #
Cargo.lock 锁定依赖的精确版本,确保构建的可重复性。
toml
# Cargo.lock 示例
[[package]]
name = "serde"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7371c2a0e6d7e6f6d7b5e5b5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7b7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7"
提交策略 #
| 项目类型 | 是否提交 Cargo.lock |
|---|---|
| 应用程序 | ✅ 必须提交 |
| 库项目 | ❌ 不提交(让用户决定) |
| 工作区 | ✅ 提交到根目录 |
更新锁定文件 #
bash
# 更新所有依赖
cargo update
# 更新特定依赖
cargo update -p serde
# 更新到特定版本
cargo update -p serde --precise 1.0.193
依赖解析 #
解析算法 #
Cargo 使用 SAT 求解器来解析依赖:
- 收集所有依赖需求
- 找到满足所有约束的版本组合
- 选择每个依赖的最高兼容版本
查看依赖树 #
bash
# 查看完整依赖树
cargo tree
# 查看重复依赖
cargo tree --duplicates
# 反向依赖
cargo tree -i serde
# 只显示直接依赖
cargo tree --depth 1
# 显示特性
cargo tree --features
解决版本冲突 #
bash
# 查看冲突
cargo tree --duplicates
# 使用 patch 解决
[patch.crates-io]
conflicting-dep = { path = "../fixed_version" }
# 使用精确版本
[dependencies]
conflicting-dep = "=1.0.0"
依赖安全 #
安全审计 #
bash
# 安装审计工具
cargo install cargo-audit
# 运行安全审计
cargo audit
# 检查特定问题
cargo audit --json
检查依赖 #
bash
# 查看过时依赖
cargo install cargo-outdated
cargo outdated
# 查看依赖许可证
cargo install cargo-license
cargo license
# 查看依赖大小
cargo install cargo-bloat
cargo bloat --crates
漏洞处理 #
toml
# 使用 patch 修复漏洞
[patch.crates-io]
vulnerable-crate = { git = "https://github.com/user/fixed-version.git" }
# 或更新到安全版本
[dependencies]
vulnerable-crate = "1.1.0" # 已修复的版本
依赖最佳实践 #
1. 版本约束 #
toml
# ✅ 推荐:使用插入符约束
serde = "1.0"
# ✅ 推荐:关键依赖使用精确版本
critical-dep = "=1.0.0"
# ❌ 不推荐:使用通配符
some-dep = "*"
2. 可选依赖 #
toml
# ✅ 推荐:将大型依赖设为可选
[dependencies]
tokio = { version = "1.0", optional = true }
[features]
async = ["dep:tokio"]
3. 特性分组 #
toml
# ✅ 推荐:按功能分组特性
[features]
default = ["std"]
std = []
async = ["tokio/rt"]
json = ["serde", "serde_json"]
full = ["std", "async", "json"]
4. 平台特定 #
toml
# ✅ 推荐:明确平台条件
[target.'cfg(windows)'.dependencies]
winapi = "0.3"
[target.'cfg(unix)'.dependencies]
libc = "0.2"
5. 开发依赖 #
toml
# ✅ 推荐:测试工具放在 dev-dependencies
[dev-dependencies]
tempfile = "3.0"
pretty_assertions = "1.0"
6. 定期更新 #
bash
# 检查更新
cargo outdated
# 更新依赖
cargo update
# 安全审计
cargo audit
常见问题 #
1. 版本冲突 #
bash
# 错误:version conflict
# 解决:查看依赖树
cargo tree -i conflicting-dep
# 使用 patch 或更新版本
2. 循环依赖 #
bash
# 错误:cyclic dependency
# 解决:重构代码,提取公共部分
3. 依赖过大 #
bash
# 查看依赖大小
cargo bloat --crates
# 移除不必要的依赖
cargo tree --duplicates
4. 编译慢 #
toml
# 减少依赖
[dependencies]
# 只启用需要的特性
tokio = { version = "1.0", default-features = false, features = ["rt"] }
下一步 #
掌握依赖管理后,继续学习 工作区 管理多包项目!
最后更新:2026-03-28