proc宏能否确定调用编译的目标?

Can proc macros determine the target of the invoking compilation?

过程宏存在于它们自己的箱子中,这些箱子是为开发机器编译的(这样它们就可以在编译使用它们的箱子时执行)。过程宏包中的任何 conditional compilation 指令将相应地基于 它们的 编译环境,而不是调用包的编译环境。

当然,这样的宏可以扩展为包含条件编译指令的标记,然后将在调用包的编译上下文中对其进行评估——然而,这并不总是可能或不可取的。

如果希望扩展标记本身成为调用包编译环境的某种功能,则需要宏在其 运行 时间内确定该环境(这当然是调用板条箱的编译时间)。显然 std::env 模块的完美用例。

然而,rustc 没有设置任何环境变量;而 Cargo 仅集 a limited few。特别是,一些关键信息(如目标 architecture/operating 系统等)根本不存在。

我很欣赏调用包中的构建脚本可以为宏设置环境变量然后读取,但这给调用包作者带来了令人不满意的负担。

proc 宏作者有什么方法可以获取有关调用 crate 的编译环境的 运行time 信息(目标体系结构和操作系统最受关注)我)?

我通过递归到第二个 proc 宏调用中有点不优雅地解决了这个问题,其中第一次调用添加了 #[cfg_attr] 带有文字布尔参数的属性,然后可以在第二次调用中访问这些属性:

#[cfg_attr(all(target_os = "linux"), my_macro(linux = true ))]
#[cfg_attr(not(target_os = "linux"), my_macro(linux = false))]
// ...

一个黑客,但它有效。

我找到了另一个解决方案:

您可以为所有 OS 生成代码并在引用的代码中使用 #[cfg(...)],而不是像这样根据标志生成代码。

quote! {
    #[cfg(linux)]
    {
        // linux specific stuff
    }

    #[cfg(not(linux))]
    {
        // not linux specific stuff
    }
}

这可能更干净。