Cargo跨工作区依赖加载失败问题咨询
无法将不同工作区的crate_b作为依赖项添加到crate_a中,文件夹结构如下:
. └── MainWorkspace/ ├── Cargo.toml ├── crate_a/ │ ├── Cargo.toml │ └── src/ │ └── main.rs └── other_workspace/ ├── Cargo.toml └── crate_b/ ├── Cargo.toml └── src/ └── lib.rs
各文件内容:
./MainWorkspace/Cargo.toml
[workspace] members = ["crate_a"] [workspace.dependencies] crate_b = { path = "other_workspace/crate_b" }
./MainWorkspace/crate_a/Cargo.toml
[package] name = "crate_a" version = "0.1.0" edition = "2021" [dependencies] crate_b = { workspace = true }
./MainWorkspace/other_workspace/Cargo.toml
[workspace] members = ["crate_b"] [workspace.dependencies] hello = { version = "*" }
./MainWorkspace/other_workspace/crate_b/Cargo.toml
[package] name = "crate_b" version = "0.1.0" edition = "2021" [dependencies] hello = { workspace = true }
运行cargo check时出现错误:
error: failed to load manifest for workspace member `/home/akhil/project/foo/crate_a` Caused by: failed to load manifest for dependency `crate_b` Caused by: failed to parse manifest at `/home/akhil/project/foo/other_workspace/crate_b/Cargo.toml` Caused by: error inheriting `hello` from workspace root manifest's `workspace.dependencies.hello` Caused by: `dependency.hello` was not found in `workspace.dependencies`
在MainWorkspace的Cargo.toml中添加hello依赖后可正常运行,更新后的配置:
[workspace] members = ["crate_a"] [workspace.dependencies] crate_b = { path = "other_workspace/crate_b" } hello = { version = "*" }
疑问:为何Cargo需要从MainWorkspace的Cargo.toml中查找hello依赖?它本该从other_workspace的Cargo.toml中读取才对。
这是因为当你在MainWorkspace中通过path依赖引用crate_b时,Cargo会将crate_b视为当前工作区(MainWorkspace)的一部分解析,而非使用它自身所属的other_workspace配置。
Cargo的工作区依赖继承规则是:当一个包被作为依赖引入到某个工作区时,它的workspace = true依赖会优先从当前执行命令所在的工作区根目录(即MainWorkspace的Cargo.toml)查找,而非它原本所属的子工作区(other_workspace)。
简单来说,crate_b里的hello = { workspace = true }会被解析为“从当前激活的工作区(MainWorkspace)的workspace.dependencies中获取hello配置”,不会去读取other_workspace的配置。
解决办法
如果你想让crate_b使用自身所属工作区的依赖配置,有两种方案:
直接指定路径依赖:将
crate_b从MainWorkspace的workspace.dependencies移除,在crate_a的依赖里直接指定路径:
修改crate_a/Cargo.toml:[dependencies] crate_b = { path = "../other_workspace/crate_b" }这样构建
crate_a时,Cargo会单独解析crate_b的依赖,此时crate_b的workspace = true会指向它自己的父工作区other_workspace。合并工作区:将other_workspace的成员加入MainWorkspace的
members列表,统一管理所有依赖:
修改MainWorkspace/Cargo.toml:[workspace] members = ["crate_a", "other_workspace/crate_b"] [workspace.dependencies] hello = { version = "*" }这种方式下所有包共享同一个工作区的依赖配置,可避免解析冲突。
内容的提问来源于stack exchange,提问作者akhildevelops

