Skip to content

Commit

Permalink
fix: envs in config can trigger rebuild by custom build script with `…
Browse files Browse the repository at this point in the history
…rerun-if-env-changed`.
  • Loading branch information
linyihai committed Oct 31, 2024
1 parent bc76779 commit 0ce1d7d
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
46 changes: 38 additions & 8 deletions src/cargo/core/compiler/fingerprint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ use std::time::SystemTime;
use anyhow::{bail, format_err, Context as _};
use cargo_util::{paths, ProcessBuilder, Sha256};
use filetime::FileTime;
use lazycell::LazyCell;
use serde::de;
use serde::ser;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -792,14 +793,36 @@ pub enum StaleItem {
impl LocalFingerprint {
/// Read the environment variable of the given env `key`, and creates a new
/// [`LocalFingerprint::RerunIfEnvChanged`] for it.
///
// TODO: This is allowed at this moment. Should figure out if it makes
// sense if permitting to read env from the config system.
#[allow(clippy::disallowed_methods)]
fn from_env<K: AsRef<str>>(key: K) -> LocalFingerprint {
fn from_env<K: AsRef<str>>(
key: K,
env_config: &Arc<HashMap<String, OsString>>,
env_config_insensitive: &Arc<LazyCell<HashMap<String, OsString>>>,
) -> LocalFingerprint {
let key = key.as_ref();
let var = key.to_owned();
let val = env::var(key).ok();
let val = if let Some(val) = env::var(key).ok() {
Some(val)
} else {
match env_config.get(key) {
Some(value) => value.to_str().map(|s| s.to_string()),
None => {
if cfg!(windows) {
env_config_insensitive
.borrow_with(|| {
env_config
.iter()
.map(|(k, v)| (k.to_uppercase().clone(), v.clone()))
.collect::<HashMap<String, OsString>>()
})
.get(&key.to_uppercase())
.and_then(|s| s.to_str().map(|s| s.to_string()))
} else {
None
}
}
}
};
LocalFingerprint::RerunIfEnvChanged { var, val }
}

Expand Down Expand Up @@ -1697,6 +1720,7 @@ fn build_script_local_fingerprints(
// obvious.
let pkg_root = unit.pkg.root().to_path_buf();
let target_dir = target_root(build_runner);
let env_config = Arc::clone(build_runner.bcx.gctx.env_config().unwrap());
let calculate =
move |deps: &BuildDeps, pkg_fingerprint: Option<&dyn Fn() -> CargoResult<String>>| {
if deps.rerun_if_changed.is_empty() && deps.rerun_if_env_changed.is_empty() {
Expand Down Expand Up @@ -1726,7 +1750,12 @@ fn build_script_local_fingerprints(
// Ok so now we're in "new mode" where we can have files listed as
// dependencies as well as env vars listed as dependencies. Process
// them all here.
Ok(Some(local_fingerprints_deps(deps, &target_dir, &pkg_root)))
Ok(Some(local_fingerprints_deps(
deps,
&target_dir,
&pkg_root,
&env_config,
)))
};

// Note that `false` == "not overridden"
Expand Down Expand Up @@ -1761,6 +1790,7 @@ fn local_fingerprints_deps(
deps: &BuildDeps,
target_root: &Path,
pkg_root: &Path,
env_config: &Arc<HashMap<String, OsString>>,
) -> Vec<LocalFingerprint> {
debug!("new local fingerprints deps {:?}", pkg_root);
let mut local = Vec::new();
Expand All @@ -1781,11 +1811,11 @@ fn local_fingerprints_deps(
.collect();
local.push(LocalFingerprint::RerunIfChanged { output, paths });
}

let env_config_insensitive = Arc::new(LazyCell::new());
local.extend(
deps.rerun_if_env_changed
.iter()
.map(LocalFingerprint::from_env),
.map(|s| LocalFingerprint::from_env(s, env_config, &env_config_insensitive)),
);

local
Expand Down
3 changes: 3 additions & 0 deletions tests/testsuite/build_script_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ fn env_config_rerun_if_changed() {
);
p.cargo("check")
.with_stderr_data(str![[r#"
[COMPILING] foo v0.0.1 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
"#]])
Expand Down Expand Up @@ -473,6 +474,7 @@ fn insensitive_env_config_rerun_if_changed() {
);
p.cargo("check")
.with_stderr_data(str![[r#"
[COMPILING] foo v0.0.1 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
"#]])
Expand Down Expand Up @@ -516,6 +518,7 @@ fn env_config_newly_added_rerun() {
);
p.cargo("check")
.with_stderr_data(str![[r#"
[COMPILING] foo v0.0.1 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
"#]])
Expand Down

0 comments on commit 0ce1d7d

Please sign in to comment.