Reputation: 105
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
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
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