(CARGO_MANIFEST_DIR,CARGO_PKG_NAME) for call site from proc macro

I lazily asked that for AI:

use proc_macro::TokenStream;
use proc_macro::Span;

#[proc_macro]
pub fn where_am_i(_: TokenStream) -> TokenStream {
    let span = Span::call_site();
    let file = span.source_file().path();
    let pkg = env!("CARGO_PKG_NAME");

    let rel_path = file.strip_prefix(std::env::var("CARGO_MANIFEST_DIR").unwrap()).unwrap();
    let combined = format!("{}/{}", pkg, rel_path.display());

    quote::quote! {
        const LOCATION: &str = #combined;
    }
    .into()
}

It should output something like crate-name/src/lib.rs (I'd typically pop the last component and resolve to an asset's path, for embedding assets without include_bytes!, for dynamic loading).

Unlike Dioxus, I don't want to embed assets with random base64 names; I'd like to keep them with a safe, fixed name, for avoiding ever-changing app's installation files.

I'm not sure though if these Cargo env's variables are guaranteed to return the call site's manifest directory and package name, though. (Another thing is I probably need to replace any :: components by _ from the crate name!)

This mixes two incompatible approaches:

env! is going to read var when your proc macro is compiled and tell you your proc macro's ownpackage name.

std::env will read when the proc macro runs, which might work and give you the root of the crate calling it, but I'm not sure if inheriting environment of the calling crate is guaranteed there.


Before stripping prefix, it may be a good idea to canonicalize() both paths in case they had some symlinks or one has been canonicalized already.

Rust also has ability to rewrite path prefixes with --remap-path-prefix. I'm not sure when in the compilation process this kicks in — test with rewrites to make sure source_file doesn't get rewritten there, as this would lose its original path prefix.

2 Likes

I see. I was pretty doubting that would work.


So far, best bet then is probably not supporting those kind of "assets" like Dioxus and demand user to bundle a copy of icons in their entry point if a library needs these icons (in case they're too heavy to be included in the RAM thru include_bytes!).

Modern operating systems use virtual memory to map executables, so resources bundled with include_bytes! are not that terrible. I wouldn't worry about icons.

1 Like

Ah, I see! Maybe you're right :slight_smile:

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.