Cargo 教程(最佳实践)

Cargo 教程:Rust 项目构建的基石

你是否曾经在使用 Rust 编写程序时,面对一堆依赖管理、编译配置和构建流程感到无从下手?别担心,这正是 Cargo 的用武之地。作为 Rust 的官方包管理器与构建工具,Cargo 不仅简化了项目创建、依赖管理与编译流程,更让整个开发体验变得像搭积木一样顺畅。今天,我们就来深入聊聊 Cargo 教程,带你从零开始掌握这个 Rust 开发中不可或缺的核心工具。

Cargo 的存在,就像一位经验丰富的项目经理。它不直接写代码,却能协调所有资源——编译器、依赖库、测试脚本、文档生成——让整个项目有条不紊地运行。无论你是刚接触 Rust 的初学者,还是已有一定经验的中级开发者,掌握 Cargo 都是迈向高效开发的第一步。

安装与初始化项目

在开始任何项目前,确保你已正确安装 Rust 工具链。可以通过官方推荐的安装方式完成,例如使用 rustup 工具:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

安装完成后,运行以下命令验证环境:

rustc --version
cargo --version

若输出版本号,说明安装成功。此时,你就可以使用 Cargo 来创建新项目了。

创建一个名为 hello_cargo 的项目:

cargo new hello_cargo

这条命令会生成一个包含 src/main.rs 源文件和 Cargo.toml 配置文件的项目结构。其中,Cargo.toml 是项目的“说明书”,定义了项目名称、版本、依赖等信息。

进入项目目录并查看内容:

cd hello_cargo
cat Cargo.toml

输出如下:

[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"


[dependencies]

这个文件虽然简单,却是 Cargo 教程中最重要的部分之一。它告诉你:项目名叫 hello_cargo,版本是 0.1.0,使用的是 Rust 2021 版本的语法标准。目前没有依赖项,但你可以随时添加。

构建与运行项目

Cargo 最基础的功能就是构建和运行项目。我们先来看如何编译并运行默认的 main.rs 文件。

cargo run

执行该命令后,Cargo 会自动完成以下操作:

  1. 检查 Cargo.toml 是否有变更,若有则重新解析依赖;
  2. 自动调用 rustc 编译源代码;
  3. 生成可执行文件(位于 target/debug/hello_cargo);
  4. 运行生成的程序。

输出结果为:

Hello, world!

这正是 src/main.rs 中的默认内容。你不需要手动指定编译命令或运行路径,Cargo 会帮你全部搞定。

如果你想只编译而不运行,使用:

cargo build

编译后的可执行文件同样位于 target/debug/ 目录中。如果你需要发布版本(优化过的代码),可以使用:

cargo build --release

这会启用编译优化,生成更高效的二进制文件,但编译时间会更长。建议在部署前使用此命令。

管理依赖项

在实际开发中,很少有项目是“从零开始”的。大多数时候,你都需要引入第三方库。Cargo 通过 Cargo.toml 文件管理这些依赖。

假设你想在项目中使用 serde 库来处理 JSON 数据,只需在 Cargo.toml[dependencies] 部分添加:

[dependencies]
serde = "1.0"

保存后,运行:

cargo build

Cargo 会自动从 crates.io(Rust 的官方包仓库)下载 serde 及其所有依赖项,并完成编译。

💡 提示:serde = "1.0" 表示使用 1.0 版本的 serde,Cargo 会自动选择兼容的最新子版本。你也可以指定具体版本,如 serde = "1.0.180"

为了验证依赖是否生效,打开 src/main.rs,添加以下代码:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u32,
}

fn main() {
    let person = Person {
        name: "Alice".to_string(),
        age: 30,
    };

    // 将结构体序列化为 JSON 字符串
    let json = serde_json::to_string(&person).unwrap();
    println!("Serialized: {}", json);

    // 将 JSON 字符串反序列化为结构体
    let deserialized: Person = serde_json::from_str(&json).unwrap();
    println!("Deserialized: {} ({})", deserialized.name, deserialized.age);
}

注意:你还需要在 Cargo.toml 中添加 serde_json 依赖:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

然后再次运行 cargo build,就能看到输出:

Serialized: {"name":"Alice","age":30}
Deserialized: Alice (30)

这就是 Cargo 教程中依赖管理的魅力所在:声明依赖,自动下载、编译、链接,开发者只需专注业务逻辑。

使用 Cargo 进行测试与文档

Cargo 不仅能构建代码,还能帮你写测试、生成文档。它内置了测试框架,支持单元测试和集成测试。

src/lib.rs 中添加一个简单的函数:

pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

然后在 tests/ 目录下创建 integration_test.rs

#[test]
fn test_add() {
    assert_eq!(add(2, 3), 5);
    assert_eq!(add(-1, 1), 0);
}

运行测试:

cargo test

Cargo 会自动发现并运行所有测试文件。输出将显示测试通过情况。

此外,Cargo 还支持文档生成。在函数前添加文档注释:

/// 计算两个整数的和
/// 
/// # Examples
/// 
/// ```
/// let result = add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

运行:

cargo doc --open

Cargo 会生成 HTML 文档并自动在浏览器中打开。你可以在文档中看到函数说明和示例代码,极大提升代码可读性。

高级用法与最佳实践

随着项目规模扩大,Cargo 的高级功能就显得尤为重要。以下是几个关键技巧:

1. 使用工作区(Workspace)管理多个包

当项目包含多个子模块时,可以使用工作区。创建一个 Cargo.toml 作为根文件:

[workspace]
members = [
    "crate_a",
    "crate_b",
]

然后在根目录下创建 crate_a/crate_b/ 子目录,每个目录都包含自己的 Cargo.toml

2. 自定义构建脚本

Cargo.toml 中添加:

[package]
build = "build.rs"

然后编写 build.rs 文件,用于执行编译前的准备工作,如生成代码或拷贝资源。

3. 使用环境变量控制编译

Cargo.toml 中可以设置条件编译:

[features]
default = []
debug = []

[dependencies]
log = { version = "0.4", optional = true }

通过 cargo build --features debug 启用特定功能。

4. 发布到 crates.io

当你准备好发布一个库时,确保 Cargo.toml 中的信息完整,然后运行:

cargo publish

这会将你的包上传到 crates.io,供他人使用。

总结

通过本篇 Cargo 教程,你已经掌握了从项目创建、依赖管理、构建运行,到测试文档生成的全流程。Cargo 不仅是工具,更是一种开发哲学:让开发者专注于解决问题,而不是被构建流程困扰。

无论你是刚接触 Rust 的新手,还是希望提升开发效率的中级开发者,深入理解 Cargo 都能让你的开发之路更加顺畅。它就像一位隐形的助手,默默帮你处理所有繁琐的细节,让你专注于创造价值。

现在,就动手试试吧。创建你的第一个 Cargo 项目,体验 Rust 开发的高效与优雅。