Rust: Cargo Workspaces 多项目(即 Monorepo)

Rust: Cargo Workspaces 多项目(即 Monorepo)

Workspaces?Monorepo?

作为一个前端人,相信大家对于近期越来越火的 monorepo 都略有耳闻,从 lerna、yarn workspaces、pnpm 等,实际上这样的概念在后端也是一样的。

今天要介绍的 Cargo Workspaces 就是对于 Rust 开发下提供官方级别的 monorepo 实践方式,我们使用的官方工具 cargo 自带的功能,其称为 Workspaces

Cargo Workspace 特征

workspaces 与 monorepo 其实几乎可以说是一样,不外乎就是把多个关联的项目统统放到同一个项目下;然而这与子项目的概念是不同的,大多数的实现主要用于一次构建多个平行、顶级的包作为独立模块,当然你用 Workspace 的时候定义一个对外暴露的主包,并用它来关联其他包也是可以的。

不过最重要的一个特征就是,在 workspaces 下每个包都应该是能够独立运行的个体,能够除了本项目以外的项目引入并运行

除了这些之外,cargo worksapces 还提出了其它约束如共同依赖包版本应该一致能,算是比较琐碎的规范,有兴趣可以看看官方介绍

项目实践

接下来带大家用一用这个 Cargo Workspaces(官方的文档真的写得很好,跟着走一遍就懂了)

项目结构

在开始之前我们先来看看最终产物的项目结构

/rust_workspaces
├── Cargo.lock
├── Cargo.toml
└── crates
    ├── add-one
    │   ├── Cargo.toml
    │   └── src
    │       └── lib.rs
    ├── add-two
    │   ├── Cargo.toml
    │   └── src
    │       └── lib.rs
    └── adder
        ├── Cargo.toml
        └── src
            └── main.rs

本篇的最终产物会有三个包,分别是 adderadd-oneadd-two,其中 adder 又依赖了其余两个包;全部三个包都放到 crates 目录下(当然你想放哪都行的),整个项目作为一个整体放到一个仓库进行管理

项目构建

接下来我们来看看如何构建一个如上的 cargo workspaces 多模块(或说多包)项目,实际上跟你原本用 cargo 的方式一模一样!

构建项目

首先先把三个小项目都建起来

# 目录结构
mkdir rust_workspaces
cd rust_workspaces
mkdir crates
cd crates
# 构建三个包
cargo new adder --lib
cargo new add-one --lib
cargo new add-two --lib

没错就是这么粗暴

根目录配置文件 Cargo.toml

我们知道通常一个由 Cargo 管理的 rust 项目,最主要的配置文件就是 Cargo.toml;一个 workspaces 项目也是一样的

  • 创建配置文件
touch Cargo.toml
  • 编辑配置文件

这里与我们通常熟悉的部分就不同了,我们不需要填哪些正常项目或是包应该要填的东西,只需要一个 workspace 属性,声明当前 workspaces 都有哪些项目就可以了!

  • /Cargo.toml
[workspace]
members = [
    "crates/adder",
    "crates/add-one",
    "crates/add-two",
]

可以看到实际上就是指定每一个项目根目录就可以了,所以其实你也可以直接平铺在项目根目录下,而不用放到什么 crates 目录下

声明依赖

前面我们提过 adder 包需要依赖另外两个包,但是根目录下的 Cargo.toml 只会识别当前 workspaces 下的项目,而无法知道你到底想要怎样的依赖关系

这其实也好解决,分别在每个项目下自己的 Cargo.toml 定义好自己的依赖关系就可以了

  • /crates/adder/Cargo.toml
[package]
name = "adder"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
add-one = { path = "../add-one" }
add-two = { path = "../add-two" }

项目功能填充

接下来我们稍微填充一下各个项目的内容代码

  • /crates/add-one/src/lib.rs
pub fn add_one(x: i32) -> i32 {
    x + 1
}
  • /crates/add-two/src/lib.rs
pub fn add_two(x: i32) -> i32 {
    x + 2
}
  • /crates/adder/src/main.rs
use {add_one, add_two};

fn main() {
    let num = 10;
    println!("Hello, world! {} + 1 = {}", num, add_one::add_one(num));
    println!("Hello, world! {} + 2 = {}", num, add_two::add_two(num));
}

打包运行

最后你可能会疑惑,那我们该怎样运行呢?我们只需要在根目录下进行打包,Cargo 就会自动识别,将最终产物统一构建在根目录的 /target 目录下,甚至我们进入到单个项目的根目录下运行相同指令也是一样的效果,不会产生多余的 target 目录

# 当前在根目录,也就是 rust_workspaces 目录下
pwd  # ~/rust_workspaces

cargo build  # 打包项目(可以省略)
cargo run --bin adder  # 指定运行 adder 项目(adder 是一个 bin 项目)
  • 最终结果
   Compiling adder v0.1.0 (~/rust_workspaces/crates/adder)
    Finished dev [unoptimized + debuginfo] target(s) in 0.53s
     Running `target/debug/adder`
Hello, world! 10 + 1 = 11
Hello, world! 10 + 2 = 12

小结

如果读者有兴趣可以去找找一些开源库来看看,现在 workspaces 或是说 monorepo 的概念其实已经在 rust 的社区广泛被采纳,写一些自己的小项目的时候也可以上手用看看,非常不错。(重点是集成的很好,体验极佳,跟某 lernx、什么 yar? wor!space 不一样)

其他资源

参考连接

TitleLink
Cargo Workspaces - The Rust Programming Languagehttps://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html

完整代码示例

https://github.com/superfreeeee/Blog-code/tree/main/back_end/rust/rust_workspaces

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值