Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

你好,Cargo!

Cargo 是 Rust 的构建系统和包管理器。大多数 Rustacean 都用它来管理 Rust 项目,因为 Cargo 能替你处理许多任务,例如构建代码、下载代码依赖的库,以及构建这些库。(我们把代码所需的库称为依赖。)

最简单的 Rust 程序(例如我们目前编写的程序)没有任何依赖。如果我们使用 Cargo 构建“Hello, world!”项目,它只会用到 Cargo 中负责构建代码的部分。随着 Rust 程序变得更加复杂,你会添加依赖;如果一开始就使用 Cargo 创建项目,添加依赖会容易得多。

绝大多数 Rust 项目都使用 Cargo,因此本书后续内容也假设你会使用 Cargo。如果你使用“安装”一节介绍的官方安装程序,Cargo 会随 Rust 一起安装。如果你通过其他方式安装 Rust,请在终端中输入以下命令检查是否安装了 Cargo:

$ cargo --version

如果看到版本号,就说明已经安装!如果看到类似 command not found 的错误,请查阅所用安装方式的文档,了解如何单独安装 Cargo。

使用 Cargo 创建项目

让我们使用 Cargo 创建一个新项目,并看看它与最初的“Hello, world!”项目有何不同。回到你的 projects 目录(或你选择的代码存放位置),然后在任何操作系统上运行以下命令:

$ cargo new hello_cargo
$ cd hello_cargo

第一条命令会创建一个名为 hello_cargo 的新目录和项目。我们将项目命名为 hello_cargo,Cargo 也会在同名目录中创建项目文件。

进入 hello_cargo 目录并列出文件。你会看到 Cargo 为我们生成了两个文件和一个目录:一个 Cargo.toml 文件,以及一个包含 main.rs 文件的 src 目录。

它还初始化了一个新的 Git 仓库,并创建了 .gitignore 文件。如果在现有 Git 仓库中运行 cargo new,则不会生成 Git 文件;你可以使用 cargo new --vcs=git 覆盖此行为。

注意:Git 是一种常见的版本控制系统。你可以使用 --vcs 标志,让 cargo new 使用其他版本控制系统,或完全不使用版本控制系统。运行 cargo new --help 查看可用选项。

使用你选择的文本编辑器打开 Cargo.toml。其内容应与代码清单 1-2 类似。

文件名:Cargo.toml
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2024"

[dependencies]
代码清单 1-2:cargo new 生成的 Cargo.toml 内容

该文件采用 TOML(Tom 的明显、精简语言)格式,这是 Cargo 使用的配置格式。

第一行 [package] 是一个区段标题,表示后续语句用于配置一个包。随着我们向此文件添加更多信息,还会添加其他区段。

接下来的三行设置了 Cargo 编译程序所需的配置信息:名称、版本,以及要使用的 Rust 版本。我们会在附录 E讨论 edition 键。

最后一行 [dependencies] 是一个区段的开头,你可以在此列出项目依赖。在 Rust 中,代码包称为crate。本项目不需要其他 crate,但第 2 章的第一个项目会用到,因此到时我们会使用这个依赖区段。

现在打开 src/main.rs 看一看:

文件名:src/main.rs

fn main() {
    println!("Hello, world!");
}

Cargo 已为你生成了一个“Hello, world!”程序,就像我们在代码清单 1-1 中编写的那个!目前我们的项目与 Cargo 生成的项目之间的区别是:Cargo 将代码放在 src 目录中,并在顶层目录中提供了 Cargo.toml 配置文件。

Cargo 期望你的源文件位于 src 目录中。项目顶层目录则用于存放 README 文件、许可证信息、配置文件以及其他与代码无关的内容。使用 Cargo 有助于整理项目:每样东西都有自己的位置,而且各就其位。

如果你像之前创建“Hello, world!”项目那样,启动了一个没有使用 Cargo 的项目,也可以将它转换为 Cargo 项目。把项目代码移到 src 目录中,并创建适当的 Cargo.toml 文件。创建该文件的一个简单方法是运行 cargo init,它会自动为你生成。

构建并运行 Cargo 项目

现在来看看使用 Cargo 构建并运行“Hello, world!”程序有什么不同!在 hello_cargo 目录中输入以下命令来构建项目:

$ cargo build
   Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs

