Skip to content

Commit

Permalink
Rollup merge of rust-lang#39888 - nagisa:on-fail-bootstrap, r=alexcri…
Browse files Browse the repository at this point in the history
…chton

[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 rust-lang#38686
Fixes rust-lang#38221
  • Loading branch information
eddyb authored Feb 25, 2017
2 parents ad9079b + 0e45a5e commit e31d464
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/bootstrap/bin/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ fn main() {
};
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
let mut on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));

let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
Expand Down Expand Up @@ -217,9 +218,20 @@ fn main() {
}

// Actually run the compiler!
std::process::exit(match exec_cmd(&mut cmd) {
Ok(s) => s.code().unwrap_or(0xfe),
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
std::process::exit(if let Some(ref mut on_fail) = on_fail {
match cmd.status() {
Ok(s) if s.success() => 0,
_ => {
println!("\nDid not run successfully:\n{:?}\n-------------", cmd);
exec_cmd(on_fail).expect("could not run the backup command");
1
}
}
} else {
std::process::exit(match exec_cmd(&mut cmd) {
Ok(s) => s.code().unwrap_or(0xfe),
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
})
})
}

Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use step;
/// Deserialized version of all flags for this compile.
pub struct Flags {
pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
pub on_fail: Option<String>,
pub stage: Option<u32>,
pub keep_stage: Option<u32>,
pub build: String,
Expand Down Expand Up @@ -81,6 +82,7 @@ impl Flags {
opts.optopt("", "build", "build target of the stage0 compiler", "BUILD");
opts.optmulti("", "host", "host targets to build", "HOST");
opts.optmulti("", "target", "target targets to build", "TARGET");
opts.optopt("", "on-fail", "command to run on failure", "CMD");
opts.optopt("", "stage", "stage to build", "N");
opts.optopt("", "keep-stage", "stage to keep without recompiling", "N");
opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
Expand Down Expand Up @@ -283,6 +285,7 @@ To learn more about a subcommand, run `./x.py <command> -h`
Flags {
verbose: m.opt_count("v"),
stage: stage,
on_fail: m.opt_str("on-fail"),
keep_stage: m.opt_str("keep-stage").map(|j| j.parse().unwrap()),
build: m.opt_str("build").unwrap_or_else(|| {
env::var("BUILD").unwrap()
Expand Down
4 changes: 4 additions & 0 deletions src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,10 @@ impl Build {
cargo.env("RUSTC_INCREMENTAL", incr_dir);
}

if let Some(ref on_fail) = self.flags.on_fail {
cargo.env("RUSTC_ON_FAIL", on_fail);
}

let verbose = cmp::max(self.config.verbose, self.flags.verbose);
cargo.env("RUSTC_VERBOSE", format!("{}", verbose));

Expand Down

0 comments on commit e31d464

Please sign in to comment.