代码之家  ›  专栏  ›  技术社区  ›  hellow Adolfo Casari

实现proc宏时的循环包依赖项

  •  3
  • hellow Adolfo Casari  · 技术社区  · 7 年前

    我尝试实现一个proc_宏 Dump ,类似于塞尔维亚人 Serialize .

    为此,我有一个板条箱 foo 它包含我的“原始”结构( P1 P2 在这种情况下),应该只能转储。

    接下来我有一个 foo_derive 包含程序宏本身的板条箱。

    因为我想支持多种格式,所以我有第三个板条箱 foo_dump 它包含了 转储 (例如,可以转储此结构)和 Dumper (这是后端应该实现的功能)。 一直往前走到这一点。

    当我现在想编译它时,我得到了这个错误:

    $ 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)`
    

    我不知道正确的方法是什么,如何在这个板条箱中使用依赖项。我现在的是:

    dependencies

    这当然是不可能的。

    我错过了什么?我必须做什么才能打破依赖关系循环?


    ( mcve@github )

    /CAMGL

    [workspace]
    members = [ 
        "foo",
        "foo_derive",
        "foo_dump",
    ]
    

    /oo/cGOG.ToMl

    [package]
    name = "foo"
    version = "0.1.0"
    edition = "2018"
    
    [dependencies]
    foo_derive = { path = "../foo_derive" }
    

    /Fo/SRC/LIB

    use foo_derive::Dump;
    
    struct P1;
    struct P2;
    
    #[derive(Dump)]
    struct Bar {
        primitive_one: P1,
        primitive_two: P2,
    }
    

    /foo_dump/cargo.toml

    [package]
    name = "foo_dump"
    version = "0.1.0"
    edition = "2018"
    
    [dependencies]
    foo = { path = "../foo" }
    

    /foo_转储/src/lib.rs

    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

    [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

    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()
    }
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   hellow Adolfo Casari    7 年前

    多亏了 @Boiethious comment 还有他的帮助 in chat 我想出了一个解决办法,包括引进一个新的板条箱。 foo_core 其中包含结构 P1 P2 .

    所以我所做的是:

    • 去除 P1 P2 foo 把它们放进 足芯
    • 移除依赖项 foo_dump foo_derive 所以这只取决于 syn quote 不再
    • 添加 足芯 作为一种依附 足尾转储
    • 添加依赖项 足尾转储

    (您可以在 git history )

    最终的依赖链现在看起来如下:

    depency graph

    推荐文章