I'm having a hard time figuring out how to use rerun-if-env-changed
in build scripts.
I have a minimal project setup like this:
inner
- src
- lib.rs
- build.rs
- Cargo.toml
src
- main.rs
build.rs
Cargo.toml
In the outer Cargo.toml I define inner
as a dependency:
[package]
name = "outer"
version = "0.1.0"
edition = "2018"
build = "build.rs"
[dependencies]
inner = { path = "./inner" }
The build script for outer
defines an env var FOO
, which I'd like inner
to use during its build:
// outer/build.rs
fn main() {
println!("cargo:rustc-env=FOO=1");
}
And the inner
build script:
// inner/build.rs
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
fn main() {
println!("cargo:rerun-if-env-changed=FOO");
let out_dir = env::var("OUT_DIR").unwrap();
let dest = Path::new(&out_dir).join("build_constants.rs");
let mut file = File::create(&dest).unwrap();
let foo: i32 = option_env!("FOO")
.map_or(Ok(-1), str::parse)
.expect("failed to parse env variable");
write!(&mut file, "const BUILD_FOO: i32 = {};", foo).unwrap();
}
The inner
crate publicly exports a the constant, which can be imported by outer
:
// inner/src/lib.rs
include!(concat!(env!("OUT_DIR"), "/build_constants.rs"));
pub const FOO: i32 = BUILD_FOO;
I would expect this to work like this:
If outer
is build first, then FOO
is set to 1
and when inner
is built, the constant is consequently set to 1
.
If inner
is build first, it is then built again (rerun), since FOO
has changed during the build of outer
.
However, this does not happen and the pub const FOO
is always set to -1, the default value defined in the inner build script.
Am I doing something wrong here or is there a better way to pass around environment variables between crates?