Skip to content

Commit d86d65b

Browse files
committed
Auto merge of #118368 - GuillaumeGomez:env-flag, r=Nilstrieb
Implement `--env` compiler flag (without `tracked_env` support) Part of #80792. Implementation of rust-lang/compiler-team#653. Not an implementation of rust-lang/rfcs#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
2 parents ec41761 + dc2f77a commit d86d65b

9 files changed

Lines changed: 107 additions & 3 deletions

File tree

‎compiler/rustc_builtin_macros/src/env.rs‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ use thin_vec::thin_vec;
1313

1414
usecrate::errors;
1515

16+
fnlookup_env<'cx>(cx:&'cxExtCtxt<'_>,var:Symbol) -> Option<Symbol>{
17+
let var = var.as_str();
18+
ifletSome(value) = cx.sess.opts.logical_env.get(var){
19+
returnSome(Symbol::intern(value));
20+
}
21+
// If the environment variable was not defined with the `--env` option, we try to retrieve it
22+
// from rustc's environment.
23+
env::var(var).ok().as_deref().map(Symbol::intern)
24+
}
25+
1626
pubfnexpand_option_env<'cx>(
1727
cx:&'cxmutExtCtxt<'_>,
1828
sp:Span,
@@ -23,7 +33,7 @@ pub fn expand_option_env<'cx>(
2333
};
2434

2535
let sp = cx.with_def_site_ctxt(sp);
26-
let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
36+
let value = lookup_env(cx,var);
2737
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
2838
let e = match value {
2939
None => {
@@ -77,7 +87,7 @@ pub fn expand_env<'cx>(
7787
};
7888

7989
let span = cx.with_def_site_ctxt(sp);
80-
let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
90+
let value = lookup_env(cx,var);
8191
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
8292
let e = match value {
8393
None => {

‎compiler/rustc_session/src/config.rs‎

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::search_paths::SearchPath;
88
usecrate::utils::{CanonicalizedPath,NativeLib,NativeLibKind};
99
usecrate::{lint,HashStableContext};
1010
usecrate::{EarlyErrorHandler,Session};
11-
use rustc_data_structures::fx::{FxHashMap,FxHashSet,FxIndexSet};
11+
use rustc_data_structures::fx::{FxHashMap,FxHashSet,FxIndexMap,FxIndexSet};
1212
use rustc_data_structures::stable_hasher::{StableOrd,ToStableHashKey};
1313
use rustc_errors::emitter::HumanReadableErrorType;
1414
use rustc_errors::{ColorConfig,DiagnosticArgValue,HandlerFlags,IntoDiagnosticArg};
@@ -1114,6 +1114,7 @@ impl Default for Options {
11141114
pretty:None,
11151115
working_dir:RealFileName::LocalPath(std::env::current_dir().unwrap()),
11161116
color:ColorConfig::Auto,
1117+
logical_env:FxIndexMap::default(),
11171118
}
11181119
}
11191120
}
@@ -1813,6 +1814,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
18131814
"Remap source names in all output (compiler messages and output files)",
18141815
"FROM=TO",
18151816
),
1817+
opt::multi("","env","Inject an environment variable","VAR=VALUE"),
18161818
]);
18171819
opts
18181820
}
@@ -2592,6 +2594,23 @@ fn parse_remap_path_prefix(
25922594
mapping
25932595
}
25942596

2597+
fnparse_logical_env(
2598+
handler:&mutEarlyErrorHandler,
2599+
matches:&getopts::Matches,
2600+
) -> FxIndexMap<String,String>{
2601+
letmut vars = FxIndexMap::default();
2602+
2603+
for arg in matches.opt_strs("env"){
2604+
ifletSome((name, val)) = arg.split_once('='){
2605+
vars.insert(name.to_string(), val.to_string());
2606+
}else{
2607+
handler.early_error(format!("`--env`: specify value for variable `{arg}`"));
2608+
}
2609+
}
2610+
2611+
vars
2612+
}
2613+
25952614
// JUSTIFICATION: before wrapper fn is available
25962615
#[allow(rustc::bad_opt_access)]
25972616
pubfnbuild_session_options(
@@ -2830,6 +2849,8 @@ pub fn build_session_options(
28302849
handler.early_error("can't dump dependency graph without `-Z query-dep-graph`");
28312850
}
28322851

2852+
let logical_env = parse_logical_env(handler, matches);
2853+
28332854
// Try to find a directory containing the Rust `src`, for more details see
28342855
// the doc comment on the `real_rust_source_base_dir` field.
28352856
let tmp_buf;
@@ -2910,6 +2931,7 @@ pub fn build_session_options(
29102931
pretty,
29112932
working_dir,
29122933
color,
2934+
logical_env,
29132935
}
29142936
}
29152937

