创建于2023-03-30 09:51
本笔记主要来自于 Rust 程序设计语言 中文版 [1.3],旨在记录个人学习过程中的重点和心得体会。在记录过程中,笔者会对文档中的某些内容进行摘抄或修改,并添加自己的注释或说明。如有不当之处,请指正。
Cargo 是 Rust 的构建系统和包管理器(有些类似MAVEN和YARN、PNPM + VITE/WEBPACK),大多数 rust 开发者都用它来管理 Rust 项目,因为他可以为你处理很多任务,比如构建代码、下载依赖库以及编译这些库。(代码所需要的库通常被叫做依赖)
一个最简单的 Rust 项目可能不包含任何依赖,所以如果使用 Cargo 来构建它,那么将只会使用到 Cargo 构建代码的那部分功能。我们在编写更复杂的 Rust 程序时,你将添加依赖想,如果使用 Cargo 启动项目,那么添加依赖项会变的得容易。
使用Cargo创建项目
我需要在我的项目文件夹创建我第一个 Cargo 项目,通过以下命令创建项目
# clover @ MacBook-Pro in ~/dev/rust/learn [10:13:17]
$ cargo new hello_cargo
Created binary (application) `hello_cargo` package
值得注意的是,通过 Cargo 创建的项目不能以数字开头
执行创建命令后,它会在我指定的地方创建 hello_cargo
,同时它还在这个文件夹里创建了一些基础的默认结构,例如一个 Cargo.toml
文件和一个 src
文件夹以及位于 src
文件夹中的 src/main.rs
文件。
同时它也在项目中初始化了 git 仓库和一个 .gitignore
文件。
# clover @ MacBook-Pro in ~/dev/rust/learn [10:14:03]
$ cd hello_cargo
# clover @ MacBook-Pro in ~/dev/rust/learn/hello_cargo on git:master x [10:16:41]
$ tree -a
.
├── .git
...
├── .gitignore
├── Cargo.toml
└── src
└── main.rs
10 directories, 8 files
如果需要在一个现有的 git 仓库执行 cargo new
,那么它不会生成 git 相关的产物。可以使用 cargo new --vcs=git
来覆盖它的默认行为。
Git 是一个常用的版本控制系统(version control system, VCS)。可以通过
--vcs
参数使cargo new
切换到其它版本控制系统,或者不使用 VCS。运行cargo new --help
查看可用的选项。
下面这段内容时 Cargo 生成的 Cargo.toml
默认内容
此文件使用 TOML (Tom's Obvious, Minimal Language) 格式,这是 Cargo 配置文件的格式。
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[package]
是一个表块(Section)标题,用来描述一个包(package)的详细信息。随着我们在这个表块添加更多信息,可能还需要添加一些其它表块。- 下面的三行设置了 Cargo 编译程序所需的配置:项目名称、版本和使用的 Rust 大版本号(version区别于edition,version描述的是当前项目的版本,而edition是rust的核心版本,目前为止,Rust的核心版本有:2015、2018、2021 版等)
- 最后一行
[dependencies]
是罗列项目依赖的表块的开始。在 Rust 中,代码包被称为 crate
该篇引用来自附录[21.5 E]
我们见过
cargo new
在 Cargo.toml 中增加了一些有关edition
的元数据。本附录将解释其意义!Rust 语言和编译器有一个为期 6 周的发布循环。这意味着用户会稳定得到新功能的更新。其他编程语言发布大更新但不甚频繁;Rust 选择更为频繁的发布小更新。一段时间之后,所有这些小更新会日积月累。不过随着小更新逐次的发布,或许很难回过头来感叹:“哇,从 Rust 1.10 到 Rust 1.31,Rust 的变化真大!”
每两到三年,Rust 团队会生成一个新的 Rust 版本(edition)。每一个版本会结合已经落地的功能,并提供一个清晰的带有完整更新文档和工具的功能包。新版本会作为常规的 6 周发布过程的一部分发布。
这为不同的人群提供了不同的功能:
- 对于活跃的 Rust 用户,其将增量的修改与易于理解的功能包相结合。
- 对于非用户,它表明发布了一些重大进展,这意味着 Rust 可能变得值得一试。
- 对于 Rust 自身开发者,其提供了项目整体的集合点。
在本文档编写时,Rust 有两个版本:Rust 2015 和 Rust 2018。本书基于 Rust 2018 edition 编写。
Cargo.toml 中的
edition
字段表明代码应该使用哪个版本编译。如果该字段不存在,其默认为2015
以提供后向兼容性。每个项目都可以选择不同于默认的 2015 edition 的版本。这样,版本可能会包含不兼容的修改,比如新增关键字可能会与代码中的标识符冲突并导致错误。不过除非选择兼容这些修改,(旧)代码仍将能够编译,即便升级了 Rust 编译器的版本。
所有 Rust 编译器都支持任何之前存在的编译器版本,并可以链接任何支持版本的 crate。编译器修改只影响最初的解析代码的过程。因此,如果你使用 Rust 2015 而某个依赖使用 Rust 2018,你的项目仍旧能够编译并使用该依赖。反之,若项目使用 Rust 2018 而依赖使用 Rust 2015 亦可工作。
有一点需要明确:大部分功能在所有版本中都能使用。开发者使用任何 Rust 版本将能继续接收最新稳定版的改进。然而在一些情况,主要是增加了新关键字的时候,则可能出现了只能用于新版本的功能。只需切换版本即可利用新版本的功能。
请查看 Edition Guide 了解更多细节,这是一个完全介绍版本的书籍,包括如何通过
cargo fix
自动将代码迁移到新版本。
以下是 Cargo 生成 src/main.rs
的默认代码
fn main() {
println!("Hello, world!");
}
它默认生成了一个通过 println!
输出 "Hello World" 的程序,和之前 hello_word 项目的区别是它将代码存放在 src 目录并且在同级生成了 Cargo.toml 配置文件。
和大多数 cli 一样,它希望我们将代码都放在 src 目录下,项目根目录只存放一些其它的资源文件或项目说明文件,例如:README、license 等其它与代码无关的文件,保持一个干净整洁的项目结构
对于没有使用 Cargo 创建的项目而现在希望使用 Cargo,只需要创建 src 目录并将代码移动到该目录,并创建一个 Cargo.toml 文件即可。
构建并运行 Cargo 项目
通过 Cargo 来编译项目
# clover @ MacBook-Pro in ~/dev/rust/learn/hello_cargo on git:master x [10:13:37]
$ cargo build
Compiling hello_cargo v0.1.0 (/Users/clover/dev/rust/learn/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 10.47s
cargo build
命令执行后会在 ./target/debug
目录下创建一个可执行文件 hello_cargo
(这在 windows 中是hello_cargo.exe
),对比之前 hello_world 项目,Cargo 的编译产物并不是存放在“当前”目录中。
如需运行,可以使用 cargo run
命令来操作,如果你 target/debug 目录中没有内容或者你的代码发生了改变,那么该命令会自动执行 build
操作,所以在我们开发的时候无需手动 build。
# clover @ MacBook-Pro in ~/dev/rust/learn/hello_cargo on git:master x [10:19:06]
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/hello_cargo`
Hello, world!
当然,也可以手动执行可执行文件,但更推荐使用 cargo run
的方式去编译和运行,因为它非常方便
# clover @ MacBook-Pro in ~/dev/rust/learn/hello_cargo on git:master x [10:19:54]
$ ./target/debug/hello_cargo
Hello, world!
在首次执行 cargo build
时,会在项目根目录创建一个 Cargo.lock 文件,这个文件用于记录项目依赖的实际版本,目前项目依赖较少,所以里面的内容记录不多。通常我们并不需要去理会这个文件,交给 Cargo 去操作就好。
Cargo 还提供了一个 cargo check
命令,它用于检查代码是否可以正常编译。与 cargo build
不同的是,它并不会产生任何可执行文件,所以它通常比 cargo build
要快很多。在发的时候,我们都需要对代码持续检查以保证第一时间修改错误,所以,cargo check
对我们的开发效率提升会很大。在我们需要使用可执行文件的时候才执行 cargo build
# clover @ MacBook-Pro in ~/dev/rust/learn/hello_cargo on git:master x [10:22:18]
$ cargo check
Checking hello_cargo v0.1.0 (/Users/clover/dev/rust/learn/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.65s
发布并构建
以下段落摘抄自[1.3]
"当项目最终准备好发布时,可以使用 cargo build --release
来优化编译项目。这会在 target/release 而不是 target/debug 下生成可执行文件。这些优化可以让 Rust 代码运行的更快,不过启用这些优化也需要消耗更长的编译时间。这也就是为什么会有两种不同的配置:一种是为了开发,你需要经常快速重新构建;另一种是为用户构建最终程序,它们不会经常重新构建,并且希望程序运行得越快越好。如果你要对代码运行时间进行基准测试,请确保运行 cargo build --release
并使用 target/release 下的可执行文件进行测试。"