有没有一种方法可以获取文件和在编译时附加了程序宏的模块路径?

问题描述 投票:0回答:1

我正在过程宏上下文中寻找file!()module_path!()的等效项。

例如,以下操作无效:

file.rs

#[some_attribute]
const A: bool = true;

macro.rs

#[proc_macro_attribute]
pub fn some_attribute(attr: TokenStream, input: TokenStream) -> TokenStream {
    println!("{}", file!());

    input
}

此打印的macro.rs有意义,但我想要的是file.rs。有没有办法做到这一点? module_path!()也有类似的方法吗?

对此的要求是必须在编译时进行。

我正在尝试在OUT_DIR中创建一个包含常量值的文件,该属性随模块及其所在的文件一起添加。

rust rust-proc-macros
1个回答
1
投票

这里的问题是println!("{}", file!());是在编译时执行的,而不是在运行时执行的。类似于最近给定的here答案,您可以编辑原始函数并将代码插入其开头,这将在runtime处执行。您仍然可以使用过程宏file!()module_path!()。这是使用此方法的macro.rs

#[proc_macro_attribute]
pub fn some_attribute(_attr: TokenStream, input: TokenStream) -> TokenStream {

    // prefix to be added to the function's body
    let mut prefix: TokenStream = "
        println!(\"Called from {:?} inside module path {:?}\",
            file!(), module_path!());
    ".parse().unwrap();

    // edit TokenStream
    input.into_iter().map(|tt| { 
        match tt { 
            TokenTree::Group(ref g) // match function body
                if g.delimiter() == proc_macro::Delimiter::Brace => { 

                    // add logic before function body
                    prefix.extend(g.stream()); 

                    // return new function body as TokenTree
                    TokenTree::Group(proc_macro::Group::new(
                        proc_macro::Delimiter::Brace, prefix.clone()))
            },
            other => other, // else just forward
        }
    }).collect()
} 

您可以在main.rs中这样使用它:

use mylib::some_attribute;

#[some_attribute]
fn yo() -> () { println!("yo"); }

fn main() { yo(); }

请注意,代码已添加之前函数主体内部的内容。我们可以在末尾插入它,但是这将打破返回不带分号的值的可能性。

© www.soinside.com 2019 - 2024. All rights reserved.