包管理与模块
Rust中的Cargo提供了类似Node中NPM的能力,包括项目的初始化、模块的安装与管理、便捷的脚本命令等功能。
命令
cargo new
cargo new <xxx> # create bin template project
cargo new <xxx> --lib # create lib template project
cargo build
cargo build # build all binary crates
cargo build --bin <xxx> # build specific binary crate
cargo run
cargo run # build and running, 要求只存在一个binary crate
cargo run --bin <xxx> # build and running
cargo publish
在我们发布我们的Rust包前,我们首先需要通过cargo login
进行本机登录,再通过cargo publish
进行发布。
cargo install
通常我们通过cargo install
来安装别人发布的二进制包,拉下代码后会自动通过cargo build --release
构建可执行文件。
Binary/Library Crate
Cargo.toml
所处的根目录被我们视为一个Rust项目(或者叫Rust包),每个Rust项目通常由一个或多个Crate组成,其中包含最多一个的Library Crate和可以存在多个的Binary Crate。
在默认情况下,src/main.rs
文件会被视为一个Binary Crate的入口,该入口文件中需要实现main
函数,这个Crate的名称默认为Rust包的名称;而src/lib.rs
会被视为Library Crate的入口,Crate名也同样为Rust包的名称。通过修改Cargo.toml
配置,我们可以指定Crate的名称和入口文件的路径。
对于上图的Rust项目,我们能够清晰的看到存在着一个Library Crate(名称为akara,路径为src/other_file.rs
)和三个Binary Crate(名称分别为akara、one和two),此时我们的cargo build
和cargo run
命令需要通过--lib <xxx>
来指定Crate的名称。
模块化
在上文中我们介绍了Rust包中可以同时包含多个Crate,而每个Crate都可以被视为一棵模块树,上文提到的src/main.rs
、src/lib.rs
则为对应的模块树的入口文件。我们可以在入口文件中声明函数乃至模块,来扩充整个模块树的内容。
为了演示,我们可以在入口文件src/lib.rs
中声明三个函数One
、Two
、Three
,那么此时整个模块树的结构如下:
crate
- One
- Two
- Three
可以看到模块树的根部用关键字crate
来表示,此时我们的结构是扁平的,通过在入口文件src/lib.rs
中使用mod
关键字声明模块,比如在我们的例子中我使用mod Apple
来声明模块Apple,编译器会根据一定的优先级来寻找该模块并加入到我们的模块树当中。
寻找本文件中是否存在对应的内联模块,比如:
mod Apple {
pub fn A() {
println!("A");
}
pub fn B() {
println!("B");
}
pub fn C() {
println!("C");
}
}寻找同目录下是否存在
src/Apple.rs
文件寻找同目录下是否存在
src/Apple/mod.rs
文件
此时,我们的模块树演变成了如下结构,我们可以在代码中通过形如crate::Apple::B
的方式来引用模块中的任意公开内容,这里的crate
关键字表示我们自身的Crate,我们也可以使用std::fs::read
的方式来引用第三方模块,甚至我们可以通过我们项目的包名来引用项目中Library Crate的内容,比如akara::utils::xxx
crate
- One
- Two
- Three
- Apple
- A
- B
- C
隐私规则
在上一节中我们介绍了Rust的模块化规则,当然并不是模块中的所有内容都可以被其他模块引用,我们需要在这些内容的声明前添加添加pub
前缀,比如:
pub fn hello() {}
pub mod Apple;
use关键字
在模块化一节中我们还介绍了通过类似crate::Apple::B
的形式来引用某个Crate模块树中的某个值,但这个值需要在多个地方中使用的话这么写会显得有些繁琐,所以Rust提供了关键字use
来帮助我们简化使用的流程。
mod Apple;
use crate::Apple::B;
fn main() {
B();
B();
B();
}