4个稳定版本
1.8.12 | 2022年1月14日 |
---|---|
1.7.17 | 2021年11月17日 |
1.6.18 | 2021年8月8日 |
1.6.16 | 2021年8月6日 |
#10 in #rebuild
8KB
Cargo(1.37版本)无法很好地处理树中多个依赖项的crate功能各不相同的情况。
为了说明这个问题,考虑如下安排的crate A、B和C:
- Crate A和C都是Cargo虚拟清单的成员
- Crate C提供两个功能,F1和F2
- Crate A请求C的F1功能,crate B请求C的F2功能
当crate A和B一起构建时,cargo
会构建C,同时启用功能F1和F2(所有启用功能的并集)。然而,当A或B单独构建时,cargo
会构建C,只启用功能F1或F2。
遗憾的是,在这些情况下,cargo
都会在相同的目标位置构建crate C,并且每次crate C的功能发生变化时,C的输出都会被重新创建。
从干净的工作区开始,首先单独构建A,这将按预期构建C。然后单独构建B,C将被重新构建,因为启用了F2而不是F1。现在重新构建A,并观察C将再次被重新构建,因为F1被重新启用。
在实际应用中,这个问题远没有这么明显,因为A和B可能没有直接依赖于C,这可能导致其他许多crate的间接重建。
safecoin-crate-features
通过明确声明所有“类似C的crate”,以显式地包含树中任何其他crate(无论是显式还是隐式)所启用的所有功能的并集,来解决这个问题。Safecoin源树中的所有crate都应该依赖于safecoin-crate-features
。
添加新的依赖项crate
当观察到不必要的cargo
重建时,第一步是确定哪个依赖项crate正在遭受功能冲突。
这个信息无法从标准的cargo
程序中直接获得,因此使用以下步骤生成一个自定义的cargo
程序,该程序将在构建过程中将必要的功能信息输出到stderr:
$ git clone [email protected]:rust-lang/cargo.git -b rust-1.38.0
$ cd cargo
$ git apply 0001-Print-package-features.patch
$ cargo build
$ mv ~/.cargo/bin/cargo ~/.cargo/bin/cargo.org
$ cp ./target/debug/cargo ~/.cargo/bin/cargo
使用自定义的 cargo
重新构建,并搜索不同功能下构建的 crate 的指示(重复运行 ./scripts/cargo-install-all.sh
非常适合此目的)。当识别出有问题的 crate 时,将其添加到 safecoin-crate-features
的依赖中,并使用该 crate 观察到的所有已启用功能的并集。
附录
此命令将启用一些额外的 cargo 日志输出,这有助于调试依赖问题。
export CARGO_LOG=cargo::core::compiler::fingerprint=info
依赖
~17–29MB
~613K SLoC