mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 06:51:58 +00:00
Auto merge of #118368 - GuillaumeGomez:env-flag, r=Nilstrieb
Implement `--env` compiler flag (without `tracked_env` support) Part of https://github.com/rust-lang/rust/issues/80792. Implementation of https://github.com/rust-lang/compiler-team/issues/653. Not an implementation of https://github.com/rust-lang/rfcs/pull/2794. It adds the `--env` compiler flag option which allows to set environment values used by `env!` and `option_env!`. Important to note: When trying to retrieve an environment variable value, it will first look into the ones defined with `--env`, and if there isn't one, then only it will look into the environment variables. So if you use `--env PATH=a`, then `env!("PATH")` will return `"a"` and not the actual `PATH` value. As mentioned in the title, `tracked_env` support is not added here. I'll do it in a follow-up PR. r? rust-lang/compiler
This commit is contained in:
commit
d86d65bbc1
@ -13,6 +13,16 @@ use thin_vec::thin_vec;
|
||||
|
||||
use crate::errors;
|
||||
|
||||
fn lookup_env<'cx>(cx: &'cx ExtCtxt<'_>, var: Symbol) -> Option<Symbol> {
|
||||
let var = var.as_str();
|
||||
if let Some(value) = cx.sess.opts.logical_env.get(var) {
|
||||
return Some(Symbol::intern(value));
|
||||
}
|
||||
// If the environment variable was not defined with the `--env` option, we try to retrieve it
|
||||
// from rustc's environment.
|
||||
env::var(var).ok().as_deref().map(Symbol::intern)
|
||||
}
|
||||
|
||||
pub fn expand_option_env<'cx>(
|
||||
cx: &'cx mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
@ -23,7 +33,7 @@ pub fn expand_option_env<'cx>(
|
||||
};
|
||||
|
||||
let sp = cx.with_def_site_ctxt(sp);
|
||||
let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
|
||||
let value = lookup_env(cx, var);
|
||||
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
|
||||
let e = match value {
|
||||
None => {
|
||||
@ -77,7 +87,7 @@ pub fn expand_env<'cx>(
|
||||
};
|
||||
|
||||
let span = cx.with_def_site_ctxt(sp);
|
||||
let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
|
||||
let value = lookup_env(cx, var);
|
||||
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
|
||||
let e = match value {
|
||||
None => {
|
||||
|
@ -8,7 +8,7 @@ use crate::search_paths::SearchPath;
|
||||
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
|
||||
use crate::{lint, HashStableContext};
|
||||
use crate::{EarlyErrorHandler, Session};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
|
||||
use rustc_errors::emitter::HumanReadableErrorType;
|
||||
use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg};
|
||||
@ -1114,6 +1114,7 @@ impl Default for Options {
|
||||
pretty: None,
|
||||
working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()),
|
||||
color: ColorConfig::Auto,
|
||||
logical_env: FxIndexMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1813,6 +1814,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
|
||||
"Remap source names in all output (compiler messages and output files)",
|
||||
"FROM=TO",
|
||||
),
|
||||
opt::multi("", "env", "Inject an environment variable", "VAR=VALUE"),
|
||||
]);
|
||||
opts
|
||||
}
|
||||
@ -2592,6 +2594,23 @@ fn parse_remap_path_prefix(
|
||||
mapping
|
||||
}
|
||||
|
||||
fn parse_logical_env(
|
||||
handler: &mut EarlyErrorHandler,
|
||||
matches: &getopts::Matches,
|
||||
) -> FxIndexMap<String, String> {
|
||||
let mut vars = FxIndexMap::default();
|
||||
|
||||
for arg in matches.opt_strs("env") {
|
||||
if let Some((name, val)) = arg.split_once('=') {
|
||||
vars.insert(name.to_string(), val.to_string());
|
||||
} else {
|
||||
handler.early_error(format!("`--env`: specify value for variable `{arg}`"));
|
||||
}
|
||||
}
|
||||
|
||||
vars
|
||||
}
|
||||
|
||||
// JUSTIFICATION: before wrapper fn is available
|
||||
#[allow(rustc::bad_opt_access)]
|
||||
pub fn build_session_options(
|
||||
@ -2830,6 +2849,8 @@ pub fn build_session_options(
|
||||
handler.early_error("can't dump dependency graph without `-Z query-dep-graph`");
|
||||
}
|
||||
|
||||
let logical_env = parse_logical_env(handler, matches);
|
||||
|
||||
// Try to find a directory containing the Rust `src`, for more details see
|
||||
// the doc comment on the `real_rust_source_base_dir` field.
|
||||
let tmp_buf;
|
||||
@ -2910,6 +2931,7 @@ pub fn build_session_options(
|
||||
pretty,
|
||||
working_dir,
|
||||
color,
|
||||
logical_env,
|
||||
}
|
||||
}
|
||||
|
||||
@ -3184,6 +3206,7 @@ pub(crate) mod dep_tracking {
|
||||
};
|
||||
use crate::lint;
|
||||
use crate::utils::NativeLib;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::stable_hasher::Hash64;
|
||||
use rustc_errors::LanguageIdentifier;
|
||||
use rustc_feature::UnstableFeatures;
|
||||
@ -3342,6 +3365,21 @@ pub(crate) mod dep_tracking {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: DepTrackingHash, V: DepTrackingHash> DepTrackingHash for FxIndexMap<T, V> {
|
||||
fn hash(
|
||||
&self,
|
||||
hasher: &mut DefaultHasher,
|
||||
error_format: ErrorOutputType,
|
||||
for_crate_hash: bool,
|
||||
) {
|
||||
Hash::hash(&self.len(), hasher);
|
||||
for (key, value) in self.iter() {
|
||||
DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
|
||||
DepTrackingHash::hash(value, hasher, error_format, for_crate_hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DepTrackingHash for OutputTypes {
|
||||
fn hash(
|
||||
&self,
|
||||
|
@ -3,6 +3,7 @@ use crate::config::*;
|
||||
use crate::search_paths::SearchPath;
|
||||
use crate::utils::NativeLib;
|
||||
use crate::{lint, EarlyErrorHandler};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::profiling::TimePassesFormat;
|
||||
use rustc_data_structures::stable_hasher::Hash64;
|
||||
use rustc_errors::ColorConfig;
|
||||
@ -150,6 +151,9 @@ top_level_options!(
|
||||
|
||||
target_triple: TargetTriple [TRACKED],
|
||||
|
||||
/// Effective logical environment used by `env!`/`option_env!` macros
|
||||
logical_env: FxIndexMap<String, String> [TRACKED],
|
||||
|
||||
test: bool [TRACKED],
|
||||
error_format: ErrorOutputType [UNTRACKED],
|
||||
diagnostic_width: Option<usize> [UNTRACKED],
|
||||
|
26
src/doc/unstable-book/src/compiler-flags/env.md
Normal file
26
src/doc/unstable-book/src/compiler-flags/env.md
Normal file
@ -0,0 +1,26 @@
|
||||
# `env`
|
||||
|
||||
The tracking issue for this feature is: [#118372](https://github.com/rust-lang/rust/issues/118372).
|
||||
|
||||
------------------------
|
||||
|
||||
This option flag allows to specify environment variables value at compile time to be
|
||||
used by `env!` and `option_env!` macros.
|
||||
|
||||
When retrieving an environment variable value, the one specified by `--env` will take
|
||||
precedence. For example, if you want have `PATH=a` in your environment and pass:
|
||||
|
||||
```bash
|
||||
rustc --env PATH=env
|
||||
```
|
||||
|
||||
Then you will have:
|
||||
|
||||
```rust,no_run
|
||||
assert_eq!(env!("PATH"), "env");
|
||||
```
|
||||
|
||||
Please note that on Windows, environment variables are case insensitive but case
|
||||
preserving whereas `rustc`'s environment variables are case sensitive. For example,
|
||||
having `Path` in your environment (case insensitive) is different than using
|
||||
`rustc --env Path=...` (case sensitive).
|
9
tests/ui/extenv/extenv-env-overload.rs
Normal file
9
tests/ui/extenv/extenv-env-overload.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// run-pass
|
||||
// rustc-env:MY_VAR=tadam
|
||||
// compile-flags: --env MY_VAR=123abc -Zunstable-options
|
||||
|
||||
// This test ensures that variables provided with `--env` take precedence over
|
||||
// variables from environment.
|
||||
fn main() {
|
||||
assert_eq!(env!("MY_VAR"), "123abc");
|
||||
}
|
5
tests/ui/extenv/extenv-env.rs
Normal file
5
tests/ui/extenv/extenv-env.rs
Normal file
@ -0,0 +1,5 @@
|
||||
// compile-flags: --env FOO=123abc -Zunstable-options
|
||||
// run-pass
|
||||
fn main() {
|
||||
assert_eq!(env!("FOO"), "123abc");
|
||||
}
|
7
tests/ui/extenv/extenv-not-env.rs
Normal file
7
tests/ui/extenv/extenv-not-env.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// run-pass
|
||||
// rustc-env:MY_ENV=/
|
||||
// Ensures that variables not defined through `--env` are still available.
|
||||
|
||||
fn main() {
|
||||
assert!(!env!("MY_ENV").is_empty());
|
||||
}
|
3
tests/ui/feature-gates/env-flag.rs
Normal file
3
tests/ui/feature-gates/env-flag.rs
Normal file
@ -0,0 +1,3 @@
|
||||
// compile-flags: --env A=B
|
||||
|
||||
fn main() {}
|
2
tests/ui/feature-gates/env-flag.stderr
Normal file
2
tests/ui/feature-gates/env-flag.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
error: the `-Z unstable-options` flag must also be passed to enable the flag `env`
|
||||
|
Loading…
Reference in New Issue
Block a user