Skip to content

Commit 0e45a5e

Browse files
committed
[rustbuild] add a way to run command after failure
This is a simple way to workaround the debugging issues caused by the rustc wrapper used in the bootstrap process. Namely, it uses some obscure environment variables and you can’t just copy the failed command and run it in the shell or debugger to examine the failure more closely. With `--on-fail` its possible to run an arbitrary command within exactly the same environment under which rustc failed. Theres’s multiple ways to use this new flag: $ python x.py build --stage=1 --on-fail=env would print a list of environment variables and the failed command, so a few copy-pastes and you now can run the same rust in your shell outside the bootstrap system. $ python x.py build --stage=1 --on-fail=bash Is a more useful variation of the command above in that it launches a whole shell with environment already in place! All that’s left to do is copy-paste the command just above the shell prompt! Fixes #38686 Fixes #38221
1 parent 62eb605 commit 0e45a5e

File tree

3 files changed

+22
-3
lines changed

3 files changed

+22
-3
lines changed

Diff for: src/bootstrap/bin/rustc.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ fn main() {
6868
};
6969
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
7070
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
71+
let mut on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));
7172

7273
let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
7374
let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
@@ -212,9 +213,20 @@ fn main() {
212213
}
213214

214215
// Actually run the compiler!
215-
std::process::exit(match exec_cmd(&mut cmd) {
216-
Ok(s) => s.code().unwrap_or(0xfe),
217-
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
216+
std::process::exit(if let Some(ref mut on_fail) = on_fail {
217+
match cmd.status() {
218+
Ok(s) if s.success() => 0,
219+
_ => {
220+
println!("\nDid not run successfully:\n{:?}\n-------------", cmd);
221+
exec_cmd(on_fail).expect("could not run the backup command");
222+
1
223+
}
224+
}
225+
} else {
226+
std::process::exit(match exec_cmd(&mut cmd) {
227+
Ok(s) => s.code().unwrap_or(0xfe),
228+
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
229+
})
218230
})
219231
}
220232

Diff for: src/bootstrap/flags.rs

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use step;
2828
/// Deserialized version of all flags for this compile.
2929
pub struct Flags {
3030
pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
31+
pub on_fail: Option<String>,
3132
pub stage: Option<u32>,
3233
pub keep_stage: Option<u32>,
3334
pub build: String,
@@ -81,6 +82,7 @@ impl Flags {
8182
opts.optopt("", "build", "build target of the stage0 compiler", "BUILD");
8283
opts.optmulti("", "host", "host targets to build", "HOST");
8384
opts.optmulti("", "target", "target targets to build", "TARGET");
85+
opts.optopt("", "on-fail", "command to run on failure", "CMD");
8486
opts.optopt("", "stage", "stage to build", "N");
8587
opts.optopt("", "keep-stage", "stage to keep without recompiling", "N");
8688
opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
@@ -283,6 +285,7 @@ To learn more about a subcommand, run `./x.py <command> -h`
283285
Flags {
284286
verbose: m.opt_count("v"),
285287
stage: stage,
288+
on_fail: m.opt_str("on-fail"),
286289
keep_stage: m.opt_str("keep-stage").map(|j| j.parse().unwrap()),
287290
build: m.opt_str("build").unwrap_or_else(|| {
288291
env::var("BUILD").unwrap()

Diff for: src/bootstrap/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,10 @@ impl Build {
499499
cargo.env("RUSTC_INCREMENTAL", incr_dir);
500500
}
501501

502+
if let Some(ref on_fail) = self.flags.on_fail {
503+
cargo.env("RUSTC_ON_FAIL", on_fail);
504+
}
505+
502506
let verbose = cmp::max(self.config.verbose, self.flags.verbose);
503507
cargo.env("RUSTC_VERBOSE", format!("{}", verbose));
504508

0 commit comments

Comments
 (0)