Cargo 作为 Rust 官方标配的构建工具与包管理器,贯穿了 Rust 项目从初始化、开发、测试到部署的全生命周期。它不仅能自动处理依赖解析、编译构建、测试运行等核心流程,还提供了丰富的拓展命令,简化了复杂项目的管理成本。本文将逐一拆解 Cargo 的常用命令与高级功能,结合详细示例代码,讲解命令的实际用法、参数含义及场景化拓展,帮助开发者彻底吃透这一 Rust 生态核心工具。
一、Cargo 基础认知与环境准备
1.1 核心定位与价值
Rust 之所以能快速普及,Cargo 功不可没。它解决了传统编译型语言的诸多痛点:
-
统一依赖管理:自动拉取、解析、更新第三方依赖,避免版本冲突;
-
标准化构建流程:无需手动编写 Makefile 或 CMake,一行命令完成编译、链接;
-
全生命周期支持:覆盖项目初始化、测试、文档生成、发布等全流程;
-
生态无缝集成:与 crates.io(Rust 官方包仓库)、Git 深度联动,支持自定义构建脚本。
1.2 环境验证与版本查看
安装 Rust 时会自动附带 Cargo,可通过以下命令验证环境是否就绪:
bash
# 查看Cargo版本(同时显示Rust编译器版本)
cargo --version
# 输出示例:cargo 1.75.0 (1d8b05cdd 2023-11-20)
# 查看Cargo详细帮助信息(所有命令与参数说明)
cargo --help
# 查看特定命令的帮助(如build命令)
cargo build --help
拓展:Cargo 版本与 Rust 版本同步更新,可通过 rustup update 同时升级 Rust 编译器与 Cargo 工具链。
二、项目基础操作命令
这部分命令覆盖项目从初始化到运行的基础流程,是日常开发中使用频率最高的核心命令。
2.1 项目初始化:cargo new / cargo init
用于创建新的 Rust 项目,自动生成标准目录结构与配置文件。
bash
# 1. 创建新项目(会自动创建同名目录,默认生成二进制项目)
cargo new my_project
# 等价于:cargo new my_project --bin(--bin指定二进制项目)
# 2. 创建库项目(用于发布到crates.io,无main函数,供其他项目依赖)
cargo new my_lib --lib
# 3. 在现有目录中初始化项目(不创建新目录,仅生成配置文件与src目录)
mkdir existing_dir && cd existing_dir
cargo init # 默认二进制项目,加--lib可改为库项目
生成的标准目录结构:
plain
my_project/
├── Cargo.toml # 项目配置文件(依赖、编译规则等)
├── Cargo.lock # 依赖版本快照(首次构建后生成)
└── src/ # 源代码目录
└── main.rs # 二进制项目入口文件(库项目为lib.rs)
拓展:cargo new 会自动初始化 Git 仓库(生成 .gitignore 文件),若无需 Git 可添加 --vcs none 参数。
2.2 编译项目:cargo build
编译项目源代码,生成可执行文件或库文件,默认使用开发模式(dev profile)。
bash
# 1. 开发模式编译(默认,编译快、无优化、含调试信息)
cargo build
# 编译产物位于 target/debug/ 目录下(如target/debug/my_project)
# 2. 发布模式编译(优化级别最高,适合生产环境,编译耗时较长)
cargo build --release
# 编译产物位于 target/release/ 目录下,体积更小、运行更快
# 3. 编译特定目标平台(如WebAssembly)
# 先安装目标平台工具链:rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown
# 4. 强制重新编译(忽略缓存,即使代码无变更)
cargo build --force
拓展:开发模式与发布模式的区别由 Cargo.toml 中的 [profile] 区块配置,后续会详细讲解。编译缓存机制会缓存未变更的模块,大幅提升二次编译速度。
2.3 运行项目:cargo run
一键完成"编译+运行",等价于先执行 cargo build 再运行编译产物,适合快速调试。
bash
# 1. 开发模式运行(编译+执行debug版本)
cargo run
# 2. 发布模式运行(编译+执行release版本)
cargo run --release
# 3. 向可执行文件传递参数(-- 后面的参数会传递给程序)
# 示例:运行程序并传递 --port 8080 参数
cargo run -- --port 8080
# 4. 编译但不运行(仅检查编译是否通过,速度更快)
cargo run --no-run
示例:假设 main.rs 代码如下,运行 cargo run -- hello 会输出对应结果:
rust
// src/main.rs
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() > 1 {
println!("Hello, {}!", args[1]);
} else {
println!("Hello, World!");
}
}
2.4 检查代码:cargo check
快速检查代码语法错误、类型错误,仅做编译前校验,不生成可执行文件,速度比 cargo build 快数倍,适合开发中频繁校验。
bash
# 基础检查(开发模式)
cargo check
# 检查发布模式下的代码(包含更严格的优化检查)
cargo check --release
# 持续检查(代码变更时自动重新检查,需提前安装:cargo install cargo-watch)
cargo watch -x check
拓展:cargo check 是 Rust 开发的"效率神器",尤其在大型项目中,能大幅减少等待编译的时间,建议搭配 cargo-watch 实现实时校验。
三、依赖管理核心命令
Cargo 最强大的功能之一就是依赖管理,以下命令用于依赖的添加、删除、更新、检查等操作,直接关联 Cargo.toml 配置。
3.1 添加依赖:cargo add
自动向 Cargo.toml 中添加依赖,并拉取对应版本,无需手动编辑配置文件,Rust 1.62+ 版本支持。
bash
# 1. 添加生产环境依赖(默认从crates.io拉取最新兼容版本)
cargo add serde # 等价于在[dependencies]中添加 serde = "最新版本"
# 2. 添加指定版本的依赖
cargo add tokio@1.0 # 固定主版本1.0,拉取最新次版本
cargo add reqwest@0.11.18 # 固定精确版本
# 3. 添加带特征(features)的依赖
cargo add tokio --features full # 启用tokio的full特征
cargo add reqwest --no-default-features --features json,rustls-tls # 禁用默认特征,启用指定特征
# 4. 添加开发依赖(仅开发环境生效,如测试框架)
cargo add rand --dev
# 5. 添加Git依赖
cargo add my_crate --git https://github.com/your-username/my_crate.git
# 6. 添加本地依赖(子项目)
cargo add my_utils --path ./my_utils
拓展:cargo add 会自动解析依赖版本冲突,并更新 Cargo.lock 文件,比手动编辑 Cargo.toml 更安全高效。
3.2 删除依赖:cargo remove
从 Cargo.toml 中删除指定依赖,并清理对应的依赖文件,Rust 1.62+ 版本支持。
bash
# 1. 删除生产环境依赖
cargo remove serde
# 2. 删除开发依赖
cargo remove rand --dev
# 3. 删除本地/Git依赖(与普通依赖删除方式一致)
cargo remove my_utils
3.3 更新依赖:cargo update
更新依赖到符合 Cargo.toml 版本范围的最新版本,并更新 Cargo.lock 文件。
bash
# 1. 更新所有依赖
cargo update
# 2. 仅更新指定依赖(如仅更新serde)
cargo update serde
# 3. 更新依赖到指定版本(需符合Cargo.toml中的版本范围)
cargo update serde --precise 1.0.188
# 4. 强制更新到最新版本(忽略Cargo.lock,慎用,可能引入冲突)
cargo update --force
拓展:cargo update 不会突破 Cargo.toml 中的版本范围限制,例如 serde = "1.0" 仅会更新到 1.x.x 系列的最新版本,不会升级到 2.0.0。若需升级主版本,需手动修改 Cargo.toml 中的版本号。
3.4 依赖检查:cargo audit / cargo outdated
用于检查依赖的安全漏洞与版本更新情况,需提前安装对应工具。
bash
# 1. 检查依赖安全漏洞(安装:cargo install cargo-audit)
cargo audit
# 输出漏洞详情,可通过 cargo audit fix 自动修复部分漏洞
# 2. 检查过时依赖(安装:cargo install cargo-outdated)
cargo outdated
# 输出格式:依赖名称 | 当前版本 | 最新版本 | 是否可更新
# 示例:serde 1.0.180 1.0.188 Upgradable
最佳实践:定期执行 cargo audit 修复安全漏洞,使用 cargo outdated 了解依赖更新情况,避免使用过时依赖带来的风险。
3.5 配置 国内的镜像源
由于 crates.io 官方源位于海外,国内直接使用 Cargo 安装依赖确实会非常慢,甚至超时。
解决这个问题最有效的方法是修改 Cargo 的配置文件,将源替换为国内的镜像(如清华、中科大、阿里云等)。
🛠️ 核心步骤:修改配置文件,你需要编辑或创建 Cargo 的配置文件,告诉它去国内镜像下载库。
1. 找到配置文件路径
- Windows: C:\Users\你的用户名.cargo\config (如果文件夹或文件不存在,请手动创建)
- macOS / Linux: ~/.cargo/config 或 ~/.cargo/config.toml
2. 编辑配置文件
将下面任选一个镜像源的配置代码复制进去,保存即可。
🚀 推荐镜像源配置(任选其一)
为了方便你选择,我对比了几个主流的镜像源。目前推荐优先尝试阿里云或中科大,清华大学源近期有时效性限制。
💡 方案一:阿里云(推荐,速度快)
toml
[source.crates-io]
replace-with = 'aliyun'
[source.aliyun]
registry = "sparse+https://mirrors.aliyun.com/crates.io-index/"
💡 方案二:中国科学技术大学 (USTC)
toml
[source.crates-io]
replace-with = 'ustc'
[source.ustc]
registry = "https://mirrors.ustc.edu.cn/crates.io-index"
💡 方案三:清华大学 (TUNA)
注意:清华源可能只保留近期的版本,如果找不到库请换用上面的源。
toml
[source.crates-io]
replace-with = 'tuna'
[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"
3.6 扩展:Rustup 工具链安装慢怎么办?
如果你是在运行 rustup install 或 rustup update 更新 Rust 语言本身时很慢(而不仅仅是 cargo install),那是因为工具链也在下载海外源。
你需要设置环境变量来加速工具链下载(以中科大为例):
Windows (ui操作):
在 Windows 上通过环境变量切换到国内源(推荐中科大 / 清华源):
- 右键点击「此电脑」→ 选择「属性」→ 点击「高级系统设置」→ 打开「环境变量」。
- 在「用户变量」或「系统变量」中,点击「新建」,添加以下 2 个变量:
sh
变量名:RUSTUP_DIST_SERVER,变量值:https://mirrors.ustc.edu.cn/rust-static
变量名:RUSTUP_UPDATE_ROOT,变量值:https://mirrors.ustc.edu.cn/rust-static/rustup
Windows (PowerShell):
powershell
$Env:RUSTUP_DIST_SERVER='https://mirrors.ustc.edu.cn/rust-static'
$Env:RUSTUP_UPDATE_ROOT='https://mirrors.ustc.edu.cn/rust-static/rustup'
# 然后执行安装或更新命令
macOS / Linux (Bash/Zsh):
bash
export RUSTUP_DIST_SERVER="https://mirrors.ustc.edu.cn/rust-static"
export RUSTUP_UPDATE_ROOT="https://mirrors.ustc.edu.cn/rust-static/rustup"
这两个环境变量的核心作用是替换rustup的默认网络源,解决国内网络访问Rust官方服务器慢、卡顿/超时的问题,具体分工如下:
1. RUSTUP_DIST_SERVER的作用
它是rustup下载**Rust组件(比如不同编译目标的标准库、编译器等)**的服务器地址。
- Rust默认会从官方服务器(如
https://static.rust-lang.org)下载组件(比如你之前要装的x86_64-unknown-linux-gnu对应的rust-std标准库); - 把它设为国内镜像(如中科大源)后,
rustup会从国内服务器下载这些组件,速度会快很多,避免卡顿。
2. RUSTUP_UPDATE_ROOT的作用
它是rustup自身版本更新时,获取更新资源的根地址。
rustup本身也需要更新(比如执行rustup self update),默认会从官方地址拉取更新包;- 配置国内镜像后,
rustup自更新时也会从国内服务器获取资源,同样能解决更新慢的问题。
简单说:这两个变量是给rustup"换国内下载源"------前者管组件下载,后者管自身更新,都是为了让国内用户用rustup更顺畅。
四(上)、测试与调试相关命令
Rust 内置强大的测试框架,Cargo 提供了对应的命令来运行测试、生成测试报告,支持单元测试、集成测试、文档测试等多种场景。
4.1 运行测试:cargo test
运行项目中的所有测试用例(单元测试、集成测试、文档测试),默认生成测试报告。
bash
# 1. 运行所有测试(开发模式)
cargo test
# 2. 运行发布模式测试(优化编译,适合性能测试)
cargo test --release
# 3. 运行指定名称的测试用例(模糊匹配,如运行含"add"的测试)
cargo test add
# 4. 精确运行某个测试用例
cargo test test_add_two_numbers
# 5. 显示测试用例的打印输出(默认不显示通过用例的输出)
cargo test -- --show-output
# 6. 仅运行单元测试(不运行集成测试和文档测试)
cargo test --lib
# 7. 仅运行集成测试(测试文件位于tests/目录下)
cargo test --test integration_test
# 8. 运行文档测试(测试lib.rs中的文档示例代码)
cargo test --doc
# 9. 并行运行测试(默认开启,指定线程数为1可关闭并行)
cargo test -- --test-threads=1
示例:假设 src/lib.rs 中有以下测试用例,运行 cargo test 会自动执行:
rust
// src/lib.rs
/// 加法函数
/// # Examples
/// ```
/// use my_lib::add;
/// assert_eq!(add(2, 3), 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
// 单元测试
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_two_numbers() {
assert_eq!(add(2, 3), 5);
}
#[test]
fn test_add_negative_numbers() {
assert_eq!(add(-1, -2), -3);
}
}
4.2 调试程序:cargo run + 调试器
Cargo 本身不提供调试功能,但可与主流调试器(如 GDB、LLDB)联动,或使用专用工具 cargo-debug。
bash
# 1. 使用LLDB调试(macOS/Linux)
cargo build # 生成带调试信息的产物
lldb target/debug/my_project
# 2. 使用GDB调试(Linux)
gdb target/debug/my_project
# 3. 使用cargo-debug工具(简化调试流程,安装:cargo install cargo-debug)
cargo debug # 自动编译并启动调试器
# 4. 调试测试用例
cargo test --no-run # 仅编译测试用例,不运行
lldb target/debug/deps/my_lib-xxxx # 调试测试产物
四(下)、交叉编译 cargo build --target
在 Windows 或 macOS 上编译出能在 Linux 上运行的程序,通常面临的核心挑战是 链接器和 C 依赖库 的问题。
4-1、前要知识
3个重要的 关键术语:
1、Target Triple 目标三元组
目标三元组,用来描述 目标平台。例如:
- x86_64-unknown-linux-gnu(Linux x86_64
glibc版) - 或 x86_64-unknown-linux-musl(Linux x86_64
musl版)。
| 部分 | 值 | 含义 |
|---|---|---|
| 1. 架构 | x86_64 |
CPU 指令集。指代 64 位的 Intel/AMD 处理器(也就是我们普通电脑和大部分服务器的架构)。 |
| 2. 供应商 | unknown |
硬件/系统厂商。表示 "未知" 或 "通用" 。如果是苹果设备这里通常是 apple,如果是 Windows 可能是 pc 或 w64。 |
| 3. 系统 | linux |
操作系统内核。明确表示这是 Linux 系统。 |
| 4. ABI/环境 | gnu |
应用程序二进制接口。指明了它使用的是 GNU C 标准库,也就是我们常说的 glibc。 |
🌉C库(或者叫 C标准库)
核心作用只有一条:作为桥梁。
是 C语言程序 与 操作系统内核(或者硬件) 之间的中间层。
具体来说,它们负责做两件事:
- 封装系统调用:把操作系统内核提供的复杂、底层的接口(比如读写硬盘、分配内存、创建进程),封装成 C 语言里简单好用的函数(比如 printf, malloc, fopen)。
- 提供标准功能:实现 C 语言标准里规定的所有通用功能,比如字符串处理、数学计算、数据结构等,让程序员不用重复造轮子。
简单说:没有它们,你的 C 程序就无法运行,因为它没法跟电脑的系统沟通。
🌉 C库 的 具体实现: 工具链
C库 是一个接口,规范, 具体的实现 在 不能同的 操作系统上, 是不一样的:
| 你的称呼 | 它们的"小名" (昵称) | 它们的"大名" (学名/全称) | 备注 |
|---|---|---|---|
| Linux 主流版 | glibc | GNU C Library | 功能最全,Linux 的"官方"实现 |
| Linux 轻量版 | musl | musl libc | 追求简洁,Docker 容器最爱 |
| Windows 版 | MSVCRT / UCRT | Microsoft C Runtime | 微软自家的运行时 |
| macOS / iOS版 | Darwin | Darwin Libc | 苹果自家的,基于 BSD 代码。 |
| Android 版 | Bionic | Bionic Libc | Google 为安卓定制 |
| 嵌入式版 | Newlib | Newlib | 专为没有操作系统的单片机设计 |
- Ubuntu, Debian, CentOS, Fedora, Red Hat:这些统统都是 glibc。
- Alpine Linux:这是最著名的 musl 发行版(这也是为什么 Alpine 镜像特别小的原因)。
- Arch Linux, openSUSE:也是 glibc
对于 CentOS 环境,优先使用 x86_64-unknown-linux-gnu (glibc)。除非你遇到了严重的依赖库版本冲突问题,或者对文件体积有极其苛刻的要求,否则不要轻易切换到 musl。
Golang 的交叉编译, 仅设置 GOOS=linux + GOARCH=amd64(amd64 对应 x86_64 架构)时,Go 编译器会默认链接 GNU C 标准库(glibc),对应的目标三元组就是 x86_64-unknown-linux-gnu
🌉提问:我用的是 rust,不是 C,还需要 这些东西吗?
答:是的,你通常仍然需要它们。
虽然你写的是 Rust 代码,但你的 程序 最终运行在 操作系统上,而目前的现实是:操作系统(如 Linux)是用 C 语言写的,它只认识 C 语言的"系统调用"规范。
即便你一行 C 代码都没写,Rust 代码在底层依然需要通过这些"C 库"来和操作系统对话。
Rust 标准库(std)依赖 C 库,Rust 标准库的底层实现,在 Linux 平台上,是直接封装了 glibc 或 musl 的功能。
2、Linker:链接器。
将编译好的目标文件 打包成 最终可执行文件 的工具。
你可以把链接器想象成"打包发货员":
- Windows 的打包员习惯用 .exe 纸箱,贴 PE 格式的标签。
- Linux 的打包员习惯用 ELF 纸箱,贴 ELF 格式的标签。
- macOS 的打包员习惯用 Mach-O 纸箱,贴 Mach-O 格式的标签。
虽然 Rust 的代码(货物)是一样的,但最后打包成什么样,完全取决于你用哪个系统的链接器。
| 维度 | Windows | Linux | macOS |
|---|---|---|---|
| 默认链接器名字 | link.exe (MSVC) 或 ld (MinGW) |
ld (GNU Binutils) |
ld (属于 LLVM/Clang 工具链) |
| 背后的工具链 | MSVC (微软官方) 或 MinGW-w64 | GNU Binutils | LLVM (Clang) |
| 生成的文件格式 | PE (Portable Executable) | ELF (Executable and Linkable Format) | Mach-O |
| 生成的文件后缀 | .exe, .dll |
无后缀, .so |
.out, .dylib |
| Rust 默认行为 | 自带链接器 (MSVC) | 需安装 binutils |
自带 (Xcode Command Line Tools) |
正是因为 链接器 不一样,所以 Rust 在做交叉编译时,必须 "借刀杀人" :
如果你在 Windows 上编译 Linux 程序: Rust 不能用 Windows 自带的 link.exe(因为它只会打 PE 包裹)。 你必须安装 Linux 的链接器(通常是 ld,来自 GNU Binutils 的 Windows 移植版),并告诉 Rust:"去用那个 x86_64-linux-gnu-ld 来帮我打包。"
当你进行 Rust 交叉编译时,最大的坑往往就在于找不到对应的链接器。因为 Rust 只负责把代码编译成中间代码(货物),最后"打包"成操作系统能识别的文件(包裹),必须依赖目标系统对应的链接器来完成。
3、静态链接 vs 动态链接:
举例说明: 静态链接 和 动态链接 这两个概念:
你可以把它们想象成打包行李的两种不同方式:
静态链接 :把所有要用的东西(牙刷、衣服、电脑充电器)都塞进一个行李箱里,走到哪带哪,完全不依赖外面的环境。
动态链接:只带衣服,到了目的地(比如酒店)再借用那里的牙刷和吹风机。
| 维度 | 静态链接 | 动态链接 |
|---|---|---|
| 链接时机 | 编译时(打包好) | 运行时(启动时找) |
| 文件大小 | 大(自带干粮) | 小(只留接口) |
| 内存占用 | 高(每个程序都有一份库代码) | 低(多个程序共享一份库) |
| 部署难度 | 低(扔过去就能跑) | 高(得先装好各种依赖库) |
| 更新维护 | 麻烦(必须重编译程序) | 方便(替换库文件即可) |
| 常见后缀 | 无(所有代码都在 .exe 里) | Windows: .dll / Linux: .so |
推荐静态链接(使用 musl), 主要原因 在于 Linux 的"方言"太多。
- 动态链接的噩梦:
你在 Ubuntu 22.04 上编译(动态链接),程序依赖 glibc 2.35。
你把程序扔到 CentOS 7 服务器上跑,结果报错:GLIBC_2.35 not found。
你不能随便升级服务器的 glibc,因为升级它可能会导致服务器上其他老程序挂掉。
结果:程序跑不起来,非常痛苦。 - 静态链接的救赎:
你使用 x86_64-unknown-linux-musl 编译。
你把 glibc 的功能(musl 实现)直接打包进了程序里。
你把程序扔到任何 Linux 服务器(CentOS, Ubuntu, Debian),它都能跑,因为它根本不看服务器有没有 glibc,它自己带着呢
golang在这方面的情况:
| 场景 | 命令 | 链接方式 | 是否依赖目标环境 |
|---|---|---|---|
| 纯 Go 代码 | go build |
静态 | 否(直接运行) |
| 含 C 依赖 (默认) | go build |
动态 | 是(依赖 glibc 等) |
| 含 C 依赖 (禁用 CGO) | CGO_ENABLED=0 go build |
静态 | 否(推荐用于 Docker/部署) |
4-2、操作步骤
五、进阶功能命令
以下命令适用于复杂项目场景,如文档生成、工作区管理、交叉编译、自定义构建脚本等,提升项目的可维护性与拓展性。
5.1 生成文档:cargo doc
cargo doc 就像是 Rust 项目的"说明书生成器"。通过在代码中编写整洁的 /// 注释,你可以让使用者(包括未来的你自己)通过浏览器直观地查看 API 的用法、参数含义以及可运行的示例代码,极大地提升了代码的可读性和可维护性。
bash
# 1. 生成项目文档(包含自身及依赖的文档)
cargo doc
# 2. 仅生成项目自身的文档(不包含依赖)
cargo doc --no-deps
# 3. 生成文档并自动在浏览器中打开预览
cargo doc --open
# 4. 生成发布模式文档(优化文档体积,去除调试信息)
cargo doc --release
# 5. 忽略文档警告(如未完善的文档注释)
cargo doc --quiet
cargo doc 是 Rust 生态系统中一个非常强大且实用的工具。简单来说,它的作用是为你的 Rust 项目自动生成漂亮的 HTML 格式文档。
它不仅仅是把注释转换成网页,更重要的是,它能解析你的代码结构(如结构体、枚举、函数、Trait 等),并生成详细的 API 手册,这对于库(library)的开发者和使用者来说是必不可少的。
为了让你更直观地理解,我将通过一个具体的项目代码例子来演示它的用法和效果。
🧰 核心作用总结
- 生成文档:将代码中的特定注释(/// 或 //!)转换为 HTML 网页。
- 可视化依赖:不仅生成你自己代码的文档,还会生成你项目所依赖的第三方库(如 rand, serde 等)的文档。
- 文档测试:它会自动运行你写在注释中的代码示例(即文档测试),确保你的示例代码是最新且能通过编译的,防止出现"文档骗人"的情况。
💻 具体项目代码举例
假设我们正在开发一个名为 math_utils 的数学工具库。这是我们的 src/lib.rs 文件内容:
rust
//! # Math Utils 库
//!
//! 这是一个简单的数学工具库,提供了基本的运算功能。
//! 你可以使用本库来进行加减乘除等操作。
/// 计算两个数字的和
///
/// 该函数接收两个 i32 类型的整数,并返回它们的和。
///
/// # 参数
///
/// * a - 第一个加数
/// * b - 第二个加数
///
/// # 返回值
///
/// 返回 a + b 的结果
///
/// # 示例
///
///
/// use math_utils::add;
///
/// let result = add(5, 3);
/// assert_eq!(result, 8);
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
/// 计算两个数字的差
///
/// # 注意
///
/// 结果可能会是负数。
///
/// # 示例
///
///
/// use math_utils::subtract;
///
/// assert_eq!(subtract(10, 3), 7);
pub fn subtract(a: i32, b: i32) -> i32 {
a - b
}
// 私有函数(以 fn 开头,没有 pub)
// 这个函数默认不会出现在生成的公开文档中
[allow(dead_code)]
fn private_helper() {
// ...
}
🚀 如何使用 cargo doc
在你的项目根目录下(即 Cargo.toml 所在的目录),打开终端执行以下命令:
- 生成文档(不打开浏览器)
cargo doc
运行后,文档会被生成在 target/doc/ 目录下。
- 生成文档并自动打开浏览器(推荐)
cargo doc --open
这是最常用的命令。Cargo 会自动编译文档并使用你的默认浏览器打开 index.html。
👀 生成了什么?
执行完 cargo doc --open 后,你会看到类似这样的网页界面:
- 首页概览:你会看到 "Math Utils 库" 这个标题和介绍(来自 //! 注释),以及下面列出了 add 和 subtract 两个公共函数。
- 详细的函数页面 :
- 点击 add 函数,你会看到参数说明 、返回值 以及最重要的代码示例。
- 注意看示例代码块,它通常是可点击运行的(在文档页面上有一个"Run"或"Try Example"的按钮,这取决于生成的文档版本),这证明了 cargo doc 确实执行了这些示例来保证准确性。
- 隐藏私有项:你不会在文档中看到 private_helper 函数,因为它是私有的(没有 pub 关键字),cargo doc 默认只展示公共 API。
📝 关键注释语法说明
在上面的代码中,你可能注意到了两种不同的注释符号,它们的含义是:
- /// (外部文档注释) :
- 作用于它下面的代码项(Item)。
- 例如:/// 计算两个数字的和 紧跟在 pub fn add 上面,就是为这个函数写文档。
- //! (内部文档注释) :
- 作用于它所在的代码项。
- 通常用在文件的最开头(如 src/lib.rs),用来描述整个 Crate(库)是干什么的。
5.2 工作区管理:cargo workspace
用于管理多 crate 项目(工作区),实现依赖统一、批量编译、协同管理。
bash
# 1. 查看工作区信息(包含所有子crate)
cargo workspace list
# 2. 编译工作区所有子crate
cargo build --workspace
# 3. 仅编译指定子crate
cargo build -p core # -p 是 --package 的缩写,指定子crate名称
# 4. 运行指定子crate的可执行文件
cargo run -p cli -- --port 8080 # 运行cli子crate,传递参数
# 5. 测试工作区所有子crate
cargo test --workspace
# 6. 清理工作区所有编译产物
cargo clean --workspace
示例:工作区根目录 Cargo.toml 配置如下,配合上述命令可实现多 crate 协同管理:
toml
[workspace]
members = [
"crates/core", # 核心功能子crate
"crates/cli", # 命令行工具子crate
]
[workspace.dependencies]
serde = "1.0"
tokio = "1.0"
5.3 自定义构建脚本:cargo build + build.rs
Cargo 支持通过 build.rs 脚本在编译前执行自定义逻辑(如代码生成、依赖检查、环境变量设置),无需额外命令,编译时自动执行。
示例 1:build.rs 脚本(生成版本信息):
rust
// build.rs
use std::env;
use std::fs::write;
use std::path::PathBuf;
fn main() {
// 获取项目版本信息
let version = env::var("CARGO_PKG_VERSION").unwrap();
// 生成版本文件,供src代码引用
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
write(out_dir.join("version.rs"), format!(r#"pub const VERSION: &str = "{}";"#, version)).unwrap();
// 告诉Cargo,当版本变更时重新运行构建脚本
println!("cargo:rerun-if-changed=Cargo.toml");
}
示例 2:在 src/main.rs 中引用生成的文件:
rust
// src/main.rs
include!(concat!(env!("OUT_DIR"), "/version.rs"));
fn main() {
println!("Project version: {}", VERSION);
}
运行 cargo build 时,Cargo 会先执行 build.rs,再编译项目代码,实现自定义构建逻辑。
5.4 发布到 crates.io:cargo publish
将库项目发布到 Rust 官方包仓库 crates.io,供其他开发者依赖使用。
bash
# 1. 登录crates.io(需先在crates.io获取API令牌)
cargo login <your-api-token>
# 2. 检查项目是否符合发布规范(如版本、许可证、文档是否完整)
cargo publish --dry-run
# 3. 发布项目到crates.io
cargo publish
# 4. 发布指定版本(需先更新Cargo.toml中的version字段)
cargo publish --version 0.1.1
# 5. 撤销已发布的版本(仅发布后72小时内可撤销,且无其他依赖引用)
cargo yank --vers 0.1.0
# 恢复已撤销的版本
cargo yank --vers 0.1.0 --undo
最佳实践:发布前需确保 Cargo.toml 包含完整的元信息(名称、版本、许可证、描述),且文档完善,建议先执行 cargo publish --dry-run 排查问题。
六、发布到 crates.io 完整流程
crates.io 是 Rust 官方包仓库,将库项目发布到该平台可让全球开发者依赖使用。发布需遵循严格的规范,从项目准备、校验到正式发布、版本维护,形成完整闭环。以下是详细流程及操作指南。
6.1 前置准备
(1)注册 crates.io 账号并获取 API 令牌
首先需注册 crates.io 账号,绑定 GitHub 账号即可快速登录,步骤如下:
-
访问 crates.io,点击右上角"Sign in with GitHub"完成登录;
-
登录后进入个人设置页(右上角头像 → Settings),找到"API Tokens"选项;
-
点击"New token",输入令牌名称(如"cargo-publish-token"),勾选"Publish crates"权限(仅发布需此权限,最小权限原则);
-
生成令牌后立即复制保存(仅显示一次,丢失需重新生成)。
(2)完善项目元信息(Cargo.toml)
crates.io 对项目元信息有强制要求,缺失会导致发布失败,需确保 Cargo.toml 包含以下内容:
toml
[package]
name = "my-lib" # 必须唯一,crates.io 不允许重名,可先在官网搜索确认
version = "0.1.0" # 遵循语义化版本,首次发布建议从 0.1.0 开始
edition = "2021"
authors = ["Your Name <your.email@example.com>"] # 作者信息(可选但推荐)
description = "A concise description of your library" # 项目描述(必填,≤100字符)
license = "MIT" # 开源许可证(必填,需与根目录 LICENSE 文件对应)
repository = "https://github.com/your-username/my-lib.git" # 代码仓库(可选但推荐)
homepage = "https://github.com/your-username/my-lib" # 项目主页(可选)
documentation = "https://docs.rs/my-lib" # 文档地址(发布后自动生成,可先填占位符)
keywords = ["rust", "example", "utils"] # 关键词(可选,优化搜索)
categories = ["utilities"] # 分类(可选,需从 crates.io 支持列表选择)
# 启用新版依赖解析器(避免依赖冲突,推荐)
resolver = "2"
注意:
-
许可证需在项目根目录放置对应 LICENSE 文件(如 MIT 许可证需 LICENSE-MIT 文件);
-
项目名称需在 crates.io 唯一,发布前可先搜索确认无重名;
-
描述需简洁准确,避免空值或无意义内容。
(3)完善文档与测试
良好的文档和测试是开源项目的基础,也是 crates.io 推荐的规范:
-
为公开 API 添加文档注释(
///开头),包含功能说明、使用示例; -
编写单元测试和集成测试,确保核心功能可用(运行
cargo test验证); -
生成文档并预览(
cargo doc --open),检查格式和可读性。
(4)清理冗余依赖与代码
发布前需精简项目,提升用户体验:
-
删除无用依赖(使用
cargo tree检查依赖链,cargo remove删除冗余依赖); -
移除调试代码、打印语句,确保发布版本简洁;
-
检查是否包含敏感信息(如密钥、个人信息),避免泄露。
6.2 发布操作步骤
(1)登录 crates.io
使用之前获取的 API 令牌登录,仅需首次发布时执行:
bash
# 替换 <your-api-token> 为实际令牌
cargo login <your-api-token>
# 登录成功无额外输出,失败会提示令牌无效
拓展:登录状态保存在本地 ~/.cargo/credentials 文件中,无需每次发布都重新登录。
(2)干跑校验(--dry-run)
发布前先执行干跑命令,模拟发布流程,排查潜在问题(如元信息缺失、依赖冲突):
bash
# 干跑校验,不实际发布
cargo publish --dry-run
常见报错及解决:
-
"missing description":补充
Cargo.toml中的description字段; -
"license not found":添加对应 LICENSE 文件,确保
license字段与文件名匹配; -
"dependency resolution failed":启用新版解析器(
resolver = "2"),调整依赖版本。
(3)正式发布
干跑无报错后,执行正式发布命令:
bash
# 正式发布到 crates.io
cargo publish
发布成功后,终端会提示 Uploaded my-lib v0.1.0 to crates.io,同时:
-
crates.io 会自动生成项目页面(地址:https://crates.io/crates/项目名称);
-
docs.rs 会自动抓取项目并生成在线文档(通常几分钟内完成,地址:https://docs.rs/项目名称);
-
本地
Cargo.lock文件会更新为发布版本的依赖快照。
6.3 发布后维护
(1)版本更新
后续迭代需更新版本号(遵循语义化版本),步骤如下:
-
修改
Cargo.toml中的version字段(如 0.1.0 → 0.1.1,修复bug;0.1.0 → 0.2.0,新增功能;0.1.0 → 1.0.0,API 稳定); -
执行干跑校验(
cargo publish --dry-run); -
正式发布(
cargo publish)。
(2)版本撤销(yank)
若发布的版本存在严重bug或安全漏洞,可撤销该版本(仅发布后72小时内可撤销,且无其他项目依赖时生效):
bash
# 撤销指定版本(如 0.1.0)
cargo yank --vers 0.1.0
# 恢复已撤销的版本
cargo yank --vers 0.1.0 --undo
注意:撤销仅阻止新项目依赖该版本,已依赖的项目仍可正常使用,建议同时发布修复版本并通知用户升级。
(3)文档更新
若仅需更新文档(无代码变更),可使用 cargo doc --upload 强制更新 docs.rs 文档(需 Rust 1.70+ 版本):
bash
# 强制更新在线文档
cargo doc --upload
6.4 常见问题与注意事项
-
发布失败:网络问题:crates.io 服务器在境外,可配置 Cargo 镜像加速,或使用代理;发布失败后可重试,避免重复发布同一版本。
-
版本重复:同一版本号不可重复发布,若发布失败但版本已被占用,需更新版本号后重新发布。
-
API 兼容性:0.x 版本可随意变更 API,1.0.0 版本后需保证 API 向后兼容,避免频繁变更。
-
依赖安全 :定期用
cargo audit检查依赖漏洞,及时发布更新版本修复。
七、实用工具与拓展命令
7.1 cargo install 命令详解
cargo install 是 Cargo 用于安装二进制 crate 的核心命令,可从 crates.io、Git 仓库或本地路径安装可执行工具,生成的二进制文件默认放入 ~/.cargo/bin 目录(已自动加入系统环境变量,支持全局调用)。其核心价值是快速拓展 Cargo 生态工具链,安装各类开发辅助工具,区别于 cargo add(添加项目依赖库),cargo install 专注于安装可独立运行的命令行工具。
核心功能与使用场景
-
安装官方/第三方辅助工具:这是最常用场景,用于安装 Cargo 生态的各类开发工具(如代码检查、格式化、依赖分析工具),提升开发效率;
-
从 Git 安装工具:支持安装 Git 仓库中的二进制 crate,适合使用工具的开发版或自定义分支版本;
-
本地 crate 安装调试:开发二进制工具时,可通过本地路径安装,验证工具的全局运行效果;
-
指定版本安装:可安装工具的特定版本,避免新版本兼容性问题。
常用示例
bash
# 1. 从 crates.io 安装最新版本工具(最常用)
# 示例:安装 cargo-watch(文件变更监听工具)
cargo install cargo-watch
# 2. 安装指定版本的工具(避免新版本兼容问题)
# 示例:安装 8.4.0 版本的 cargo-tree(依赖树查看工具)
cargo install cargo-tree --version 8.4.0
# 等价写法:cargo install cargo-tree@8.4.0
# 3. 从 Git 仓库安装工具(支持分支、标签、提交哈希)
# 示例:从 GitHub 安装某个工具的开发分支
cargo install --git https://github.com/your-username/cargo-tool.git --branch dev
# 4. 从本地路径安装工具(开发调试自用工具时)
# 示例:安装本地 ./my-cargo-tool 目录下的二进制 crate
cargo install --path ./my-cargo-tool
# 5. 自定义安装路径(默认 ~/.cargo/bin,需手动配置环境变量)
cargo install cargo-asm --root /usr/local/bin
# 6. 卸载已安装的工具(对应 install 的反向操作)
cargo uninstall cargo-watch
注意事项
-
仅能安装二进制 crate(包含 main 函数的可执行项目),无法安装纯库 crate(无 main 函数);
-
安装后工具可全局调用,若提示"命令不存在",需检查
~/.cargo/bin是否在系统环境变量中; -
部分工具依赖系统库(如编译相关工具),安装失败时需先安装对应系统依赖(如 Ubuntu 下的
build-essential); -
可通过
cargo install --list查看所有已安装的 Cargo 工具及版本。
7.2 常用第三方工具(基于 cargo install 安装)
bash
# 1. cargo-watch:文件变更时自动执行命令(实时编译、检查)
cargo install cargo-watch
# 用法:自动检查代码变更并重新编译
cargo watch -x build
# 2. cargo-edit:增强依赖管理(兼容旧版本Rust,提供add/remove/update命令)
cargo install cargo-edit
# 3. cargo-tree:查看依赖树结构(清晰展示依赖关系)
cargo install cargo-tree
# 用法:查看项目依赖树
cargo tree
# 查看指定依赖的依赖链
cargo tree -p serde
# 4. cargo-clippy:代码 lint 工具(检查代码风格、潜在问题)
# 无需安装,Rust自带,用法:
cargo clippy
# 自动修复部分问题
cargo clippy --fix
# 5. cargo-fmt:代码格式化工具(遵循Rust官方风格)
# 无需安装,Rust自带,用法:
cargo fmt # 格式化所有代码
cargo fmt --check # 仅检查格式,不修改代码
# 6. cargo-asm:查看编译后的汇编代码(优化性能分析)
cargo install cargo-asm
# 用法:查看main函数的汇编代码
cargo asm --release my_project::main
7.3 其他实用命令
bash
# 1. 清理编译产物(删除target目录)
cargo clean
# 2. 查看项目信息(名称、版本、依赖等)
cargo pkgid # 查看项目唯一标识
cargo metadata # 以JSON格式输出项目元数据(适合脚本处理)
# 3. 运行自定义命令(在Cargo.toml中定义)
# 在Cargo.toml中添加:
# [scripts]
# start = "cargo run --release"
# 运行自定义命令:
cargo script start
# 4. 构建静态链接产物(适合跨平台部署)
cargo build --release --target x86_64-unknown-linux-musl
八、最佳实践与常见问题排查
8.1 最佳实践
-
依赖管理 :
优先使用
cargo add/remove管理依赖,避免手动编辑Cargo.toml; -
二进制项目提交
Cargo.lock,确保跨环境构建一致性;库项目不提交Cargo.lock,让使用者自主解析依赖; -
定期用
cargo audit检查安全漏洞,用cargo outdated更新依赖。 -
编译优化 :
开发时用
cargo check快速校验,用cargo run调试; -
生产环境用
cargo build --release编译,开启优化; -
大型项目使用工作区,拆分多个子crate,提升编译效率。
-
测试与文档 :
编写单元测试与集成测试,定期执行
cargo test; -
完善文档注释,用
cargo doc --open验证文档效果; -
文档示例代码用
# Examples标签,确保可运行。
8.2 常见问题排查
(1)依赖冲突报错
报错示例:version solving failed: package A v1.0.0 depends on B ^0.1.0, but B v0.2.0 is required by C v2.0.0。
解决方法:
-
升级/降级冲突依赖,调整
Cargo.toml中的版本范围; -
启用新版依赖解析器(
resolver = "2"),允许同一 crate 多版本共存; -
用
cargo tree查看依赖链,定位冲突源头,手动指定兼容版本。
(2)编译失败,提示缺少系统依赖
报错示例:could not find system library 'openssl' required by the 'openssl-sys' crate。
解决方法:安装对应系统依赖,例如:
-
Ubuntu/Debian:
sudo apt-get install libssl-dev; -
macOS:
brew install openssl; -
Windows:通过 Chocolatey 安装对应库,或使用纯 Rust 替代方案(如
rustls)。
(3)交叉编译失败
解决方法:
-
确保已安装对应目标平台工具链:
rustup target add <target-triple>; -
安装交叉编译器(如 ARM 平台需
gcc-aarch64-linux-gnu); -
在
.cargo/config.toml中配置交叉编译工具链路径。
九、总结
Cargo 作为 Rust 生态的核心工具,不仅简化了项目的构建与依赖管理流程,还通过丰富的命令与拓展能力,支撑起从简单脚本到大型企业级项目的全生命周期管理。本文从基础命令到进阶功能,全面拆解了 Cargo 的核心用法,结合示例代码与实践技巧,帮助开发者快速上手并灵活运用。
在实际开发中,建议结合项目场景选择合适的命令与工具,例如用 cargo check 提升开发效率,用工作区管理多 crate 项目,用 cargo audit 保障依赖安全。同时,持续关注 Cargo 的版本更新与生态工具,不断优化开发流程,充分发挥 Rust 语言的优势。