I am working on a Rust project that involves writing a procedural macro, which need to get the relative file path where the macro is invoked. For example, let's say I have the following code structure:
// /src/some_file/mod.rs
use other_crate::my_proc_macro;
my_proc_macro!(file1);
In this case, I want my_proc_macro could detect the calling path /src/some_file/mod.rs during the macro parsing.
I found std::env::current_dir().unwrap().join(file!()) could get the path of a file, but it's the procedural macro file path, not the user code caller's file path.
How can I get the caller's file path in a Rust procedural macro? Is it not feasible yet?
(You may wonder why needs this path info. In my case, there is more than 1 macros, the information of the caller's file path from 1 macro is used to determine another macro's behavior--- this mechanism is somehow used in enum_dispatch)
Thanks your feedback, but I guess this is not suitable in my case. What I want is that , 1 macor(say Macro_a) would produce some code for a hidden trait. Anthor trait (say Macro_b) would be used like #[Macro_b(hidden_trait_name)].
Usually but not always, the Macro_b would be used in another file, compared with the Macro_a, and I want the hidden trait totally transparent to users, which means users should not add use .... hidden_trait_name; explicitly---That is why I want to know the caller file path.
If this is not feasible, I wonder if there is a way that could make a trait available to the whole crate just like #[macro_export] does for a declarative macro.
This is the correct way to do so, which should be done like this:
#[proc_macro]
pub fn example_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
// Get the `Span` where the macro was called
let span = proc_macro::Span::call_site();
// Use the `Span` to get the `SourceFile`
let source_file = span.source_file();
// Get the path of the `SourceFile`
let path: PathBuf = source_file.path();
// Now you can use the file path for further processing
// ...
// Return the original input for this example
input
}
But since fn source_file is not stable both for proc_macro and proc_macro2, I finally take a workaround as this github comment said.