]> git.lizzy.rs Git - rust.git/blob - src/tools/x/src/main.rs
Auto merge of #107843 - bjorn3:sync_cg_clif-2023-02-09, r=bjorn3
[rust.git] / src / tools / x / src / main.rs
1 //! Run bootstrap from any subdirectory of a rust compiler checkout.
2 //!
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.
6 //!
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;
10
11 use std::{
12     env, io,
13     path::Path,
14     process::{self, Command, ExitStatus},
15 };
16
17 #[cfg(windows)]
18 fn x_command(dir: &Path) -> Command {
19     let mut cmd = Command::new("powershell.exe");
20     cmd.args([
21         "-NoLogo",
22         "-NoProfile",
23         "-NonInteractive",
24         "-ExecutionPolicy",
25         "RemoteSigned",
26         "-Command",
27         "./x.ps1",
28     ])
29     .current_dir(dir);
30     cmd
31 }
32
33 #[cfg(unix)]
34 fn x_command(dir: &Path) -> Command {
35     Command::new(dir.join("x"))
36 }
37
38 #[cfg(not(any(windows, unix)))]
39 fn x_command(_dir: &Path) -> Command {
40     compile_error!("Unsupported platform");
41 }
42
43 #[cfg(unix)]
44 fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
45     use std::os::unix::process::CommandExt;
46     Err(command.exec())
47 }
48
49 #[cfg(not(unix))]
50 fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
51     command.status()
52 }
53
54 fn main() {
55     match env::args().skip(1).next().as_deref() {
56         Some("--wrapper-version") => {
57             let version = env!("CARGO_PKG_VERSION");
58             println!("{}", version);
59             return;
60         }
61         _ => {}
62     }
63     let current = match env::current_dir() {
64         Ok(dir) => dir,
65         Err(err) => {
66             eprintln!("Failed to get current directory: {err}");
67             process::exit(1);
68         }
69     };
70
71     for dir in current.ancestors() {
72         let candidate = dir.join("x.py");
73
74         if candidate.exists() {
75             let mut cmd = x_command(dir);
76
77             cmd.args(env::args().skip(1)).current_dir(dir);
78
79             let result = exec_or_status(&mut cmd);
80
81             match result {
82                 Err(error) => {
83                     eprintln!("Failed to invoke `{:?}`: {}", cmd, error);
84                 }
85                 Ok(status) => {
86                     process::exit(status.code().unwrap_or(1));
87                 }
88             }
89         }
90     }
91
92     eprintln!(
93         "x.py not found. Please run inside of a checkout of `https://github.com/rust-lang/rust`."
94     );
95
96     process::exit(1);
97 }