Expand description

An extension to the include_str!() and include_bytes!() macro for embedding an entire directory tree into your binary. This is a fork of the include_dir crate which gathers files’ mimetype at compile-time that can be accessed at run-time.

Environment Variables

When invoking the include_directory!() macro you should try to avoid using relative paths because rustc makes no guarantees about the current directory when it is running a procedural macro.

Environment variable interpolation can be used to remedy this. You might want to read the Environment Variables section of The Cargo Book for a list of variables provided by cargo.

Most crates will want to use the $CARGO_MANIFEST_DIR or $OUT_DIR variables. For example, to include a folder relative to your crate you might use include_directory!("$CARGO_MANIFEST_DIR/assets").

Examples

Here is an example that embeds the include_directory crate’s source code in a static so we can play around with it.

use include_directory::{include_directory, Dir};
use std::path::Path;

static PROJECT_DIR: Dir<'_> = include_directory!("$CARGO_MANIFEST_DIR");

// of course, you can retrieve a file by its full path
let lib_rs = PROJECT_DIR.get_file("src/lib.rs").unwrap();

// you can get the mimetype by doing
let mimetype = lib_rs.mimetype();

// you can also inspect the file's contents
let body = lib_rs.contents_utf8().unwrap();
assert!(body.contains("SOME_INTERESTING_STRING"));

// if you enable the `glob` feature, you can for files (and directories) using glob patterns
#[cfg(feature = "glob")]
{
    let glob = "**/*.rs";
    for entry in PROJECT_DIR.find(glob).unwrap() {
        println!("Found {}", entry.path().display());
    }
}

Features

This library exposes a couple feature flags for enabling and disabling extra functionality. These are:

  • glob - search for files using glob patterns
  • metadata - include some basic filesystem metadata like last modified time. This is not enabled by default to allow for more reproducible builds and to hide potentially identifying information.
  • nightly - enables nightly APIs like track_path and proc_macro_tracked_env. This gives the compiler more information about what is accessed by the procedural macro, enabling better caching. Functionality behind this feature flag is unstable and may change or stop compiling at any time.

Compile Time Considerations

While the include_directory!() macro executes relatively quickly, it expands to a fairly large amount of code (all your files are essentially embedded as Rust byte strings) and this may have a flow-on effect on the build process.

In particular, including a large number or files or files which are particularly big may cause the compiler to use large amounts of RAM or spend a long time parsing your crate.

As one data point, this crate’s target/ directory contained 620 files with a total of 64 MB, with a full build taking about 1.5 seconds and 200MB of RAM to generate a 7MB binary.

Using include_directory!("target/") increased the compile time to 5 seconds and used 730MB of RAM, generating a 72MB binary.

Macros

Embed the contents of a directory in your crate.

Structs

A directory.
A file with its contents stored in a &'static [u8].
Basic metadata for a file.

Enums

A directory entry, roughly analogous to std::fs::DirEntry.