Cyclic package dependency while implementing proc macro
我尝试实现proc_macro
为此,我有一个板条箱
接下来,我确实有一个
因为我想支持多种格式,所以我有第三个板条箱
非常直截了当的到这一点。
现在,我想编译它时,出现以下错误:
1 2 3 4 5 | $ cargo build error: cyclic package dependency: package `foo v0.1.0 (/tmp/tmp.u34pI5J6qd/example/foo)` depends on itself. Cycle: package `foo v0.1.0 (/tmp/tmp.u34pI5J6qd/example/foo)` ... which is depended on by `foo_dump v0.1.0 (/tmp/tmp.u34pI5J6qd/example/foo_dump)` ... which is depended on by `foo_derive v0.1.0 (/tmp/tmp.u34pI5J6qd/example/foo_derive)` |
我不知道正确的方法是什么,如何在此板条箱中使用依赖项。我当前的是:
这当然是不可能的。
我想念什么?我要怎么做才能打破依赖圈?
(mcve @ github)
/Cargo.toml
1 2 3 4 5 6 | [workspace] members = [ "foo", "foo_derive", "foo_dump", ] |
/foo/Cargo.toml
1 2 3 4 5 6 7 | [package] name ="foo" version ="0.1.0" edition ="2018" [dependencies] foo_derive = { path ="../foo_derive" } |
/foo/src/lib.rs
1 2 3 4 5 6 7 8 9 10 | use foo_derive::Dump; struct P1; struct P2; #[derive(Dump)] struct Bar { primitive_one: P1, primitive_two: P2, } |
/foo_dump/Cargo.toml
1 2 3 4 5 6 7 | [package] name ="foo_dump" version ="0.1.0" edition ="2018" [dependencies] foo = { path ="../foo" } |
/foo_dump/src/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | use foo::{P1, P2}; pub trait Dumper { fn dump_p1(&mut self, value: &P1); fn dump_p2(&mut self, value: &P2); } pub trait Dump { fn dump<D: Dumper>(&self, d: D); } impl Dump for P1 { fn dump<D: Dumper>(&self, d: D) { d.dump_p1(self); } } impl Dump for P2 { fn dump<D: Dumper>(&self, d: D) { d.dump_p2(self); } } |
/foo_derive/Cargo.toml
1 2 3 4 5 6 7 8 9 10 11 12 | [package] name ="foo_derive" version ="0.1.0" edition ="2018" [lib] proc-macro = true [dependencies] syn ="*" quote ="*" foo_dump = { path ="../foo_dump" } |
/foo_derive/src/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | extern crate proc_macro; use quote::quote; use proc_macro::TokenStream; use syn::DeriveInput; #[proc_macro_derive(Dump)] pub fn derive_dump(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as DeriveInput); let name = &input.ident; quote!( impl foo_dump::Dump for #name { fn dump<D: foo_dump::Dumper>(&self, d: D) { unimplemented!() } } ).into() } |
感谢@Boiethious评论和他在聊天中的帮助,我得以提出一个解决方案,该解决方案涉及引入一个新的板条箱
所以我做的是:
-
从
foo 中删除P1 和P2 并将它们放入foo_core -
从
foo_derive 中删除依赖项foo_dump ,使其不再仅依赖于syn 和quote -
在
foo 和foo_dump 中将foo_core 添加为依赖项 -
将依赖项
foo_dump 添加到foo
(您可以在git历史中查看更改的完整列表)。
现在,最终的依赖链如下所示: