Is there a macro or similar workaround to include the source folder (src) path at compile time?
Asked Answered
Z

2

6

Is there a Rust macro or a similar workaround to include the path of the 'src' folder created via cargo new in my source file as a string literal at compile time or specifically when doing cargo build?

I have successfully done something similar where I use include_str! to include file content but I need to know if it is possible to directly include the src path in the code.

Zucchetto answered 15/11, 2017 at 8:9 Comment(0)
E
9

No, but you can get close using file!:

const FILE: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/", file!());

fn main() {
    use std::path::Path;

    println!("FILE: {:?}", FILE);
    println!("src path: {:?}", Path::new(FILE).parent());
}

Outputs, on the playground:

FILE: "/playground/src/main.rs"
src path: Some("/playground/src")
Emmerie answered 15/11, 2017 at 8:22 Comment(0)
B
0

As @DK mentioned this can be done with file!() and env!("CARGO_MANIFEST_DIR").

Here's a macro for ease of use:

#[macro_export]
macro_rules! file_abs {
    () => {
        std::path::Path::new(env!("CARGO_MANIFEST_DIR").join(file!()))
    };
}

Workspace Crates

This solution works for standalone crates but not workspaces. Assuming the crate is following the standard convention of crates/my_crate the above macro would return something like this:

/playgroud/crates/my_crate/crates/my_crate/src/main.rs

This can be fixed by popping the first two components of the path returned by file!().


#[macro_export]
macro_rules! file_abs_workspace {
    () => {
        std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
            .join(my_crate::pop_first_two_path_components(file!()))
    };
}

pub fn pop_first_two_path_components(path: &str) -> PathBuf {
    let mut components = std::path::Path::new(path).components();
    components.next();
    components.next();
    components.as_path().to_path_buf()
}

Once you have the file you can get the parent like normal:


fn main(){
  let dir = file_abs_workspace!().parent().unwrap();
  println!("directory is: {:?}", dir);
}

Note i haven't yet tried this with a published workspace crate, I suspect in that case you'd need to switch back to file_abs!().

Butanone answered 31/7, 2023 at 10:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.