@@ -3184,6 +3206,7 @@ pub(crate) mod dep_tracking {
31843206
};
31853207
usecrate::lint;
31863208
usecrate::utils::NativeLib;
3209+
use rustc_data_structures::fx::FxIndexMap;
31873210
use rustc_data_structures::stable_hasher::Hash64;
31883211
use rustc_errors::LanguageIdentifier;
31893212
use rustc_feature::UnstableFeatures;
@@ -3342,6 +3365,21 @@ pub(crate) mod dep_tracking {
33423365
}
33433366
}
33443367

3368+
impl<T:DepTrackingHash,V:DepTrackingHash>DepTrackingHashforFxIndexMap<T,V>{
3369+
fnhash(
3370+
&self,
3371+
hasher:&mutDefaultHasher,
3372+
error_format:ErrorOutputType,
3373+
for_crate_hash:bool,
3374+
){
3375+
Hash::hash(&self.len(), hasher);
3376+
for(key, value)inself.iter(){
3377+
DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
3378+
DepTrackingHash::hash(value, hasher, error_format, for_crate_hash);
3379+
}
3380+
}
3381+
}
3382+
33453383
implDepTrackingHashforOutputTypes{
33463384
fnhash(
33473385
&self,

‎compiler/rustc_session/src/options.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::config::*;
33
usecrate::search_paths::SearchPath;
44
usecrate::utils::NativeLib;
55
usecrate::{lint,EarlyErrorHandler};
6+
use rustc_data_structures::fx::FxIndexMap;
67
use rustc_data_structures::profiling::TimePassesFormat;
78
use rustc_data_structures::stable_hasher::Hash64;
89
use rustc_errors::ColorConfig;
@@ -150,6 +151,9 @@ top_level_options!(
150151

151152
target_triple:TargetTriple[TRACKED],
152153

154+
/// Effective logical environment used by `env!`/`option_env!` macros
155+
logical_env:FxIndexMap<String,String> [TRACKED],
156+
153157
test:bool[TRACKED],
154158
error_format:ErrorOutputType[UNTRACKED],
155159
diagnostic_width:Option<usize> [UNTRACKED],
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# `env`
2+
3+
The tracking issue for this feature is: [#118372](https://github.com/rust-lang/rust/issues/118372).
4+
5+
------------------------
6+
7+
This option flag allows to specify environment variables value at compile time to be
8+
used by `env!` and `option_env!` macros.
9+
10+
When retrieving an environment variable value, the one specified by `--env` will take
11+
precedence. For example, if you want have `PATH=a` in your environment and pass:
12+
13+
```bash
14+
rustc --env PATH=env
15+
```
16+
17+
Then you will have:
18+
19+
```rust,no_run
20+
assert_eq!(env!("PATH"), "env");
21+
```
22+
23+
Please note that on Windows, environment variables are case insensitive but case
24+
preserving whereas `rustc`'s environment variables are case sensitive. For example,
25+
having `Path` in your environment (case insensitive) is different than using
26+
`rustc --env Path=...` (case sensitive).
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// run-pass
2+
// rustc-env:MY_VAR=tadam
3+
// compile-flags: --env MY_VAR=123abc -Zunstable-options
4+
5+
// This test ensures that variables provided with `--env` take precedence over
6+
// variables from environment.
7+
fnmain(){
8+
assert_eq!(env!("MY_VAR"),"123abc");
9+
}

‎tests/ui/extenv/extenv-env.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// compile-flags: --env FOO=123abc -Zunstable-options
2+
// run-pass
3+
fnmain(){
4+
assert_eq!(env!("FOO"),"123abc");
5+
}

‎tests/ui/extenv/extenv-not-env.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// run-pass
2+
// rustc-env:MY_ENV=/
3+
// Ensures that variables not defined through `--env` are still available.
4+
5+
fnmain(){
6+
assert!(!env!("MY_ENV").is_empty());
7+
}

‎tests/ui/feature-gates/env-flag.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// compile-flags: --env A=B
2+
3+
fnmain(){}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: the `-Z unstable-options` flag must also be passed to enable the flag `env`
2+

0 commit comments

Comments
 (0)