We have a library crate which is a simple little web framework. It contains some static assets like javascript files, style sheets, images, etc. A few different applications use this framework (including its assets).
By default the (Rocket) applications set up a file serving mount which points to the web framework crate's static
directory, but we also support a feature called builtin-content
which is used for deployment builds. This feature makes the application build the static files into the binary:
const LOGO_SVG: &'static [u8] =
include_bytes!("../../libs/htstatic/static/img/logo.min.svg");
"How can the application reference files in the library crate?", you ask. That's a good question -- it works because all the projects are checked into the same repository, so the application and the static directory and files are deterministically relative to each other.
However, having the library and the application in the same repository has become a substantial burden. We want to separate them so the framework library is in its own crate and each application gets its own crate.
We still want to keep the static files which belong to the framework in the framework's library crate, which means we have to be able to reference its directory from the applications. This can be done by adding a function to the library which gets the library crate's "static assets" path:
pub fn get_static_base_dir() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("static")
}
Then the applications set up a static file serving mount which points to framework::get_static_base_dir()
. This works fine.
However, it obviously does not work for the builtin-content
feature, because:
- It returns
PathBuf
-
include_bytes!()
is (understandably) picky about path input type.
I tried making get_static_base_dir()
const
:
pub const fn get_static_base_dir() -> str {
concat!(env!("CARGO_MANIFEST_DIR"), "/static")
}
.. and then making the include_bytes!()
in the application use concat!()
:
let path = concat!(framework::get_static_base_dir(), "img/logo.min.svg");
const LOGO_SVG: &'static [u8] = include_bytes!(path);
.. but this is clearly not a solution.
Is there a way to do this? I know that all the data is available at compile time, so I know it's possible in theory, but I feel like I'm missing a few important puzzle pieces to stitch it together.
tl;dr
I want to call include_bytes()
in an application crate to include a file which lives in a library crate, and I want that library crate to have a function which returns its static assets path at compile time, and the application crate concatenates the path returned from the library crate and a string literal to form the input path to include_bytes()
.