Announcing include_dir!()

I was looking for a crate for embedding an entire directory tree into an executable to make deployment easier, but couldn't find anything which worked the way I wanted it to... So I made my own.

At the moment you need to use a build script, but when proc_macros become stable I'll be creating an include_dir!() macro to go alongside include_str!() and include_bytes!().

To embed a directory and its contents into your binary, you'll need to add the
following to your build.rs script.

extern crate include_dir;

use std::env;
use std::path::Path;
use include_dir::include_dir;

fn main() {
    let outdir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&outdir).join("assets.rs");

    include_dir("assets")
        .as_variable("SRC")
        .to_file(dest_path)
        .unwrap();
}

The generated code comes with doc-comments to make discovering how to use it easier, otherwise check out the integration tests directory.

Let me know what you think :slight_smile:

9 Likes

... this is a thing I will need very soon, and so I'm extremely excited that you've made it! I'll be checking it out in the near future :thumbsup:

Dumb question, but does any resource include images, audio files, or even other binary files?

RustProjectRoot
└───src
    └───Main.rs
└───Resources
    ├───HappyPicture.png
    ├───SomethingElse.so
    └───Audio.flac

Would I add the Resources folder as an 'asset' in build.rs and then reference each file or folder similar to the CI examples you added?

I think this is a really awesome idea, thanks for your contribution! If what I think turns out to be true, I could definitely see myself using this in the future.

Internally it'll look at everything in the directory you point it at and store each file as

pub struct File {
  pub name: &'static str,
  pub contents: &'static [u8],
}

Therefore it shouldn't matter whether your "Resources" directory contains text files, images, or even other binaries. They all just get stored as a bunch of bytes.

I added a couple convenience methods to make accessing the resources easier. Say you embedded that "Resources" directory under the variable RESOURCES, you can do something like this

let happy_picture = RESOURCES.find("HappyPicture.png");

or if you want to iterate over each thing in the "Resources" directory

for entry in RESOURCES.walk() {
  println!("{}", entry.name());
}
1 Like