包与代码箱
Packages and Crates
我们要介绍的模块系统的头两个部分,是包与代码箱。
代码箱,crate 是 Rust 编译器一次要考虑的最小代码量。即使咱们运行的是 rustc
而不是 cargo
,并只传递了一个源代码文件(就像我们在第 1 章 “编写和运行 Rust 程序” 小节中所做的那样),编译器也会将该文件,视为一个代码箱。代码箱可以包含模组,模组也可以定义在与该代码箱一起编译的其他文件中,正如我们将在接下来的小节中看到的那样。
代码箱有两种形式:二进制代码箱或库代码箱。二进制板条箱,binary creates 属于可以编译成咱们可以运行的可执行文件的程序,例如命令行程序或服务器。每个二进制代码箱,都必须有个名为 main
的函数,定义出可执行文件运行时会发生什么。到目前为止,我们创建的所有代码箱,都是二进制代码箱。
库代码箱,library crates 没有 main
函数,也不会编译成可执行文件。相反,他们定义了旨在与多个项目共享的功能。例如,我们在 第 2 章 中,使用的 rand
代码箱,就提供了生成随机数的功能。大多数时候,当 Rustaceans 说 “代码箱,crate” 时,他们指的是库代码箱,而且他们会将 “代码箱”,与一般的编程概念 “库,library” 互换使用。
而 代码箱根,crate root,则是个 Rust 编译器开始之处的源代码文件,并构成了咱们代码箱的 根模组,root module(我们将在 定义控制作用域和隐私的模组 小节,深入探讨模组)。
包,package 是提供了一组功能的一或多个代码箱的捆绑。包会包含一个描述如何构建这些代码箱的 Cargo.toml
文件。Cargo 实际上就是个包含了,咱们用来构建代码的命令行工具的包。Cargo 包还包含该二进制代码箱所依赖的库代码箱。其他项目可以依赖于 Cargo 的库代码箱,使用与 Cargo 这个命令行工具,所使用的同样逻辑。
一个包可以包含任意数量的二进制代码箱,但最多只能包含一个库代码箱。一个包必须至少包含一个代码箱,无论是库代码箱,还是二进制代码箱。
我们来看看,在我们创建某个软件包时,会发生什么。首先,我们输入命令 cargo new
:
$ 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
目录中放置一些文件,包可以有多个二进制代码箱:每个文件都将是个单独的二进制代码箱。