1 //! Run bootstrap from any subdirectory of a rust compiler checkout.
3 //! We prefer `exec`, to avoid adding an extra process in the process tree.
4 //! However, since `exec` isn't available on Windows, we indirect through
5 //! `exec_or_status`, which will call `exec` on unix and `status` on Windows.
7 //! We use `powershell.exe x.ps1` on Windows, and `sh -c x` on Unix, those are
8 //! the ones that call `x.py`. We use `sh -c` on Unix, because it is a standard.
9 //! We also don't use `pwsh` on Windows, because it is not installed by default;
14 process::{self, Command, ExitStatus},
18 fn x_command(dir: &Path) -> Command {
19 let mut cmd = Command::new("powershell.exe");
34 fn x_command(dir: &Path) -> Command {
35 Command::new(dir.join("x"))
38 #[cfg(not(any(windows, unix)))]
39 fn x_command(_dir: &Path) -> Command {
40 compile_error!("Unsupported platform");
44 fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
45 use std::os::unix::process::CommandExt;
50 fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
55 match env::args().skip(1).next().as_deref() {
56 Some("--wrapper-version") => {
57 let version = env!("CARGO_PKG_VERSION");
58 println!("{}", version);
63 let current = match env::current_dir() {
66 eprintln!("Failed to get current directory: {err}");
71 for dir in current.ancestors() {
72 let candidate = dir.join("x.py");
74 if candidate.exists() {
75 let mut cmd = x_command(dir);
77 cmd.args(env::args().skip(1)).current_dir(dir);
79 let result = exec_or_status(&mut cmd);
83 eprintln!("Failed to invoke `{:?}`: {}", cmd, error);
86 process::exit(status.code().unwrap_or(1));
93 "x.py not found. Please run inside of a checkout of `https://github.com/rust-lang/rust`."