为啥 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_macroproc_macro_derive 项目,而且似乎不是特别有用,恕我直言。

【讨论】:

书中提到:“目前,程序宏需要在自己的 crate 中。最终,这个限制可能会解除,但现在,它是必需的。”我认为,将来,编译器可能会自动将 proc-macro 代码(与其他库代码)分离并以这种特殊方式编译它。希望这将很快实施。不错的答案! 这就是为什么我。在多个文件中拆分宏,如果您不喜欢项目中超过 9000 行长的文件,它可能会很有用。但这似乎是一个普遍的生锈问题,您更愿意将所有东西放在一个单一的圆角中 @majkrzak:关于 9000 行文件,实际上没有必要。您可以在 proc-macro crate 中编写任意数量的私有模块、子模块(在单独的文件中)和私有函数。您只是无法将它们公开。

以上是关于为啥 proc-macros 必须在 proc-macro crate 中定义?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 lock 语句中必须指定同步对象

C++:为啥必须声明私有函数?

为啥必须在 C 中链接数学库?

为啥必须在 C 中向后读取指针声明? [关闭]

为啥我必须在所有回复中传递 RequestContext ?

为啥必须在 XML 属性中转义 <?