Skip to content

32.1 cargo

Cargo 是 Rust 的包管理工具,是随着编译器一起发布的。在使用 rustup 安装了官方发布的 Rust 开发套装之后,Cargo 工具就已经安装好了,无须单独安装。我们可以使用 cargo 命令来查看它的基本用法。

Cargo 可以用于创建和管理项目、编译、执行、测试、管理外部下载的包和可执行文件等。

下面我们使用 cargo 来创建一个项目,一步步带领大家学习 cargo 的基本用法。

我们创建一个新的工程,这个工程会生成一个可执行程序。 步骤如下:

(1)进入项目文件夹后,使用如下命令:

sh
cargo new hello_world

# 在当前目录新建项目
cargo init

默认生成的是可执行程序,cargo 会帮助我们生成一个具有 git 版本控制的项目,其中 src/main.rs 的模板文件,它是程序的入口。

如果我们的工程是一个 library,则可以使用 --lib 选项,自动生成一个 lib.rs 的模板文件。

一个包可以包含任意多的二进制 crate,但最多只能包含一个库 crate。反正至少得包含其中一种。 如果一个包同时包含 src/main.rssrc/lib.rs,那么它就有两个 crate:一个二进制文件和一个库,且两者都与包同名。一个包可以在 src/bin 目录中存在多个二进制 crate,每个文件都是一个单独的二进制 crate。

(2)使用 tree . 命令查看当前的文件夹结构。可以看到:

sh
.
└── hello_world
    ├── .git
    ├── .gitignore
    ├── Cargo.lock
    ├── Cargo.toml
    └── target
    └── src
        └── main.rs

其中,Cargo.toml 是我们的项目管理配置文件,这里记录了该项目相关的元信息。关于这个文件的详细格式定义,可以参考官方文档

src 文件夹内是源代码。

(3)进入 hello_world 文件夹,使用 cargo build命令,编译项目。生成的可执行文件在 ./target/debug/ 文件夹内。如果我们使用 cargo build --release 命令,则可以生成 release 版的可执行文件,它比 debug 版本优化得更好。

(4)使用 ./target/debug/hello_world 命令,或者cargo run命令,可以执行我们刚生成的这个可执行程序。

在 Rust 中,一个项目对应着一个目标文件,可能是 library,也可能是可执行程序。现在我们试试给我们的程序添加依赖项目。

进入hello_world的上一层文件夹,新建一个 library 项目:

sh
cargo new --lib good_bye

lib.rs文件是库项目的入口,打开这个文件,写入以下代码:

rust
pub fn say() {
    println!("good bye");
}

使用 cargo build,编译通过。现在我们希望 hello_world 项目能引用 good_bye 项目。 打开 hello_world 项目的 Cargo.toml 文件,在依赖项下面添加对 good_bye 的引用。

toml
[dependencies]
good_bye = { path = "../good_bye" }

这个写法是引用本地路径中的库。如果要引用官方仓库中的库更简单,比如:

toml
[dependencies]
lazy_static = "1.0.0"

现在在应用程序中调用这个库。 打开main.rs源文件,修改代码为:

rust
use good_bye;

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

再次使用 cargo run 编译执行,就可以看到我们正确调用了good_bye项目中的代码。

cargo yank

Crates.io 的一个主要目标是永久存档所有代码库,以便所有依赖于 crates.io 上的 crate 的项目在任何时候都能正常构建成功。

因为发布到 Crates.io 上的代码,不能被覆盖、删除,只可以通过 “yanking”(撤回)来标记它不可用,这样未来的项目就不会自动选择这个版本。

对于已经依赖了被 yank 版本的现有项目,只要它们有一个 Cargo.lock 文件锁定了那个版本,它们仍然可以构建和运行。Cargo.lock 文件记录了项目构建时使用的确切依赖版本,因此即使这些版本被 yank,只要它们已经被锁定,项目就不会受到影响。

所以我们在运行 cargo publish 进行发布时,确保我们已经准备好了。

举个例子,假如我们发布了一个名为 guessing_game 版本号为 1.0.1 的 crate,并且想要将其撤销,在 guessing_game 项目目录中我们会运行:

sh
$ cargo yank --vers 1.0.1
    Updating crates.io index
        Yank guessing_game@1.0.1

# 撤消 yank
$ cargo yank --vers 1.0.1 --undo

cargo install

从 crates.io 下载二进制工具到 $HOME/.cargo/bin 路径下,当然了,要确保该路径在 $PATH 中。

Cargo 的设计初衷是,你可以通过添加新的子命令来扩展其功能,而无需修改 Cargo 本身。如果你的 $PATH 中的一个二进制文件名为 cargo-something,你可以通过运行 cargo something 来将其当作 Cargo 的子命令来执行。 能够使用 cargo install 安装扩展,然后像使用内置的 Cargo 工具一样运行它们,是 Cargo 设计的超级便捷的优点!

运行 cargo --list 时,像这样的自定义命令也会被列出。

更多 cargo 用法

cargo 只是一个包管理工具,并不是编译器。Rust 的编译器是rustc,使用 cargo 编译工程实际上最后还是调用的 rustc 来完成的。 如果我们想知道 cargo 在后面是如何调用 rustc 完成编译的,可以使用 cargo build --verbose 选项查看详细的编译命令。

cargo 在 Rust 的生态系统中扮演着非常重要的角色。除了最常用的 cargo newcargo buildcargo b)、cargo runcargo r)等命令之外,还有很多有用的命令。

我们可以用 cargo -h 来查看其他用法,如果想查看某个命令的具体用法,可以使用 cargo help new

现在挑选一部分给大家介绍:

命令解释
add添加 依赖项 到项目的Cargo.toml
--help [COMMAND]显示指定命令的帮助信息
--verbose启用详细输出,使用cargo -vv获得更详细的输出
--locked--frozen要求Cargo.lock是最新的
cargo --color WHEN启用颜色: always,auto 或者 never
+toolchain用指定的工具链覆盖当前的工具链(例如:cargo +nightly切换到 nightly 工具链)
bench执行 Rust 项目的基准测试
checkccheck命令可以只检查编译错误,而不做代码优化以及生成可执行程序,非常适合在开发过程中快速检查语法、类型错误
clean清理以前的编译结果
doc生成该项目的文档
testt执行单元测试
bench执行 benchmark 性能测试
update升级所有依赖项的版本,重新生成Cargo.lock文件
install安装可执行程序,例如 cargo install felix 之后,就可以使用了fx
install --list查看所有已安装的工具包
uninstall删除可执行程序
login登录 crate.io 帐户
publish将包发布到 crate.io
owner管理 crate 的拥有者(通过使用--add添加拥有者)

crates.io 网站上,用 subcommand 关键字可以搜出许多有用的子命令,用户可以按需安装。

Released under the MIT License