Opening files in proc macros

I'm trying to implement a procedural macro that requires the opening of a grammar file as such:

#[derive(Parser)]
#[grammar = "grammar.pest"]
struct MyParser;

There are two problems with this approach:

  • running Cargo in any subfolders of the project makes finding the grammar file hard
  • modifying the grammar file does not notify Cargo that it needs to rebuild the project

My current solutions to these problems are quite hacky. In order to have proper control of the project structure, I could require Cargo as a dependency, but this would make the macro painfully slow to compile. I'm not aware if there is any minimum Cargo API crate in the wild. The other problem is solvable by storing the file as a string in an unused constant const _PEST_GRAMMAR: &'static str = include_str!("grammar.pest");. Not a perfect solution, but definitely doable.

Any fresh ideas on the issues are more than welcome. :smiley:

4 Likes

If I understand the problem correctly, I think you can use CARGO_MANIFEST_DIR as the parent directory of grammar.pest or a starting point of a search for such file.

See this for an example, which panics in play.rust-lang.org but panicing is probably ok when not compiling with cargo... Rust Playground

3 Likes

The vulcano_shader_derive macro solves this by using CARGO_MANIFEST_DIR. See tomaka/vulkano#501.

#[derive(VulkanoShader)]
#[ty = "fragment"]
#[path = "shader/fragment.glsl"]
struct Dummy;
1 Like

Does the "modifying the grammar file does not notify Cargo that it needs to rebuild the project" part have a solution?

Looks like that's what include field in the cargo manifest is for.

Thanks. Kind of annoying that it's not additive and instead supposed to be complete. Issue filed.