Search code examples
rustrust-cargo

Generating constants at compile time from file content


Let's say I have a file with some constants in it. This file probably comes from a different service and might be different for different scenarios. Now I want to squeeze every last bit of performance out of my program, want the compiler to do as much optimization as possible and I would compile the project for every scenario separately if needed.

Is there a way to take a file at compile time, turn it into rust code through some conversion logic, e.g. generate some constants, and compile the result (all inside the rust tooling, no other code-generation)?


Solution

  • If you write a build.rs file in the root of your crate it will be compiled and run with each crate compilation.

    It is usually used to build C bindings and such, but nothing prevents you from using it for your own purposes.

    Usually this build.rs creates a Rust source file somewhere int the output directory, reading the OUT_DIR environment variable:

    fn main() {
        println!("cargo:rerun-if-changed=build.rs");
        println!("cargo:rerun-if-changed=data.txt");
    
        let out_dir = std::env::var_os("OUT_DIR").unwrap();
        let path = std::path::Path::new(&out_dir).join("test.rs");
        std::fs::write(&path, "pub fn test() { todo!() }").unwrap();
    }
    

    Then the source is included in your project, usually in its own module with:

    mod test {
        include!(concat!(env!("OUT_DIR"), "/test.rs"));
    }