# 包与代码箱

**Packages and Crates**


我们要介绍的模块系统的头两个部分，是包与代码箱。

*代码箱，crate* 是 Rust 编译器一次要考虑的最小代码量。即使咱们运行的是 `rustc` 而不是 `cargo`，并只传递了一个源代码文件（就像我们在第 1 章 “编写和运行 Rust 程序” 小节中所做的那样），编译器也会将该文件，视为一个代码箱。代码箱可以包含模组，模组也可以定义在与该代码箱一起编译的其他文件中，正如我们将在接下来的小节中看到的那样。

代码箱有两种形式：二进制代码箱或库代码箱。*二进制板条箱，binary creates* 属于可以编译成咱们可以运行的可执行文件的程序，例如命令行程序或服务器。每个二进制代码箱，都必须有个名为 `main` 的函数，定义出可执行文件运行时会发生什么。到目前为止，我们创建的所有代码箱，都是二进制代码箱。

*库代码箱，library crates* 没有 `main` 函数，也不会编译成可执行文件。相反，他们定义了旨在与多个项目共享的功能。例如，我们在 [第 2 章](../Ch02_Programming_a_Guessing_Game.md#生成随机数) 中，使用的 `rand` 代码箱，就提供了生成随机数的功能。大多数时候，当 Rustaceans 说 “代码箱，crate” 时，他们指的是库代码箱，而且他们会将 “代码箱”，与一般的编程概念 “库，library” 互换使用。

而 *代码箱根，crate root*，则是个 Rust 编译器开始之处的源代码文件，并构成了咱们代码箱的 *根模组，root module*（我们将在 [定义控制作用域和隐私的模组](/packages_crates_and_modules/defining_modules.md) 小节，深入探讨模组）。

*包，package* 是提供了一组功能的一或多个代码箱的捆绑。包会包含一个描述如何构建这些代码箱的 `Cargo.toml` 文件。Cargo 实际上就是个包含了，咱们用来构建代码的命令行工具的包。Cargo 包还包含该二进制代码箱所依赖的库代码箱。其他项目可以依赖于 Cargo 的库代码箱，使用与 Cargo 这个命令行工具，所使用的同样逻辑。

一个包可以包含任意数量的二进制代码箱，但最多只能包含一个库代码箱。一个包必须至少包含一个代码箱，无论是库代码箱，还是二进制代码箱。

我们来看看，在我们创建某个软件包时，会发生什么。首先，我们输入命令 `cargo new`：


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


运行 `cargo new` 后，我们使用 `ls` 查看 Cargo 创建了什么。在该项目目录中，有个 `Cargo.toml` 文件，给到我们一个包。还有个包含了 `main.rs` 的 `src` 目录。请用咱们的文本编辑器，打开 `Cargo.toml`，注意其中没有提到 `src/main.rs`。Cargo 遵循，`src/main.rs` 是与该软件包同名的二进制代码箱的代码箱根，这一惯例。同样，Cargo 知道，如果包目录中包含 `src/lib.rs`，那么该包中就包含一个，与该包同名的库代码箱，而 `src/lib.rs` 就是其代码箱根。Cargo 会将代码箱根文件，传递给 `rustc` 以构建出该库或二进制程序。

这里，我们有着一个只包含 `src/main.rs` 的包，意味着他只包含一个名为 `my-project` 的二进制代码箱。如果某个包包含 `src/main.rs` 和 `src/lib.rs`，那么他就有两个代码箱：一个二进制代码箱和一个库代码箱，且两个代码箱都有着与该包同样的名字。通过在 `src/bin` 目录中放置一些文件，包可以有多个二进制代码箱：每个文件都将是个单独的二进制代码箱。
