喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)
14.4.1. 为什么需要cargo workspace
假如说我们构建了一个二进制crate,里面既有library又有库。随着项目规模不断增长,库crate可能不断变大。在这种情况下通常会把它拆为多个包,针对这种需求,Rust提供了cargo工作空间,也就是cargo workspace。
cargo workspace会帮助管理多个相互关联且需要协同开发的crate。其本质是一套共享同一个Cargo.lock
和输出文件的包。
14.4.2. 使用workspace
有多种方式可以创建工作空间(workspace)。
做一个例子,这个工作空间里有1个二进制crate和1个库crate:
- 二进制crate里有
main
函数,依赖于库crate - 其中一个库crate提供一个叫
add_one
函数
1. 创建workspace目录
首先为工作空间创建一个目录,我取名叫add
,在终端输入:
$ mkdir add
$ cd add
2. 在主项目中使用workspace
接下来,在add
目录中,我们创建将配置整个工作区的Cargo.toml
文件。该文件不会有[package]
部分。相反,它将以[workspace]
部分开头:
[workspace]
members = [
"adder",
]
adder
就是我给二进制crate取的名,这个列表可以继续添加。
3. 添加库
$ cargo new adder
通过这个命令创建了adder
crate,在目录add/adder
下
此时整个项目的结构如下:
├── Cargo.lock
├── Cargo.toml
├── adder
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── target
需要注意的是,这时候我们既可以对add
这个项目使用cargo build
,也可以对add
下的adder
库使用cargo bulid
。但是生成的target
目录和Cargo.lock
文件只会有一个,在add
目录下,而adder
库使用cargo bulid
的产出物也会存放在这里。因为各个crate往往是相互依赖的,每个目录都有自己的target
就会导致开发者不得不反复编译工作空间里的其余crate。
接下来添加其它crate:
另一个crate叫add_one
,修改工作空间信息:
[workspace]
members = [
"adder",
"add_one",
]
使用cargo new
添加库,记得使用--lib
旗帜来把它声明为library crate:
$ cargo new add_one --lib
现在整个项目的结构是:
├── Cargo.lock
├── Cargo.toml
├── add_one
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
├── adder
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── target
4. 编写代码
在add_one/src/lib.rs
文件中,我们添加一个add_one
函数:
pub fn add_one(x: i32) -> i32 {
x + 1
}
现在我们可以让adder
包和我们的二进制文件依赖于add_one
。首先,我们需要添加路径依赖add_one
到adder/Cargo.toml
,因为Cargo并不假设工作区中的crate会相互依赖,因此我们需要明确依赖关系。在adder/Cargo.toml
中这么写:
[dependencies]
add_one = { path = "../add_one" }
接下来,让我们使用add_one
函数(来自add_one
crate)。打开adder/src/main.rs
文件并在顶部添加use
来把add_one
引入作用域,将新的add_one
库crate纳入范围。然后更改main
函数来调用add_one
函数。
use add_one;
fn main() {
let num = 10;
println!("Hello, world! {num} plus one is {}!", add_one::add_one(num));
}
5. 编译
对add
这个项目使用cargo build
:
$ cargo build
Compiling add_one v0.1.0 (file:///projects/add/add_one)
Compiling adder v0.1.0 (file:///projects/add/adder)
Finished dev [unoptimized + debuginfo] target(s) in 0.68s
没有报错,正常运行。
6. 测试
我们还可以通过使用-p
标志并指定我们要测试的包的名称,从顶级目录中对工作区中的一个特定包运行测试。比如说仅测试add_one
函数:
$ cargo test -p add_one
Finished test [unoptimized + debuginfo] target(s) in 0.00s
Running unittests src/lib.rs (target/debug/deps/add_one-b3235fea9a156f74)
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Doc-tests add_one
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
如果您将工作区中的 crate 发布到crates.io ,则工作区中的每个 crate 都需要单独发布。与cargo test
一样,我们可以使用-p
在工作区中发布特定的箱子标记并指定我们要发布的包的名称。