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 求解器来解析依赖:

  1. 收集所有依赖需求
  2. 找到满足所有约束的版本组合
  3. 选择每个依赖的最高兼容版本

查看依赖树 #

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