Which directory does a proc macro run from?

Until Span::source_file() from the proc-macro crate becomes stable, any procedural macros that need to do filesystem operations will resolve paths relative to the current directory... but which directory is that?

Are there any guarantees about which directory a procedural macro will run in? And how does that interact with workspaces where the crate that consumes this macro may be compiled from its directory individually or at the same time as the entire workspace (cargo build --workspace)?

2 Likes

no answers, further questions: If a proc-macro changes directories and does not reset it on exit does a tree fall in the woods?

1 Like

I'm not sure if I've understood the problem correctly, but the CARGO_MANIFEST_DIR environment variable might be useful? I'm not totally sure how it interacts with workspaces and such, but I've used it as the root path before to avoid dealing with relative paths.

A proc macro runs from whichever directory cargo invokes rustc. In the past this used to.be the package root, but it was changed to the workspace root to make error messages relative to the workspace root. I don't think there i sany guarantee that this won't change again in the future.

Note that doctests processing still uses package root and not workspace root.

Oh yeah, you can use $CARGO_MANIFEST_DIR as an "anchor" to get a known useful path, but let's say I write something like diesel::embed_migrations!("./migrations/"). What is that migrations/ directory relative to?

In the include_dir!() crate I solved this issue by letting people explicitly use environment variables when referring to paths.

However, I'm now using a 3rd party procedural macro that does things with files and having really strange issues around how the path is resolved:

  • On my computer, I'll write path/to/file and it'll build
  • On my computer, I'll cargo clean and write ../path/to/file and it'll build (this one was a massive wtf for me!)
  • In CI, I'll write path/to/file and the nightly job will pass while stable will fail
  • In CI, I'll write ../path/to/file and the stable job will pass while the nightly one fails

(at least I think the difference in CI is stable vs nightly, I just know that no matter what path I pass in I'll get a CI failure)

Here is the original ticket if anyone is interested:

For consistency with std, it should probably be relative to the source file which invokes the macro. I don't know if this information is currently available to proc macros, though.

Agreed. Unfortunately, that API isn't stable yet so crates like include_dir can't use it[1].


  1. That's the Span::source_file() thing I linked to in my original post :wink: ↩︎

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.