Skip to content

Commit

Permalink
fix(env):Get environment variables from the latest environment config
Browse files Browse the repository at this point in the history
  • Loading branch information
heisen-li committed Jul 18, 2024
1 parent e0f523a commit f91dc78
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 51 deletions.
6 changes: 6 additions & 0 deletions src/cargo/core/compiler/build_context/target_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use cargo_util::{paths, ProcessBuilder};
use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use std::collections::hash_map::{Entry, HashMap};
use std::collections::BTreeMap;
use std::ffi::OsString;
use std::path::{Path, PathBuf};
use std::str::{self, FromStr};

Expand Down Expand Up @@ -588,6 +590,10 @@ impl TargetInfo {
.iter()
.any(|sup| sup.as_str() == split.as_str())
}

pub fn get_target_envs(&self) -> &BTreeMap<String, Option<OsString>> {
return self.crate_type_process.get_envs();
}
}

/// Takes rustc output (using specialized command line args), and calculates the file prefix and
Expand Down
51 changes: 43 additions & 8 deletions src/cargo/core/compiler/fingerprint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,9 @@ mod dirty_reason;

use std::collections::hash_map::{Entry, HashMap};

use std::collections::BTreeMap;
use std::env;
use std::ffi::OsString;
use std::hash::{self, Hash, Hasher};
use std::io;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -768,14 +770,35 @@ 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 {
let key = key.as_ref();
fn from_env<K: AsRef<str>>(
key: K,
envs: &BTreeMap<String, Option<OsString>>,
) -> LocalFingerprint {
fn get_envs_case_insensitive(
key: &str,
envs: &BTreeMap<String, Option<OsString>>,
) -> Option<OsString> {
let upper_case_key: String = key.to_uppercase();
for (k, v) in envs {
if k.to_uppercase().eq(&upper_case_key) {
return v.to_owned();
}
}
None
}

let key: &str = key.as_ref();
let var = key.to_owned();
let val = env::var(key).ok();

let val: Option<String> = if cfg!(windows) {
get_envs_case_insensitive(key, envs)
} else {
envs.get(key).and_then(|v| v.to_owned())
}
.or(env::var_os(key))
.and_then(|os_str| os_str.into_string().ok());

LocalFingerprint::RerunIfEnvChanged { var, val }
}

Expand Down Expand Up @@ -1608,6 +1631,12 @@ fn build_script_local_fingerprints(
bool,
) {
assert!(unit.mode.is_run_custom_build());
let envs = build_runner
.bcx
.target_data
.info(unit.kind)
.get_target_envs()
.clone();
// First up, if this build script is entirely overridden, then we just
// return the hash of what we overrode it with. This is the easy case!
if let Some(fingerprint) = build_script_override_fingerprint(build_runner, unit) {
Expand Down Expand Up @@ -1660,7 +1689,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,
&envs,
)))
};

// Note that `false` == "not overridden"
Expand Down Expand Up @@ -1695,6 +1729,7 @@ fn local_fingerprints_deps(
deps: &BuildDeps,
target_root: &Path,
pkg_root: &Path,
envs: &BTreeMap<String, Option<OsString>>,
) -> Vec<LocalFingerprint> {
debug!("new local fingerprints deps {:?}", pkg_root);
let mut local = Vec::new();
Expand All @@ -1719,7 +1754,7 @@ fn local_fingerprints_deps(
local.extend(
deps.rerun_if_env_changed
.iter()
.map(LocalFingerprint::from_env),
.map(|v| LocalFingerprint::from_env(v, &envs)),
);

local
Expand Down
69 changes: 26 additions & 43 deletions tests/testsuite/build_script_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ fn rerun_if_env_changes_config() {
.file(
"build.rs",
r#"
fn main() {
println!("cargo:rerun-if-env-changed=FOO");
if let Ok(foo) = std::env::var("FOO") {
assert!(&foo != "bad");
}
}
"#,
fn main() {
println!("cargo:rerun-if-env-changed=FOO");
if let Ok(foo) = std::env::var("FOO") {
assert!(&foo != "bad");
}
}
"#,
)
.build();

Expand All @@ -47,47 +47,38 @@ fn rerun_if_env_changes_config() {
);

p.cargo("check")
.with_status(101)
.with_stderr_data(str![[r#"
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
[COMPILING] foo v0.1.0 ([ROOT]/foo)
[ERROR] failed to run custom build command for `foo v0.1.0 ([ROOT]/foo)`
...
"#]])
.run();

p.cargo("clean").run();
p.cargo("check")
.with_status(101)
.with_stderr_data(
"\
[COMPILING] foo v0.1.0 ([ROOT]/foo)
[ERROR] failed to run custom build command for `foo v0.1.0 ([..])`
...",
)
.run();
}

#[cfg(windows)]
#[cargo_test]
fn rerun_if_env_changes_config_windows() {
fn rerun_if_env_changes_config_in_windows() {
let p = project()
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
.file("src/main.rs", "fn main() {}")
.file(
".cargo/config.toml",
r#"
[env]
FOO = "good"
Foo = "good"
"#,
)
.file(
"build.rs",
r#"
fn main() {
println!("cargo:rerun-if-env-changed=Foo");
if let Ok(foo) = std::env::var("Foo") {
assert!(&foo != "bad");
}
}
"#,
fn main() {
println!("cargo:rerun-if-env-changed=foo");
if let Ok(foo) = std::env::var("FOo") {
assert!(&foo != "bad");
}
}
"#,
)
.build();

Expand All @@ -103,26 +94,17 @@ fn rerun_if_env_changes_config_windows() {
".cargo/config.toml",
r#"
[env]
FOO = "bad"
FoO = "bad"
"#,
);

p.cargo("check")
.with_stderr_data(str![[r#"
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
"#]])
.run();

p.cargo("clean").run();
p.cargo("check")
.with_status(101)
.with_stderr_data(
"\
.with_stderr_data(str![[r#"
[COMPILING] foo v0.1.0 ([ROOT]/foo)
[ERROR] failed to run custom build command for `foo v0.1.0 ([..])`
...",
)
[ERROR] failed to run custom build command for `foo v0.1.0 ([ROOT]/foo)`
...
"#]])
.run();
}

Expand Down Expand Up @@ -158,6 +140,7 @@ fn rerun_if_env_changes_cargo_set_env_variable() {

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 f91dc78

Please sign in to comment.