From f91dc782245cc5fcf75f9acc191ee9b018605328 Mon Sep 17 00:00:00 2001 From: heisen-li Date: Thu, 18 Jul 2024 17:25:07 +0800 Subject: [PATCH] fix(env):Get environment variables from the latest environment config --- .../compiler/build_context/target_info.rs | 6 ++ src/cargo/core/compiler/fingerprint/mod.rs | 51 +++++++++++--- tests/testsuite/build_script_env.rs | 69 +++++++------------ 3 files changed, 75 insertions(+), 51 deletions(-) diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index ed4b04dc228..3082abecea3 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -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}; @@ -588,6 +590,10 @@ impl TargetInfo { .iter() .any(|sup| sup.as_str() == split.as_str()) } + + pub fn get_target_envs(&self) -> &BTreeMap> { + return self.crate_type_process.get_envs(); + } } /// Takes rustc output (using specialized command line args), and calculates the file prefix and diff --git a/src/cargo/core/compiler/fingerprint/mod.rs b/src/cargo/core/compiler/fingerprint/mod.rs index 9d9eb4e4da4..8e972c8d608 100644 --- a/src/cargo/core/compiler/fingerprint/mod.rs +++ b/src/cargo/core/compiler/fingerprint/mod.rs @@ -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}; @@ -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>(key: K) -> LocalFingerprint { - let key = key.as_ref(); + fn from_env>( + key: K, + envs: &BTreeMap>, + ) -> LocalFingerprint { + fn get_envs_case_insensitive( + key: &str, + envs: &BTreeMap>, + ) -> Option { + 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 = 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 } } @@ -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) { @@ -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" @@ -1695,6 +1729,7 @@ fn local_fingerprints_deps( deps: &BuildDeps, target_root: &Path, pkg_root: &Path, + envs: &BTreeMap>, ) -> Vec { debug!("new local fingerprints deps {:?}", pkg_root); let mut local = Vec::new(); @@ -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 diff --git a/tests/testsuite/build_script_env.rs b/tests/testsuite/build_script_env.rs index 5081d221fc7..0f923500046 100644 --- a/tests/testsuite/build_script_env.rs +++ b/tests/testsuite/build_script_env.rs @@ -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(); @@ -47,27 +47,18 @@ 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() {}") @@ -75,19 +66,19 @@ fn rerun_if_env_changes_config_windows() { ".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(); @@ -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(); } @@ -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 "#]])