这条命令会在 target/debug/hello_cargo(Windows 上为 target\debug\hello_cargo.exe)中创建可执行文件,而不是放在当前目录中。由于默认构建类型是调试构建,Cargo 会将二进制文件放入名为 debug 的目录。你可以使用以下命令运行可执行文件:

$ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows
Hello, world!

如果一切顺利,终端应该会打印 Hello, world!。首次运行 cargo build 时,Cargo 还会在顶层目录中创建一个新文件:Cargo.lock。该文件会记录项目依赖的确切版本。此项目没有依赖,所以文件内容很少。你无需手动修改此文件;Cargo 会替你管理其内容。

我们刚刚用 cargo build 构建了项目,并用 ./target/debug/hello_cargo 运行它;也可以使用 cargo run,通过一条命令先编译代码,再运行生成的可执行文件:

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/hello_cargo`
Hello, world!

使用 cargo run 比记住先运行 cargo build、再输入二进制文件的完整路径更方便,因此大多数开发者都会使用 cargo run。

注意,这次没有看到 Cargo 正在编译 hello_cargo 的输出。Cargo 判断文件没有变化,因此没有重新构建,而是直接运行了二进制文件。如果你修改了源代码,Cargo 就会在运行前重新构建项目,并显示以下输出:

$ cargo run
   Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs
     Running `target/debug/hello_cargo`
Hello, world!

Cargo 还提供了名为 cargo check 的命令。它会快速检查代码能否编译,但不会生成可执行文件:

$ cargo check
   Checking hello_cargo v0.1.0 (file:///projects/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs

为什么不需要可执行文件?通常 cargo check 比 cargo build 快得多,因为它跳过了生成可执行文件这一步。如果你在编写代码时不断检查进度,使用 cargo check 就能更快地告诉你项目是否仍可编译!因此,许多 Rustacean 会在编写程序时定期运行 cargo check,确保程序能够编译;等到需要使用可执行文件时,再运行 cargo build。

让我们回顾一下目前学到的 Cargo 知识:

  • 可以使用 cargo new 创建项目。
  • 可以使用 cargo build 构建项目。
  • 可以使用 cargo run 一步完成项目构建与运行。
  • 可以使用 cargo check 检查错误而不生成二进制文件。
  • Cargo 不会将构建结果保存在代码所在目录,而是存放在 target/debug 目录中。

使用 Cargo 的另一个优点是,无论你使用哪种操作系统,命令都相同。因此从现在开始,我们不再分别提供适用于 Linux、macOS 和 Windows 的说明。

为发布版本构建

项目准备发布时,可以使用 cargo build --release 启用优化进行编译。这条命令会将可执行文件创建在 target/release 中,而不是 target/debug。优化会让 Rust 代码运行得更快,但也会延长编译时间。因此 Cargo 提供了两种配置:一种用于开发,便于快速且频繁地重新构建;另一种用于构建最终交付给用户的程序,该程序不需要反复重建,并会尽可能快速地运行。如果要测量代码的运行时间,请务必运行 cargo build --release,并使用 target/release 中的可执行文件进行基准测试。

利用 Cargo 的约定

对于简单项目,与直接使用 rustc 相比,Cargo 的优势并不明显;但随着程序日益复杂,它的价值就会体现出来。当程序包含多个文件或需要依赖时,让 Cargo 协调构建会容易得多。

虽然 hello_cargo 项目很简单,但它已经使用了你今后编写 Rust 程序时会接触到的大部分实际工具。事实上,要处理任何现有项目,都可以使用以下命令通过 Git 获取代码、进入项目目录并进行构建:

$ git clone example.org/someproject
$ cd someproject
$ cargo build

关于 Cargo 的更多信息,请参阅它的文档。

总结

你的 Rust 之旅已经有了很好的开端!在本章中,你学会了如何:

  • 使用 rustup 安装最新稳定版 Rust。
  • 更新到较新的 Rust 版本。
  • 打开本地安装的文档。
  • 直接使用 rustc 编写并运行“Hello, world!”程序。
  • 按照 Cargo 的约定创建并运行新项目。

现在正适合构建一个更完整的程序,熟悉 Rust 代码的阅读与编写。因此在第 2 章中,我们会构建一个猜数字游戏。如果你更愿意先了解常见编程概念在 Rust 中的用法,可以先阅读第 3 章,再回来学习第 2 章。