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
}
}
这可能更干净。
过程宏存在于它们自己的箱子中,这些箱子是为开发机器编译的(这样它们就可以在编译使用它们的箱子时执行)。过程宏包中的任何 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
}
}
这可能更干净。