如何从分散(非层级)目录构建Rust/Cargo工作区?
多年来积累了一系列Rust项目,重构核心库API时,检查并更新所有依赖该库的应用十分繁琐。不仅要编写shell脚本遍历所有项目,还因各目录重复编译相同内容,耗费大量磁盘空间和计算时间。
尝试使用Cargo工作区时遇到报错:
error: workspace member
/home/user/art/2019/equation-minis/equation-stitcher/Cargo.tomlis not hierarchically below the workspace root/home/user/src/embroidery/Cargo.toml
用软链接ln -s ../../art .规避后,又因项目中的依赖路径配置:
[dependencies] "filler" = { path = "../../../src/embroidery/filler" }
触发新报错:
error: failed to load manifest for workspace member
/home/user/src/embroidery/art/2022/united-methodistCaused by:
failed to load manifest for dependencyfillerCaused by:
failed to read/home/user/src/embroidery/src/embroidery/filler/Cargo.toml
寻求更灵活的方式,将多个Rust crate纳入同一工作区,实现统一的Cargo.lock并共享构建产物。
1. 启用Cargo工作区的resolver = "2" + 绝对路径(推荐)
Cargo 1.64及以上版本支持的resolver = "2"允许工作区成员使用绝对路径依赖,无需所有crate都位于工作区根目录的层级之下。
操作步骤:
- 在任意位置创建新的工作区根目录(比如
~/rust-workspace/),并在其中创建Cargo.toml - 在工作区配置中用绝对路径列出所有需要纳入的crate:
[workspace] resolver = "2" members = [ "/home/user/src/embroidery/filler", "/home/user/art/2019/equation-minis/equation-stitcher", "/home/user/art/2022/united-methodist", # 添加其他需要的crate绝对路径 ] - 将所有项目中依赖核心库的相对路径改为绝对路径,例如把
path = "../../../src/embroidery/filler"替换为path = "/home/user/src/embroidery/filler" - 在工作区根目录执行
cargo build,所有crate将共享同一个Cargo.lock文件和构建缓存。
2. 使用cargo workspaces第三方工具
如果不想修改大量依赖路径,可以借助cargo workspaces工具(需先通过cargo install cargo-workspaces安装),它支持跨目录管理多个crate,自动处理依赖路径并生成统一的工作区配置。
常用命令:
cargo workspaces init:初始化工作区并添加指定目录的cratecargo workspaces build:统一构建所有crate,自动共享构建缓存和锁文件
3. 调整项目目录结构(长期维护最优解)
如果计划长期维护这些项目,建议将相关项目整理到同一父目录下,示例结构:
~/rust-projects/ ├── embroidery/ │ ├── filler/ │ └── 其他子项目 └── art/ ├── 2019/ └── 2022/
然后在~/rust-projects/Cargo.toml中配置工作区:
[workspace] members = [ "embroidery/filler", "art/**/*", # 匹配art目录下所有子目录的crate ]
这种方式彻底避免路径混乱,是Cargo工作区的标准使用方式。
内容的提问来源于stack exchange,提问作者Mutant Bob

