为什么必须在proc-macro crate中定义proc-macros?

maj*_*zak 5 language-lawyer rust rust-macros

我试图为我的特征创建一个派生宏,以简化一些内容。

我遇到了一些问题:

the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
Run Code Online (Sandbox Code Playgroud)

并且,在进行小规模修复后proc-macro=true

proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently
functions tagged with `#[proc_macro_derive]` must currently reside in the root of the crate`
Run Code Online (Sandbox Code Playgroud)

这种行为的原因是什么?

rod*_*igo 8

过程宏从根本上不同于代码中的常规依赖项。普通库只是链接到您的代码中,而过程宏实际上是编译器插件

考虑交叉编译的情况:您正在Linux机器上工作,但是正在构建WASM项目。

  • 普通的板条箱将被交叉编译,生成WASM代码,并与其余板条箱链接。
  • proc-macro板条箱必须在本地编译,在这种情况下为Linux代码,并与当前编译器运行时(稳定,beta,夜间)链接,并在编译板条箱实际使用的地方时由编译器本身加载。它不会链接到其他板条箱(不同的架构!)。

而且由于编译流程不同,所以板条箱类型也必须不同,这就是为什么proc_macro=true需要的原因。

关于此限制:

proc-macro 板条箱类型不能导出除带有标记的功能以外的其他任何项目 #[proc_macro_derive]

好吧,由于proc-macro板条箱是由编译器加载的,没有链接到其余板条箱,因此,从此板条箱导出的任何非proc-macro代码都将是无用的。

请注意,错误消息不准确,因为您还可以使用导出函数tagget #[proc_macro]

还有其他限制:

标记为的函数#[proc_macro_derive]当前必须位于板条箱的根目录中

恕我直言,当前不支持在嵌套模块中添加proc_macroproc_macro_derive项目,并且似乎并不是特别有用。

  • @majkrzak:关于9000行文件,实际上并没有必要。您可以在proc-macro crate中编写任意数量的私有模块,子模块(在单独的文件中)和私有函数。您只是被禁止将其公开。 (3认同)
  • 书中提到:“目前,程序宏需要放在自己的板条箱中。*最终,这个限制可能会被取消*,但就目前而言,这是必需的。” 我认为,将来,编译器可能会自动将 proc-macro 代码(与其他库代码)分离并以这种特殊方式进行编译。希望这将很快得到实施。很好的答案! (2认同)