使用Bazel构建外部Rust依赖时serde1特性失效问题求助
我尝试将Foundry作为外部依赖纳入仓库,需要用到其github.com/foundry-rs/foundry/blob/master/crates/cli中的forge CLI命令。
已配置WORKSPACE文件引入相关CLI crate及依赖:
crates_repository( name = "foundry", annotations = { "svm-rs": [crate.annotation( gen_binaries = True, )], "foundry-cli": [crate.annotation( gen_binaries = True, )], "forge": [crate.annotation( gen_binaries = True, )], "serde": [crate.annotation( gen_binaries = True, )], }, cargo_lockfile = "//:Cargo.lock", lockfile = "//:Cargo.Bazel.lock", packages = { "svm-rs": crate.spec( git = "https://github.com/alloy-rs/svm-rs", rev = "b55c47b09437cf8dc01e1028aa0ab0a2300083d4", ), "forge": crate.spec( git = "https://github.com/foundry-rs/foundry", rev = "d5db2c514fea76291715b019db65b60aa41eb421", ), "foundry-cli": crate.spec( git = "https://github.com/foundry-rs/foundry", rev = "d5db2c514fea76291715b019db65b60aa41eb421", ), "serde": crate.spec( version = "1", features = ["derive"], ), #### Added the below while debugging "camino": crate.spec( version = "1.1.6", features = ["serde1"], ), "globset": crate.spec( version = "0.4.9", features = ["serde1"], ), "serde_derive": crate.spec( version = "1", ), "serde_json": crate.spec( version = "1", ), "hex": crate.spec( features = ["serde"], ), ### end of added }, )
之后我修改了生成的规则文件.cache/bazel/_bazel_j/6c68e123d5be80edfb5e3a8f56f57687/external/foundry__svm-rs-0.3.0/BUILD.bazel,把:
rust_binary( name = "svm__bin", ...
改为:
rust_binary( name = "svm", ...
执行命令bazel build @foundry//:foundry-cli__forge时出现以下错误:
ERROR: .cache/bazel/_bazel_j/6c68e123d5be80edfb5e3a8f56f57687/external/foundry__camino-1.1.6/BUILD.bazel:22:13: Compiling Rust rlib camino v1.1.6 (6 files) failed: (Exit 1): process_wrapper failed: error executing command bazel-out/k8-opt-exec-2B5CBBC6/bin/external/rules_rust/util/process_wrapper/process_wrapper --env-file bazel-out/k8-fastbuild/bin/external/foundry__camino-1.1.6/camino_build_script.env --arg-file ... (remaining 35 arguments skipped) Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging error: proc-macro derive panicked --> external/foundry__camino-1.1.6/src/lib.rs:108:39 | 108 | #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] | ^^^^^^^^^^^^^^^^ | = help: message: file missing from serde_derive manifest directory during macro expansion: .cache/bazel/_bazel_j/6c68e123d5be80edfb5e3a8f56f57687/sandbox/linux-sandbox/7574/execroot/external/foundry__serde_derive-1.0.183/serde_derive-x86_64-unknown-linux-gnu error: proc-macro derive panicked --> external/foundry__camino-1.1.6/src/lib.rs:108:57 | 108 | #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] | ^^^^^^^^^^^^^^^^^^ | = help: message: file missing from serde_derive manifest directory during macro expansion: .cache/bazel/_bazel_j/6c68e123d5be80edfb5e3a8f56f57687/sandbox/linux-sandbox/7574/execroot/external/foundry__serde_derive-1.0.183/serde_derive-x86_64-unknown-linux-gnu error[E0599]: no function or associated item named `deserialize` found for struct `Utf8PathBuf` in the current scope --> external/foundry__camino-1.1.6/src/serde_impls.rs:62:25 | 62 | Ok(Utf8PathBuf::deserialize(deserializer)?.into()) | ^^^^^^^^^^^ function or associated item not found in `Utf8PathBuf` | ::: external/foundry__camino-1.1.6/src/lib.rs:111:1 | 111 | pub struct Utf8PathBuf(PathBuf); | ---------------------- function or associated item `deserialize` not found for this struct | = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `deserialize`, perhaps you need to implement one of them: candidate #1: `Deserialize` candidate #2: `DeserializeSeed` error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0599`.
根据serde文档,Deserialize和DeserializeSeed都属于serde1特性,但我已配置该特性,请问遗漏了什么?
问题出在Bazel编译proc-macro时的沙箱路径问题,以及依赖特性的传递性配置上,按以下步骤修复:
替换手动修改BUILD文件的操作
手动修改生成的BUILD文件会导致依赖图不一致,后续规则更新时还会被覆盖。直接在crates_repository的annotations中给svm-rs指定二进制名称:"svm-rs": [crate.annotation( gen_binaries = True, binary_name = "svm", )],这样生成的规则会直接使用
svm作为二进制目标名,无需手动修改文件。修复serde_derive的proc-macro沙箱问题
错误提示serde_derive的manifest文件找不到,是因为Bazel沙箱中proc-macro无法正确访问路径。给serde_derive添加注解,确保Bazel正确处理其构建脚本:
在annotations中新增:"serde_derive": [crate.annotation( gen_build_script = True, )],确保serde特性的正确传递
把serde_derive的依赖合并到serde的spec中,避免单独声明导致的版本不一致,同时保证特性传递正确:
修改serde的配置:"serde": crate.spec( version = "1", features = ["derive"], dependencies = { "serde_derive": crate.spec(version = "1"), }, ),然后删除单独的
serde_derive条目。清理缓存并重新生成规则
执行以下命令清理旧缓存,重新生成依赖规则:bazel clean --expunge bazel run @rules_rust//crate_universe:generate -- --config //:Cargo.Bazel.lock重新编译验证
再次执行编译命令:bazel build @foundry//:foundry-cli__forge
内容的提问来源于stack exchange,提问作者Josh Laird

