为啥 proc-macros 必须在 proc-macro crate 中定义?
Posted
技术标签:
【中文标题】为啥 proc-macros 必须在 proc-macro crate 中定义?【英文标题】:Why do proc-macros have to be defined in proc-macro crate?为什么 proc-macros 必须在 proc-macro crate 中定义? 【发布时间】:2019-11-04 22:06:21 【问题描述】:我试图为我的 trait 创建一个派生宏,以简化一些东西。
我遇到了一些问题:
#[proc_macro_derive]
属性仅适用于proc-macro
板条箱类型的板条箱
并且,在小修复之后proc-macro=true
:
proc-macro
crate 类型目前不能导出除带有#[proc_macro_derive]
标记的函数以外的任何项目 标有#[proc_macro_derive]
的函数当前必须位于 crate 的根目录中`
这种行为的原因是什么?
【问题讨论】:
显示更多代码可能会有所帮助。 @CatoMinor 有什么帮助? 【参考方案1】:过程宏与代码中的正常依赖关系根本不同。一个普通的库只是链接到你的代码中,但一个过程宏实际上是一个编译器插件。
考虑交叉编译的情况:您在 Linux 机器上工作,但正在构建一个 WASM 项目。
一个普通的 crate 将被交叉编译,生成 WASM 代码并与其余 crate 链接。 proc-macro crate 必须在本机编译,在本例中为 Linux 代码,与当前编译器运行时(稳定、beta、nightly)链接,并在编译实际使用的 crate 时由编译器本身加载。它不会链接到其余的板条箱(不同的架构!)。而且由于编译流程不同,crate 类型也必须不同,这就是为什么需要proc_macro=true
。
关于这个限制:
proc-macro
crate 类型不能导出除带有#[proc_macro_derive]
标记的函数以外的任何项目
好吧,由于 proc-macro crate 是由编译器加载的,而不是链接到您的其余 crate,因此您从该 crate 导出的任何非 proc-macro 代码都是无用的。
请注意,错误消息是不准确的,因为您也可以使用#[proc_macro]
导出函数标记。
关于其他限制:
带有
#[proc_macro_derive]
标记的函数当前必须位于 crate 的根目录中
目前不支持在嵌套模块中添加 proc_macro
或 proc_macro_derive
项目,而且似乎不是特别有用,恕我直言。
【讨论】:
书中提到:“目前,程序宏需要在自己的 crate 中。最终,这个限制可能会解除,但现在,它是必需的。”我认为,将来,编译器可能会自动将 proc-macro 代码(与其他库代码)分离并以这种特殊方式编译它。希望这将很快实施。不错的答案! 这就是为什么我。在多个文件中拆分宏,如果您不喜欢项目中超过 9000 行长的文件,它可能会很有用。但这似乎是一个普遍的生锈问题,您更愿意将所有东西放在一个单一的圆角中 @majkrzak:关于 9000 行文件,实际上没有必要。您可以在 proc-macro crate 中编写任意数量的私有模块、子模块(在单独的文件中)和私有函数。您只是无法将它们公开。以上是关于为啥 proc-macros 必须在 proc-macro crate 中定义?的主要内容,如果未能解决你的问题,请参考以下文章