软件包和板条箱


我们将介绍的模块系统的第一部分是 package 和 crate。


crate 是 Rust 编译器一次考虑的最小代码量。即使你运行 rustc 而不是 cargo 并传递一个源代码文件(就像我们在第 1 章的 “编写和运行 Rust 程序” 一节中所做的那样),编译器也会认为该文件是一个 crate。crate 可以包含模块,并且这些模块可以在使用 crate 编译的其他文件中定义,我们将在后面的章节中看到。


crate 可以有两种形式之一:二进制 crate 或库 crate。 Binary crate 是你可以编译成可以运行的可执行文件的程序, 例如命令行程序或服务器。每个 API 都必须有一个名为 main 定义可执行文件运行时发生的情况。到目前为止,我们创建的所有 crate 都是二进制 crate。


库 crate 没有 main 函数,它们不会编译为可执行文件。相反,它们定义了要与多个项目共享的功能。例如,我们在章节中使用的 rand crate 2 提供生成随机数的功能。大多数时候,当 Rustacean 说 “crate” 时,他们指的是 library crate,并且他们将 “crate” 与 “library” 的一般编程概念互换使用。


crate 根是 Rust 编译器从源文件开始并生成的 上 crate 的根模块(我们将在 “定义模块以控制范围和隐私” 部分)。


软件包是一个或多个 crate 的捆绑包,可提供一组功能。一个包包含一个 Cargo.toml 文件,该文件描述了如何构建这些 crate。Cargo 实际上是一个包,其中包含您用于构建代码的命令行工具的二进制 crate。Cargo 包还包含二进制 crate 所依赖的库 crate。其他项目可以依赖 Cargo 库 crate 来使用 Cargo 命令行工具使用的相同逻辑。一个包可以包含任意数量的二进制 crate,但最多只能包含一个库 crate。一个包必须至少包含一个 crate,无论是库还是二进制 crate。


让我们来看看创建 package 时会发生什么。首先,我们输入命令 cargo new my-project

$ cargo new my-project
     Created binary (application) `my-project` package
$ ls my-project
Cargo.toml
src
$ ls my-project/src
main.rs


在我们运行 cargo new my-project 之后,我们使用 ls 来查看 Cargo 创建的内容。在项目目录中,有一个 Cargo.toml 文件,为我们提供了一个包。还有一个包含 main.rssrc 目录。在文本编辑器中打开 Cargo.toml,请注意没有提到 src/main.rs。Cargo 遵循一个约定,即 src/main.rs 是与包同名的二进制 crate 的 crate 根。同样,Cargo 知道如果 package 目录包含 src/lib.rs,则该 package 包含一个与该 package 同名的库 crate,而 src/lib.rs 是其 crate 根。Cargo 将 crate 根文件传递给 rustc 以构建库或二进制文件。


在这里,我们有一个只包含 src/main.rs 的包,这意味着它只包含一个名为 my-project 的二进制 crate。如果软件包包含 src/main.rssrc/lib.rs,它有两个 crate:一个 binary 和一个 library,它们都与包同名。通过将文件放在 src/bin 目录中,一个包可以有多个二进制 crate:每个文件将是一个单独的二进制 crate。