diff options
| author | bors <bors@rust-lang.org> | 2020-06-25 22:52:59 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-06-25 22:52:59 +0000 |
| commit | 1033351a51dd3ca342a83d4be13f7554f0b4fb1e (patch) | |
| tree | de82ec4b5eefbef6f58767a7ac5c823fbf8776be | |
| parent | 50fc24d8a172a853b5dfe40702d6550e3b8562ba (diff) | |
| parent | 69b2179afe695d1a93b792cfd7c4197ca63ce658 (diff) | |
| download | rust-1033351a51dd3ca342a83d4be13f7554f0b4fb1e.tar.gz rust-1033351a51dd3ca342a83d4be13f7554f0b4fb1e.zip | |
Auto merge of #71858 - petrochenkov:env, r=Mark-Simulacrum
Print environment variables accessed by rustc as special comments into depinfo files So cargo (and perhaps others tools) can use them for linting (at least) or for actually rebuilding crates on env var changes. --- I've recently observed one more forgotten environment variable in a build script https://github.com/rust-lang/rust/pull/71314/commits/8a77d1ca3fc2df789157f7986ddbaf2a377ff0fe and thought it would be nice to provide the list of accessed variables to cargo automatically as a part of depinfo. Unsurprisingly, I wasn't the first who had this idea - cc https://github.com/rust-lang/rust/issues/70517 https://github.com/rust-lang/rust/issues/40364 https://github.com/rust-lang/rust/issues/44074. Also, there are dozens of uses of `(option_)env!` in rustc repo and, like, half of them are not registered in build scripts. --- Description: - depinfo files are extended with special comments containing info about environment variables accessed during compilation. - Comment format for environment variables with successfully retrieved value: `# env-dep:KEY=VALUE`. - Comment format for environment variables without successfully retrieved value: `# env-dep:KEY` (can happen with `option_env!`). - `KEY` and `VALUE` are minimally escaped (`\n`, `\r`, `\\`) so they don't break makefile comments and can be unescaped by anything that can unescape standard `escape_default` and friends. FCP report: https://github.com/rust-lang/rust/pull/71858#issuecomment-633071488 Closes https://github.com/rust-lang/rust/issues/70517 Closes https://github.com/rust-lang/rust/issues/40364 Closes https://github.com/rust-lang/rust/issues/44074 A new issue in the cargo repo will be needed to track the cargo side of this feature. r? @ehuss
| -rw-r--r-- | src/librustc_builtin_macros/env.rs | 18 | ||||
| -rw-r--r-- | src/librustc_builtin_macros/lib.rs | 1 | ||||
| -rw-r--r-- | src/librustc_interface/passes.rs | 35 | ||||
| -rw-r--r-- | src/librustc_session/parse.rs | 3 | ||||
| -rw-r--r-- | src/test/run-make/env-dep-info/Makefile | 8 | ||||
| -rw-r--r-- | src/test/run-make/env-dep-info/main.rs | 6 |
6 files changed, 64 insertions, 7 deletions
diff --git a/src/librustc_builtin_macros/env.rs b/src/librustc_builtin_macros/env.rs index d769ebb1f55..6c3a1ce0958 100644 --- a/src/librustc_builtin_macros/env.rs +++ b/src/librustc_builtin_macros/env.rs @@ -22,8 +22,10 @@ pub fn expand_option_env<'cx>( }; let sp = cx.with_def_site_ctxt(sp); - let e = match env::var(&var.as_str()) { - Err(..) => { + let value = env::var(&var.as_str()).ok().as_deref().map(Symbol::intern); + cx.parse_sess.env_depinfo.borrow_mut().insert((Symbol::intern(&var), value)); + let e = match value { + None => { let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp)); cx.expr_path(cx.path_all( sp, @@ -37,10 +39,10 @@ pub fn expand_option_env<'cx>( ))], )) } - Ok(s) => cx.expr_call_global( + Some(value) => cx.expr_call_global( sp, cx.std_path(&[sym::option, sym::Option, sym::Some]), - vec![cx.expr_str(sp, Symbol::intern(&s))], + vec![cx.expr_str(sp, value)], ), }; MacEager::expr(e) @@ -78,12 +80,14 @@ pub fn expand_env<'cx>( } let sp = cx.with_def_site_ctxt(sp); - let e = match env::var(&*var.as_str()) { - Err(_) => { + let value = env::var(&*var.as_str()).ok().as_deref().map(Symbol::intern); + cx.parse_sess.env_depinfo.borrow_mut().insert((var, value)); + let e = match value { + None => { cx.span_err(sp, &msg.as_str()); return DummyResult::any(sp); } - Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), + Some(value) => cx.expr_str(sp, value), }; MacEager::expr(e) } diff --git a/src/librustc_builtin_macros/lib.rs b/src/librustc_builtin_macros/lib.rs index a0f82d65618..f56d8a372a7 100644 --- a/src/librustc_builtin_macros/lib.rs +++ b/src/librustc_builtin_macros/lib.rs @@ -5,6 +5,7 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] +#![feature(inner_deref)] #![feature(nll)] #![feature(or_patterns)] #![feature(proc_macro_internals)] diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index e9a4119f4a3..ed5e715ce70 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -549,6 +549,22 @@ fn escape_dep_filename(filename: &FileName) -> String { filename.to_string().replace(" ", "\\ ") } +// Makefile comments only need escaping newlines and `\`. +// The result can be unescaped by anything that can unescape `escape_default` and friends. +fn escape_dep_env(symbol: Symbol) -> String { + let s = symbol.as_str(); + let mut escaped = String::with_capacity(s.len()); + for c in s.chars() { + match c { + '\n' => escaped.push_str(r"\n"), + '\r' => escaped.push_str(r"\r"), + '\\' => escaped.push_str(r"\\"), + _ => escaped.push(c), + } + } + escaped +} + fn write_out_deps( sess: &Session, boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>, @@ -604,6 +620,25 @@ fn write_out_deps( for path in files { writeln!(file, "{}:", path)?; } + + // Emit special comments with information about accessed environment variables. + let env_depinfo = sess.parse_sess.env_depinfo.borrow(); + if !env_depinfo.is_empty() { + let mut envs: Vec<_> = env_depinfo + .iter() + .map(|(k, v)| (escape_dep_env(*k), v.map(escape_dep_env))) + .collect(); + envs.sort_unstable(); + writeln!(file)?; + for (k, v) in envs { + write!(file, "# env-dep:{}", k)?; + if let Some(v) = v { + write!(file, "={}", v)?; + } + writeln!(file)?; + } + } + Ok(()) })(); diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index ddbc95fb1b0..93b27cabfb6 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -135,6 +135,8 @@ pub struct ParseSess { pub symbol_gallery: SymbolGallery, /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors. pub reached_eof: Lock<bool>, + /// Environment variables accessed during the build and their values when they exist. + pub env_depinfo: Lock<FxHashSet<(Symbol, Option<Symbol>)>>, } impl ParseSess { @@ -160,6 +162,7 @@ impl ParseSess { gated_spans: GatedSpans::default(), symbol_gallery: SymbolGallery::default(), reached_eof: Lock::new(false), + env_depinfo: Default::default(), } } diff --git a/src/test/run-make/env-dep-info/Makefile b/src/test/run-make/env-dep-info/Makefile new file mode 100644 index 00000000000..2be0b4b324b --- /dev/null +++ b/src/test/run-make/env-dep-info/Makefile @@ -0,0 +1,8 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + EXISTING_ENV=1 EXISTING_OPT_ENV=1 $(RUSTC) --emit dep-info main.rs + $(CGREP) "# env-dep:EXISTING_ENV=1" < $(TMPDIR)/main.d + $(CGREP) "# env-dep:EXISTING_OPT_ENV=1" < $(TMPDIR)/main.d + $(CGREP) "# env-dep:NONEXISTENT_OPT_ENV" < $(TMPDIR)/main.d + $(CGREP) "# env-dep:ESCAPE\nESCAPE\\" < $(TMPDIR)/main.d diff --git a/src/test/run-make/env-dep-info/main.rs b/src/test/run-make/env-dep-info/main.rs new file mode 100644 index 00000000000..a25246bac79 --- /dev/null +++ b/src/test/run-make/env-dep-info/main.rs @@ -0,0 +1,6 @@ +fn main() { + env!("EXISTING_ENV"); + option_env!("EXISTING_OPT_ENV"); + option_env!("NONEXISTENT_OPT_ENV"); + option_env!("ESCAPE\nESCAPE\\"); +} |
