Search code examples
rust

Is it possible to write a file containing macros-gathered data at compile time?


I have a couple of macro which collect signatures of some of my defined functions and then generate a function which can emit this data as &`static str.

E.g.

// stores 'test_fn1() -> u8' inside lazy_static variable
#[test_macro]
fn test_fn1() -> u8 {}


// stores 'test_fn2(u8) -> u8' inside the same lazy_static variable
#[test_macro]
fn test_fn2(arg1: u8) -> u8 {}


// generates a function 'get_signatures' that emits everything lazy_static variable has
generate_get_signatures!();

I want to output this data to some separate file during the same compilation process. Is it possible?


Solution

  • It is, currently, technically possible for a macro to write a file. However:

    1. The Rust compiler does not guarantee that macros will be invoked in any order, or only once, or even at all (e.g. in case of partially recompiling a modified crate) — citation. Therefore, you cannot rely on generate_get_signatures being able to see test_macro's results.

    2. There is interest in executing proc macros inside a WebAssembly sandbox, for security and deterministic builds. If this were implemented, you would no longer even be able to write files.

    3. It is just not recommended for proc-macros to have side effects.

    Proc macros are supposed to be “pure functions” from input source code to output source code, independently at each macro call site. Don't use them to produce other outputs. Use build.rs if you need a complex code generation step.

    If your problem is not to actually generate a file but to be able to discover all of the individual #[test_macro] annotated functions, then you may find inventory or linkme useful; they provide ways to access (at run time) information that is gathered from multiple sources in the code without needing to hardcode a centralized list.