超干货!大型 Rust 项目经验分享| Databend 与您共同进步

大型 Rust 项目工作空间

原文:https://matklad.github.io/2021/08/22/large-rust-workspaces.html

在本篇文章中,我将分享我组织大型 Rust 项目的经验。但这绝不是权威的,只是我通过尝试和错误中发现的一些小技巧。

Cargo,作为 Rust 的构建系统,遵循约定大于配置的原则。它不仅为小型项目提供了一套良好的默认配置集,尤其为公共 crates.io 库量身定做。虽然这些默认值并不完美,但它们已经足够用了。这对整个生态系统的一致性也是值得欢迎的。

然而当涉及到大型的、多 crate 的项目时,Cargo 就不那么统一了,它被组织成一个 Cargo 工作空间。而工作空间是灵活的 —— Cargo 对工作空间的布局并没有一个偏好统一。因此,人们会尝试不同的东西,取得不同程度的效果。

回到标题,我认为对于代码行数在一万到一百万之间的项目,扁平化结构是最为合理的。此处 rust-analyzer (多达 200k 行)是一个比较好的例子,它的项目组织如下:

rust-analyzer/
  Cargo.toml
  Cargo.lock
  crates/
    rust-analyzer/
    hir/
    hir_def/
    hir_ty/
    ...

在 repo 的根部,Cargo.toml 定义了一个虚拟清单:

Cargo.toml:

[workspace]
members = ["crates/*"]

其他的东西(包括 rust-analyzer "main" crate)都嵌套在 crates/ 下的某一个层级中。每个目录的名称都等于 crate 的名称。

crates/hir_def/Cargo.toml:

[package]
name = "hir_def"
version = "0.0.0"
edition = "2018"

在撰写本文时,crates/ 中有 32 个不同子文件夹。

扁平式比嵌套式更好

有趣的是,这个建议和按层级组织的习惯倾向(注:按照我们平时开发习惯来说)刚好对立:

rust-analyzer/
  Cargo.toml
  src/
  hir/
    Cargo.toml
    src/
    def/
    ty/

在这种情况下,有几个原因可以说明树形结构是低级的:

  1. crates 的 cargo 分级命名空间是扁平的。在 Cargo.toml 中不可能写出 hir::def ,所以一般 crate 的名字中都有前缀。树状排列创造了另一种层次结构,这就增加了不一致的可能性。
  2. 即使是比较大的列表也比小的树更容易让人一目了然。ls ./crates 给出了项目的层级概览,而且这看起来足够小。
> ls ./crates

base_db
cfg
flycheck
hir
hir_def
hir_expand
hir_ty
ide
ide_assists
ide_completion
ide_db
ide_diagnostics
ide_ssr
limit
mbe
parser
paths
proc_macro_api
proc_macro_srv
proc_macro_test
profile
project_model
rust-analyzer
sourcegen
stdx
syntax
test_utils
text_edit
toolchain
tt
vfs

在基于树状结构的布局做同样的事情比较困难的:

  • 只从单层级上看并不能告诉你哪些文件夹包含嵌套的 crate

  • 而在所有层级上看又会列出太多的文件夹(无关文件干扰视觉)

正确方式只看包含 Cargo.toml 的文件夹可以得到正确的结果,但并没有 ls 那样简单

嵌套结构确实比扁平结构更容易扩展。但常数很重要 —— 在你达到一百万行代码之前,项目中的 crates 数量可能会充满一个屏幕。

  1. 层级布局的最后一个问题是:没有完美的分层结构。但是对于扁平结构,增加或拆分 crates 的代价微不足道。在树状结构下,你需要弄清楚把新的 crate 放在哪里,而且,如果已经没有一个完美的匹配,你将不得不选择以下几种情况:
  • 在顶部附近添加一个愚蠢的空的文件夹
  • 添加到一个巨无霸的 utils 文件夹
  • 将代码放在一个已存在但是不是很理想的目录中(所以结构会随着维护而慢慢恶化)

对于长期维护的多人项目来说,这是一个重要的问题 —— 树状结构往往会随着时间的推移而恶化,而扁平结构则不怎么需要维护。

小技巧

让工作空间的根部成为虚拟清单。

这可以驱使我们把 main crate 放在根目录下,但这样做会使根目录被 src/ 污染,需要在每个 Cargo 命令中传递 --workspace,并向其他一致的结构添加异常。

反对从文件夹名称中去除普通前缀。

如果每个板块的名字都和它所在的文件夹一模一样,这让导航和重命名就会变得更容易。反向依赖的 Cargo.toml 同时提到了文件夹和 crate 的名称,当它们完全相同的时候就很有用。

对于大型项目来说,很多版本库的臃肿往往来自于自动化。

Makefiles 和各种 prepare.sh 脚本。为了避免臃肿和临时工作流程的泛滥,可以将所有的 Rust 自动化写在一个专门的 crate 里。这里安利一个有用的库:cargo-xtask

对于你不打算发布的内部 crate,可以使用 version = "0.0.0"

如果你确实想发布具有符合语义版本 API 的 crate 的子集,那么要非常慎重对待它们。将所有这样的crate提取到一个单独的顶层文件夹,即 libs/,这样做对未来可能是有意义的。这使得检查 libs/ 中的东西是否使用了 crates/ 中的东西更加容易。

由一个文件组成一个 crate。

对于这些文件,我们很容易陷入:把 src 目录展开,把 lib.rs 和 Cargo.toml 放在同一个目录下。但是我建议不要这样做 —— 即使 crate 现在是单文件,以后也可能会被扩展。

如果想了解更多,可以关注公众号: Databend

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容