Art Rosnovsky
Art Rosnovsky

Reputation: 105

Is it possible to use .env file at build time?

I'm coming to Rust from the JavaScript world, where you could have a .env file (git-ignored), and environmental values from this file could be made available at runtime via an npm package (say, dotenv).

I was able to use a dotenv crate to make this work similarly when I just cargo run the project, but after I build a release version, the value of the environment variable is lost and the app panics.

I understand that cargo doesn't evaluate env variables at build time, and using env!-like macros won't work either, at least to my best understanding.

What I'm asking is this: how do I store a variable in a file (that I can gitignore), make Rust pick up values from this file, and use them at build time so that these values are available to the release-built app?

I'm sure that there's a well-established way of doing this, but I struggle to figure it out.

Upvotes: 4

Views: 10390

Answers (2)

Chayim Friedman
Chayim Friedman

Reputation: 71605

I'm not so sure this is well-established, but you can use a build script that will read the file and use println!("cargo:rustc-env=VAR=VALUE") to send the environment variables to Cargo, allowing you to retrieve them in the code with env!() or option_env!().

For example, to use a .env file, add dotenv to build-dependencies, and use it like so in build.rs:

fn main() {
    let dotenv_path = dotenv::dotenv().expect("failed to find .env file");
    println!("cargo:rerun-if-changed={}", dotenv_path.display());

    // Warning: `dotenv_iter()` is deprecated! Roll your own or use a maintained fork such as `dotenvy`.
    for env_var in dotenv::dotenv_iter().unwrap() {
        let (key, value) = env_var.unwrap();
        println!("cargo:rustc-env={key}={value}");
    }
}

Upvotes: 3

kmdreko
kmdreko

Reputation: 60787

There is the dotenv-codegen crate that provides a dotenv! macro that works like the env! macro except it will load from a .env file.

Upvotes: 4

Related Questions