Skip to content

Commit 76ffbe0

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

File tree

2 files changed

+33
-14
lines changed

2 files changed

+33
-14
lines changed

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

+31-14
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();
@@ -801,15 +802,24 @@ pub enum StaleItem {
801802

802803
impl LocalFingerprint {
803804
/// Read the environment variable of the given env `key`, and creates a new
804-
/// [`LocalFingerprint::RerunIfEnvChanged`] for it.
805+
/// [`LocalFingerprint::RerunIfEnvChanged`] for it. The `env_config` is used firstly
806+
/// to check if the env var is set in the config system as some envs need to be overridden.
807+
/// If not, it will fallback to `std::env::var`.
805808
///
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.
809+
// TODO: `std::env::var` is allowed at this moment. Should figure out
810+
// if it makes sense if permitting to read env from the env snapshot.
808811
#[allow(clippy::disallowed_methods)]
809-
fn from_env<K: AsRef<str>>(key: K) -> LocalFingerprint {
812+
fn from_env<K: AsRef<str>>(
813+
key: K,
814+
env_config: &Arc<HashMap<String, OsString>>,
815+
) -> LocalFingerprint {
810816
let key = key.as_ref();
811817
let var = key.to_owned();
812-
let val = env::var(key).ok();
818+
let val = if let Some(val) = env_config.get(key) {
819+
val.to_str().map(ToOwned::to_owned)
820+
} else {
821+
env::var(key).ok()
822+
};
813823
LocalFingerprint::RerunIfEnvChanged { var, val }
814824
}
815825

@@ -1577,7 +1587,7 @@ fn calculate_run_custom_build(
15771587
// the build script this means we'll be watching files and env vars.
15781588
// Otherwise if we haven't previously executed it we'll just start watching
15791589
// the whole crate.
1580-
let (gen_local, overridden) = build_script_local_fingerprints(build_runner, unit);
1590+
let (gen_local, overridden) = build_script_local_fingerprints(build_runner, unit)?;
15811591
let deps = &build_runner.build_explicit_deps[unit];
15821592
let local = (gen_local)(
15831593
deps,
@@ -1671,7 +1681,7 @@ See https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-change
16711681
fn build_script_local_fingerprints(
16721682
build_runner: &mut BuildRunner<'_, '_>,
16731683
unit: &Unit,
1674-
) -> (
1684+
) -> CargoResult<(
16751685
Box<
16761686
dyn FnOnce(
16771687
&BuildDeps,
@@ -1680,20 +1690,20 @@ fn build_script_local_fingerprints(
16801690
+ Send,
16811691
>,
16821692
bool,
1683-
) {
1693+
)> {
16841694
assert!(unit.mode.is_run_custom_build());
16851695
// First up, if this build script is entirely overridden, then we just
16861696
// return the hash of what we overrode it with. This is the easy case!
16871697
if let Some(fingerprint) = build_script_override_fingerprint(build_runner, unit) {
16881698
debug!("override local fingerprints deps {}", unit.pkg);
1689-
return (
1699+
return Ok((
16901700
Box::new(
16911701
move |_: &BuildDeps, _: Option<&dyn Fn() -> CargoResult<String>>| {
16921702
Ok(Some(vec![fingerprint]))
16931703
},
16941704
),
16951705
true, // this is an overridden build script
1696-
);
1706+
));
16971707
}
16981708

16991709
// ... Otherwise this is a "real" build script and we need to return a real
@@ -1705,6 +1715,7 @@ fn build_script_local_fingerprints(
17051715
// obvious.
17061716
let pkg_root = unit.pkg.root().to_path_buf();
17071717
let target_dir = target_root(build_runner);
1718+
let env_config = Arc::clone(build_runner.bcx.gctx.env_config()?);
17081719
let calculate =
17091720
move |deps: &BuildDeps, pkg_fingerprint: Option<&dyn Fn() -> CargoResult<String>>| {
17101721
if deps.rerun_if_changed.is_empty() && deps.rerun_if_env_changed.is_empty() {
@@ -1734,11 +1745,16 @@ fn build_script_local_fingerprints(
17341745
// Ok so now we're in "new mode" where we can have files listed as
17351746
// dependencies as well as env vars listed as dependencies. Process
17361747
// them all here.
1737-
Ok(Some(local_fingerprints_deps(deps, &target_dir, &pkg_root)))
1748+
Ok(Some(local_fingerprints_deps(
1749+
deps,
1750+
&target_dir,
1751+
&pkg_root,
1752+
&env_config,
1753+
)))
17381754
};
17391755

17401756
// Note that `false` == "not overridden"
1741-
(Box::new(calculate), false)
1757+
Ok((Box::new(calculate), false))
17421758
}
17431759

17441760
/// Create a [`LocalFingerprint`] for an overridden build script.
@@ -1769,6 +1785,7 @@ fn local_fingerprints_deps(
17691785
deps: &BuildDeps,
17701786
target_root: &Path,
17711787
pkg_root: &Path,
1788+
env_config: &Arc<HashMap<String, OsString>>,
17721789
) -> Vec<LocalFingerprint> {
17731790
debug!("new local fingerprints deps {:?}", pkg_root);
17741791
let mut local = Vec::new();
@@ -1793,7 +1810,7 @@ fn local_fingerprints_deps(
17931810
local.extend(
17941811
deps.rerun_if_env_changed
17951812
.iter()
1796-
.map(LocalFingerprint::from_env),
1813+
.map(|s| LocalFingerprint::from_env(s, env_config)),
17971814
);
17981815

17991816
local

tests/testsuite/build_script_env.rs

+2
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)