Skip to content

Commit e035080

Browse files
committed
fix: envs in config can trigger rebuild by custom build script with rerun-if-env-changed.
1 parent a014fd0 commit e035080

File tree

2 files changed

+30
-13
lines changed

2 files changed

+30
-13
lines changed

src/cargo/core/compiler/fingerprint/mod.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ mod dirty_reason;
374374

375375
use std::collections::hash_map::{Entry, HashMap};
376376
use std::env;
377+
use std::ffi::OsString;
377378
use std::fs;
378379
use std::fs::File;
379380
use std::hash::{self, Hash, Hasher};
@@ -509,7 +510,7 @@ pub fn prepare_target(
509510
// thunk we can invoke on a foreign thread to calculate this.
510511
let build_script_outputs = Arc::clone(&build_runner.build_script_outputs);
511512
let metadata = build_runner.get_run_build_script_metadata(unit);
512-
let (gen_local, _overridden) = build_script_local_fingerprints(build_runner, unit);
513+
let (gen_local, _overridden) = build_script_local_fingerprints(build_runner, unit)?;
513514
let output_path = build_runner.build_explicit_deps[unit]
514515
.build_script_output
515516
.clone();
@@ -803,13 +804,20 @@ impl LocalFingerprint {
803804
/// Read the environment variable of the given env `key`, and creates a new
804805
/// [`LocalFingerprint::RerunIfEnvChanged`] for it.
805806
///
806-
// TODO: This is allowed at this moment. Should figure out if it makes
807-
// sense if permitting to read env from the config system.
807+
/// The `env_config` is used first to check if the env var is set in the config system
808+
/// as some env needs to be overridden. If not, it will fallback to `std::env::var`.
808809
#[allow(clippy::disallowed_methods)]
809-
fn from_env<K: AsRef<str>>(key: K) -> LocalFingerprint {
810+
fn from_env<K: AsRef<str>>(
811+
key: K,
812+
env_config: &Arc<HashMap<String, OsString>>,
813+
) -> LocalFingerprint {
810814
let key = key.as_ref();
811815
let var = key.to_owned();
812-
let val = env::var(key).ok();
816+
let val = if let Some(val) = env_config.get(key) {
817+
val.to_str().map(ToOwned::to_owned)
818+
} else {
819+
env::var(key).ok()
820+
};
813821
LocalFingerprint::RerunIfEnvChanged { var, val }
814822
}
815823

@@ -1577,7 +1585,7 @@ fn calculate_run_custom_build(
15771585
// the build script this means we'll be watching files and env vars.
15781586
// Otherwise if we haven't previously executed it we'll just start watching
15791587
// the whole crate.
1580-
let (gen_local, overridden) = build_script_local_fingerprints(build_runner, unit);
1588+
let (gen_local, overridden) = build_script_local_fingerprints(build_runner, unit)?;
15811589
let deps = &build_runner.build_explicit_deps[unit];
15821590
let local = (gen_local)(
15831591
deps,
@@ -1671,7 +1679,7 @@ See https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-change
16711679
fn build_script_local_fingerprints(
16721680
build_runner: &mut BuildRunner<'_, '_>,
16731681
unit: &Unit,
1674-
) -> (
1682+
) -> CargoResult<(
16751683
Box<
16761684
dyn FnOnce(
16771685
&BuildDeps,
@@ -1680,20 +1688,20 @@ fn build_script_local_fingerprints(
16801688
+ Send,
16811689
>,
16821690
bool,
1683-
) {
1691+
)> {
16841692
assert!(unit.mode.is_run_custom_build());
16851693
// First up, if this build script is entirely overridden, then we just
16861694
// return the hash of what we overrode it with. This is the easy case!
16871695
if let Some(fingerprint) = build_script_override_fingerprint(build_runner, unit) {
16881696
debug!("override local fingerprints deps {}", unit.pkg);
1689-
return (
1697+
return Ok((
16901698
Box::new(
16911699
move |_: &BuildDeps, _: Option<&dyn Fn() -> CargoResult<String>>| {
16921700
Ok(Some(vec![fingerprint]))
16931701
},
16941702
),
16951703
true, // this is an overridden build script
1696-
);
1704+
));
16971705
}
16981706

16991707
// ... Otherwise this is a "real" build script and we need to return a real
@@ -1705,6 +1713,7 @@ fn build_script_local_fingerprints(
17051713
// obvious.
17061714
let pkg_root = unit.pkg.root().to_path_buf();
17071715
let target_dir = target_root(build_runner);
1716+
let env_config = Arc::clone(build_runner.bcx.gctx.env_config()?);
17081717
let calculate =
17091718
move |deps: &BuildDeps, pkg_fingerprint: Option<&dyn Fn() -> CargoResult<String>>| {
17101719
if deps.rerun_if_changed.is_empty() && deps.rerun_if_env_changed.is_empty() {
@@ -1734,11 +1743,16 @@ fn build_script_local_fingerprints(
17341743
// Ok so now we're in "new mode" where we can have files listed as
17351744
// dependencies as well as env vars listed as dependencies. Process
17361745
// them all here.
1737-
Ok(Some(local_fingerprints_deps(deps, &target_dir, &pkg_root)))
1746+
Ok(Some(local_fingerprints_deps(
1747+
deps,
1748+
&target_dir,
1749+
&pkg_root,
1750+
&env_config,
1751+
)))
17381752
};
17391753

17401754
// Note that `false` == "not overridden"
1741-
(Box::new(calculate), false)
1755+
Ok((Box::new(calculate), false))
17421756
}
17431757

17441758
/// Create a [`LocalFingerprint`] for an overridden build script.
@@ -1769,6 +1783,7 @@ fn local_fingerprints_deps(
17691783
deps: &BuildDeps,
17701784
target_root: &Path,
17711785
pkg_root: &Path,
1786+
env_config: &Arc<HashMap<String, OsString>>,
17721787
) -> Vec<LocalFingerprint> {
17731788
debug!("new local fingerprints deps {:?}", pkg_root);
17741789
let mut local = Vec::new();
@@ -1793,7 +1808,7 @@ fn local_fingerprints_deps(
17931808
local.extend(
17941809
deps.rerun_if_env_changed
17951810
.iter()
1796-
.map(LocalFingerprint::from_env),
1811+
.map(|s| LocalFingerprint::from_env(s, env_config)),
17971812
);
17981813

17991814
local

tests/testsuite/build_script_env.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ fn rerun_if_env_is_exsited_config() {
415415

416416
p.cargo(r#"check --config 'env.FOO="bar"'"#)
417417
.with_stderr_data(str![[r#"
418+
[COMPILING] foo v0.0.1 ([ROOT]/foo)
418419
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
419420
420421
"#]])
@@ -445,6 +446,7 @@ fn rerun_if_env_newly_added_in_config() {
445446

446447
p.cargo(r#"check --config 'env.FOO="foo"'"#)
447448
.with_stderr_data(str![[r#"
449+
[COMPILING] foo v0.0.1 ([ROOT]/foo)
448450
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
449451
450452
"#]])

0 commit comments

Comments
 (0)