Cargo 是 Rust 的官方包管理器和构建工具,集成了依赖管理、项目构建、测试、文档生成、发布等功能。以下从核心功能出发,结合具体示例和底层逻辑,详细说明其用法。
一、Cargo 核心概念
在开始前,先明确几个关键概念:
- Cargo.toml:项目的“清单文件”,定义项目元数据(名称、版本、作者)、依赖、构建脚本(
build.rs
)、特性(features)等。 - Cargo.lock:自动生成的“锁文件”,记录所有依赖的精确版本(包括间接依赖),确保构建的可重复性。
- 工作区(Workspace):用于管理多个关联的 Rust 包(
crate
),共享依赖和构建缓存。 - 包(Package):一个可发布的 Rust 项目,包含
Cargo.toml
和代码(通常在src/
目录下)。 - 目标(Target):可编译的产物,如二进制文件(
src/main.rs
)、库(src/lib.rs
)或自定义构建脚本。
二、基础操作:创建与管理项目
1. 创建新项目
# 创建二进制项目(默认,生成 src/main.rs)
cargo new hello_world
cd hello_world
# 创建库项目(生成 src/lib.rs)
cargo new --lib my_lib
# 查看项目结构
tree
# hello_world/
# ├── Cargo.toml
# └── src/
# └── main.rs
原理:cargo new
会根据模板生成标准项目结构,Cargo.toml
包含初始元数据(如 name
、version
),src/main.rs
是二进制入口(fn main()
是程序起点)。
2. 构建项目
# 调试模式构建(默认,生成未优化的二进制文件,路径:target/debug/hello_world)
cargo build
# 发布模式构建(优化代码,生成路径:target/release/hello_world)
cargo build --release
# 检查代码是否能编译(不生成二进制文件,更快)
cargo check
# 清理构建产物
cargo clean
原理:Cargo 调用 Rust 编译器(rustc
)进行编译,调试模式(debug
)保留调试信息(便于断点调试),发布模式(release
)启用优化(如内联、循环展开)。cargo check
跳过链接阶段,仅验证语法和类型正确性,适合快速迭代。
3. 运行项目
# 直接运行调试模式构建的二进制文件(无需手动 cargo build)
cargo run
# 运行发布模式构建的程序(需先 cargo build --release)
cargo run --release
三、依赖管理:添加与管理第三方库
Cargo 的核心优势之一是自动解析和下载依赖,支持语义化版本(SemVer,如 ^1.2.3
表示兼容 1.2.x 的更新)。
1. 添加依赖
修改 Cargo.toml
的 [dependencies]
部分,添加需要的库。例如,添加 HTTP 客户端 reqwest
和序列化库 serde
:
[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"
[dependencies]
reqwest = { version = "0.11", features = ["json"] } # 启用 json 特性
serde = { version = "1.0", features = ["derive"] } # 启用 derive 特性(用于 #[derive(Serialize, Deserialize)])
说明:
version
:指定依赖的版本范围(0.11
等价于^0.11.0
,即允许 0.11.x 的更新)。features
:启用可选特性(部分库通过特性开关控制功能,如reqwest
的json
特性依赖serde_json
)。- 其他版本语法示例:
=1.2.3
:严格匹配 1.2.3。^1.2
:允许 1.2.x(不包括 2.0.0)。~1.2.3
:允许 1.2.x(不包括 1.3.0)。*
:任意版本(不推荐,可能导致构建不稳定)。
2. 下载依赖
添加依赖后,首次构建时会自动下载:
cargo build # 自动解析并下载 reqwest、serde 及其依赖
原理:Cargo 读取 Cargo.toml
中的依赖描述,查询 https://crates.io/(Rust 官方包仓库)获取最新兼容版本,下载到本地缓存(默认路径:~/.cargo/registry
),并在 Cargo.lock
中记录精确版本。
3. 查看依赖树
cargo tree # 查看依赖层级(扁平化显示)
cargo tree --depth 2 # 仅显示前两层依赖
输出示例:
hello_world v0.1.0
├── reqwest v0.11.18
│ ├── serde v1.0.197 (*)
│ ├── tokio v1.36.0
│ │ ├── tokio-macros v2.3.1
│ │ └── ...
└── serde v1.0.197
作用:排查依赖冲突(如两个依赖要求同一库的不同版本),通过 Cargo.lock
锁定版本后,所有依赖将使用同一版本。
4. 管理开发依赖
测试、文档生成等仅在开发阶段需要的依赖,应放在 [dev-dependencies]
中:
[dev-dependencies]
rstest = "0.18" # 用于编写测试用例
说明:[dev-dependencies]
中的库不会被打包到最终发布的二进制文件中,仅用于本地测试和文档生成。
四、高级功能:自定义构建与扩展
1. 构建脚本(Build Script)
通过 build.rs
可以在编译前执行自定义逻辑(如生成代码、调用外部工具)。
步骤:
- 在项目根目录创建
build.rs
。 - 在
Cargo.toml
中声明build = "build.rs"
。 - 在
build.rs
中使用println!("cargo:rustc-env=VAR=value")
向编译器传递环境变量。
示例(生成版本信息):
// build.rs
fn main() {
let version = env!("CARGO_PKG_VERSION");
// 读取 Cargo.toml 中的 version
println!("cargo:rustc-env=APP_VERSION={}", version);
}
// src/main.rs
fn main() {
println!("App version: {}", env!("APP_VERSION"));
// 输出 0.1.0
}
2. 工作区(Workspace)
当项目包含多个关联的包(如主程序 + 工具库 + 测试库),可以使用工作区统一管理。
示例结构:
my_workspace/
├── Cargo.toml # 工作区清单
├── apps/
│ └── main_app/ # 主程序包
│ ├── Cargo.toml
│ └── src/
├── libs/
│ ├── utils/ # 工具库
│ │ ├── Cargo.toml
│ │ └── src/
│ └── api/ # API 库
│ ├── Cargo.toml
│ └── src/
└── tests/ # 集成测试(可选)
工作区 Cargo.toml
:
[workspace]
members = [
"apps/main_app",
"libs/utils",
"libs/api",
]
resolver = "2" # 使用新版依赖解析器(推荐)
作用:
- 共享依赖:所有成员包共用
Cargo.lock
(位于工作区根目录),避免重复下载。 - 统一构建:
cargo build --workspace
会构建所有成员包。 - 发布管理:可批量发布工作区中的包。
3. 特性(Features)
特性用于启用可选功能,常见于库开发。例如,某个库支持 async
运行时(如 tokio
或 async-std
),可通过特性让用户选择。
库的 Cargo.toml
示例:
[package]
name = "async_utils"
version = "0.1.0"
[features]
default = ["tokio-runtime"] # 默认启用 tokio 运行时
tokio-runtime = ["dep:tokio"] # 启用 tokio 依赖
async-std-runtime = ["dep:async-std"] # 启用 async-std 依赖
[dependencies]
tokio = { version = "1.0", optional = true } # 可选依赖
async-std = { version = "1.0", optional = true }
用户使用时:
[dependencies]
async_utils = { version = "0.1.0", features = ["async-std-runtime"] } # 启用 async-std 特性
原理:optional = true
标记依赖为可选,features
中通过 dep:name
语法关联可选依赖,用户通过 features
开关启用功能。
五、测试与文档
1. 运行测试
Cargo 集成了测试框架,支持单元测试(#[test]
)、集成测试(tests/
目录下的文件)和文档测试(///
注释中的示例)。
示例测试:
// src/lib.rs
pub fn add(a: i32, b: i32) ->
i32 {
a + b
}#[cfg(test)]
mod tests {
use super::*;#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
}
运行测试:
cargo test # 运行所有测试(单元 + 文档测试)
cargo test test_add # 运行特定测试
cargo test -- --nocapture # 显示测试输出的详细日志(默认会截断)
2. 生成文档
Cargo 可以为库生成 HTML 文档(基于 Rustdoc),包含代码注释和示例。
生成文档:
cargo doc # 生成文档到 target/doc/<包名>/cargo doc --open # 生成后自动打开浏览器查看
文档注释示例:
/// 计算两个整数的和
///
/// # 示例
/// ```
/// assert_eq!(async_utils::add(2, 3), 5);
/// ```
pub fn add(a: i32, b: i32) ->
i32 {
a + b
}
说明:cargo doc
会解析 ///
注释,生成包含示例代码(可执行验证)的文档,适合库的 API 说明。
六、发布与共享
1. 发布到 crates.io
将包发布到 https://crates.io/ 供他人使用,需先注册账号并获取 API Token。
步骤:
- 登录 https://crates.io/,进入账户设置,复制 API Token。
- 本地终端执行
cargo login <API_TOKEN>
完成认证。 - 确保
Cargo.toml
中的元数据完整(name
、version
、description
、license
等)。 - 执行
cargo publish
上传包。
注意:发布后版本不可修改,若需修复 bug 需递增版本号(如从 0.1.0
到 0.1.1
)后重新发布。
2. 安装二进制包
通过 cargo install
可以安装 crates.io 上的二进制包(如 ripgrep
、fd-find
)。
示例:
cargo install ripgrep # 安装 ripgrep(rg 命令行工具)
原理:cargo install
下载包,编译二进制文件,并安装到 ~/.cargo/bin/
(需将该路径添加到 PATH
环境变量以全局访问)。
七、配置与优化
1. 配置镜像源(国内加速)
由于网络原因,国内用户可通过修改 Cargo 配置文件,使用国内镜像源(如清华源、中科大源)。
配置方法:
- 在
~/.cargo/config.toml
(Linux/macOS)或%USERPROFILE%\.cargo\config.toml
(Windows)中添加:[source.crates-io] replace-with = 'tuna' # 使用清华源 [source.tuna] registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git" [registries.tuna] index = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git" [net] git-fetch-with-cli = true # 可选:使用 git 命令行加速克隆
2. 优化构建速度
- 并行编译:设置环境变量
CARGO_BUILD_JOBS=N
(N
为 CPU 核心数),例如CARGO_BUILD_JOBS=8 cargo build
。 - 增量编译:Cargo 默认启用增量编译(仅重新编译修改的部分),可通过
CARGO_INCREMENTAL=1
强制启用(默认已启用)。 - 使用
sccache
:sccache
是 Rust 的编译缓存工具,可缓存编译结果加速后续构建:cargo install sccache # 安装 sccache export RUSTC_WRAPPER=sccache # Linux/macOS set RUSTC_WRAPPER=sccache # Windows
总结
Cargo 是 Rust 生态的核心工具,通过标准化的 Cargo.toml
和自动化流程,极大简化了依赖管理、构建和发布。掌握其核心功能(项目创建、依赖管理、测试文档、发布)后,开发者可高效构建和维护 Rust 项目。实际使用中,建议结合 cargo clippy
(代码检查)、cargo fmt
(代码格式化)等工具进一步提升代码质量。