Rust 学习笔记(三)Hello, Cargo!
Hello, Cargo!
Cargo 是 Rust 的构建系统和包管理器。大多数 Rustaceans(Rust 程序员)使用这个工具来管理他们的 Rust 项目,因为 Cargo 为你处理了很多任务,比如构建你的代码、下载你的代码所依赖的库,并构建这些库。(我们把你的代码需要的库称为依赖项。)
像我们之前写的最简单的 Rust 程序,没有依赖项。如果我们用 Cargo 来构建“Hello, world!”项目,它只会使用 Cargo 中处理构建代码的部分。随着你编写更复杂的 Rust 程序,你会添加依赖项,如果你从一开始就使用 Cargo 开始一个项目,添加依赖项会更容易。
因为绝大多数 Rust 项目都使用 Cargo,所以本书的其余部分都假设你也使用 Cargo。如果你使用官方安装程序安装了 Rust(如“安装”部分所讨论的),Cargo 会随 Rust 一起安装。如果你通过其他方式安装了 Rust,可以通过在终端中输入以下命令来检查是否安装了 Cargo:
1 | $ cargo --version |
如果你看到了版本号,那么你已经安装了!如果你看到了错误,比如command not found
,请查看你的安装方法的文档,以确定如何单独安装 Cargo。
使用 Cargo 创建项目
让我们使用 Cargo 创建一个新项目,并看看它与我们原来的“Hello, world!”项目有什么不同。回到你的projects
目录(或者你决定存放代码的任何地方)。然后,在任何操作系统上,运行以下命令:
1 | $ cargo new hello_cargo |
第一个命令创建了一个名为hello_cargo
的新目录和项目。我们把项目命名为hello_cargo
,Cargo 会在同名的目录中创建它的文件。
进入hello_cargo
目录并列出文件。你会看到 Cargo 为我们生成了两个文件和一个目录:一个Cargo.toml
文件和一个src
目录,里面有一个main.rs
文件。
它还初始化了一个新的 Git 仓库,以及一个.gitignore
文件。如果你在现有的 Git 仓库中运行cargo new
,则不会生成 Git 文件;你可以通过使用cargo new --vcs=git
来覆盖这种行为。
注意:Git 是一个常见的版本控制系统。你可以通过使用--vcs
标志来改变cargo new
使用不同的版本控制系统或不使用版本控制系统。运行cargo new --help
以查看可用选项。
在你选择的文本编辑器中打开Cargo.toml
。它应该看起来类似于清单 1-2 中的代码。
文件名:Cargo.toml
1 | [package] |
清单 1-2:由cargo new
生成的Cargo.toml
的内容
这个文件是用**TOML(Tom’s Obvious, Minimal Language)**格式的,这是 Cargo 的配置格式。
第一行,[package]
,是一个节标题,表明接下来的语句是配置一个包的。随着我们向这个文件添加更多信息,我们会添加其他节。
接下来的三行设置了 Cargo 编译你的程序所需的配置信息:名称、版本和要使用的 Rust 版本。我们将在附录 E 中讨论edition
键。
最后一行,[dependencies]
,是开始列出你的项目依赖项的部分。在 Rust 中,代码包被称为crate。这个项目我们不需要其他 crate,但在第 2 章的第一个项目中我们会用到,所以那时我们会使用这个依赖项部分。
现在打开src/main.rs
看看:
文件名:src/main.rs
1 | fn main() { |
Cargo 为你生成了一个“Hello, world!”程序,就像我们在清单 1-1 中写的那样!到目前为止,我们的项目和 Cargo 生成的项目之间的区别在于 Cargo 把代码放在了src
目录中,而且我们在顶层目录有一个Cargo.toml
配置文件。
Cargo 期望你的源文件位于src
目录中。顶层项目目录只是用于 README 文件、许可证信息、配置文件以及任何与你的代码无关的东西。使用 Cargo 有助于你组织你的项目。每个东西都有它该在的地方,而且每个东西都在它该在的地方。
如果你开始了一个不使用 Cargo 的项目,就像我们之前做的“Hello, world!”项目一样,你可以将它转换为一个使用 Cargo 的项目。把项目代码移到src
目录中,并创建一个合适的Cargo.toml
文件。一个简单的方法是运行cargo init
,它会自动为你创建Cargo.toml
文件。
构建和运行 Cargo 项目
现在我们来看看使用 Cargo 构建和运行“Hello, world!”程序有什么不同!从你的hello_cargo
目录中,通过输入以下命令来构建你的项目:
1 | $ cargo build |
这个命令会在target/debug/hello_cargo
(在 Windows 上是target\debug\hello_cargo.exe
)而不是当前目录中创建一个可执行文件。因为默认构建是一个调试构建,Cargo 把二进制文件放在一个名为debug
的目录中。你可以通过以下命令运行可执行文件:
1 | $ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows |
如果一切顺利,Hello, world!
应该会打印到终端上。第一次运行cargo build
还会导致 Cargo 在顶层创建一个新文件:Cargo.lock
。这个文件跟踪你的项目中依赖项的确切版本。这个项目没有依赖项,所以文件内容比较少。你不需要手动更改这个文件;Cargo 会为你管理它的内容。
我们刚刚用cargo build
构建了一个项目,并用./target/debug/hello_cargo
运行了它,但我们也可以使用cargo run
来编译代码,然后运行生成的可执行文件,所有这些都在一个命令中完成:
1 | $ cargo run |
使用cargo run
比记住要运行cargo build
,然后使用整个路径来运行二进制文件更方便,所以大多数开发人员使用cargo run
。
注意,这次我们没有看到 Cargo 正在编译hello_cargo
的输出。Cargo 发现文件没有改变,所以它没有重新构建,只是运行了二进制文件。如果你修改了你的源代码,Cargo 会在运行之前重新构建项目,你会看到这样的输出:
1 | $ cargo run |
Cargo 还提供了一个名为cargo check
的命令。这个命令快速检查你的代码,确保它能够编译,但不会生成可执行文件:
1 | $ cargo check |
为什么你不需要可执行文件呢?通常,cargo check
比cargo build
要快得多,因为它跳过了生成可执行文件的步骤。如果你在编写代码时不断检查你的工作,使用cargo check
会加快让你知道你的项目是否仍然可以编译的过程!因此,许多 Rustaceans 在编写程序时会定期运行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 build --release
,并使用target/release
中的可执行文件进行基准测试。
Cargo 作为一种约定
对于简单的项目,Cargo 并没有比直接使用rustc
提供太多价值,但随着你的程序变得越来越复杂,它将证明自己的价值。一旦程序增长到多个文件或需要一个依赖项时,让 Cargo 协调构建会容易得多。
尽管hello_cargo
项目很简单,但它现在使用了你将在整个 Rust 职业生涯中使用的大部分真实工具。实际上,要参与任何现有项目,你可以使用以下命令通过 Git 检出代码,切换到该项目的目录,并进行构建:
1 | git clone example.org/someproject |
有关 Cargo 的更多信息,请查看它的文档。
总结
你的 Rust 之旅已经取得了良好的开端!在本章中,你已经学会了如何:
- 使用
rustup
安装最新稳定版本的 Rust - 更新到更新的 Rust 版本
- 打开本地安装的文档
- 使用
rustc
直接编写和运行“Hello, world!”程序 - 使用 Cargo 的约定创建和运行一个新项目
现在正是构建一个更复杂的程序以熟悉阅读和编写 Rust 代码的好时机。因此,在第 2 章中,我们将构建一个猜数字游戏程序。如果你更愿意先了解 Rust 中的常见编程概念,可以先阅读第 3 章,然后再回到第 2 章。