Skip to content

Commit adbb608

Browse files
committed
Link stage1 build to toolchain automatically
Fixed types Add checks for rustup and if toolchain is linked Fortified rustup/directory checks; made other suggested changes Added check for output status Remove output of rustup from console Made suggested change Deleted confusing comment Fixed compiler error; removed extra declaration Refactored to smaller components; made suggested changes Automate toolchain linking for stage 1 builds
1 parent 0132f82 commit adbb608

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

src/bootstrap/setup.rs

+80
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::TargetSelection;
12
use crate::{t, VERSION};
23
use std::fmt::Write as _;
34
use std::path::{Path, PathBuf};
@@ -107,6 +108,17 @@ pub fn setup(src_path: &Path, profile: Profile) {
107108
let include_path = profile.include_path(src_path);
108109
println!("`x.py` will now use the configuration at {}", include_path.display());
109110

111+
let build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
112+
let stage_path = ["build", build.rustc_target_arg(), "stage1"].join("/");
113+
114+
println!();
115+
116+
if !rustup_installed() && profile != Profile::User {
117+
println!("`rustup` is not installed; cannot link `stage1` toolchain");
118+
} else if stage_dir_exists(&stage_path[..]) {
119+
attempt_toolchain_link(&stage_path[..]);
120+
}
121+
110122
let suggestions = match profile {
111123
Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
112124
Profile::Tools => &[
@@ -139,6 +151,74 @@ pub fn setup(src_path: &Path, profile: Profile) {
139151
}
140152
}
141153

154+
fn rustup_installed() -> bool {
155+
Command::new("rustup")
156+
.arg("--version")
157+
.stdout(std::process::Stdio::null())
158+
.output()
159+
.map_or(false, |output| output.status.success())
160+
}
161+
162+
fn stage_dir_exists(stage_path: &str) -> bool {
163+
match fs::create_dir(&stage_path[..]) {
164+
Ok(_) => true,
165+
Err(_) => Path::new(&stage_path[..]).exists(),
166+
}
167+
}
168+
169+
fn attempt_toolchain_link(stage_path: &str) {
170+
if toolchain_is_linked() {
171+
return;
172+
}
173+
174+
if try_link_toolchain(&stage_path[..]) {
175+
println!(
176+
"Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
177+
);
178+
} else {
179+
println!("`rustup` failed to link stage 1 build to `stage1` toolchain");
180+
println!(
181+
"To manually link stage 1 build to `stage1` toolchain, run:\n
182+
`rustup toolchain link stage1 {}`",
183+
&stage_path[..]
184+
);
185+
}
186+
}
187+
188+
fn toolchain_is_linked() -> bool {
189+
match Command::new("rustup")
190+
.args(&["toolchain", "list"])
191+
.stdout(std::process::Stdio::piped())
192+
.output()
193+
{
194+
Ok(toolchain_list) => {
195+
if !String::from_utf8_lossy(&toolchain_list.stdout).contains("stage1") {
196+
return false;
197+
}
198+
// The toolchain has already been linked.
199+
println!(
200+
"`stage1` toolchain already linked; not attempting to link `stage1` toolchain"
201+
);
202+
}
203+
Err(_) => {
204+
// In this case, we don't know if the `stage1` toolchain has been linked;
205+
// but `rustup` failed, so let's not go any further.
206+
println!(
207+
"`rustup` failed to list current toolchains; not attempting to link `stage1` toolchain"
208+
);
209+
}
210+
}
211+
true
212+
}
213+
214+
fn try_link_toolchain(stage_path: &str) -> bool {
215+
Command::new("rustup")
216+
.stdout(std::process::Stdio::null())
217+
.args(&["toolchain", "link", "stage1", &stage_path[..]])
218+
.output()
219+
.map_or(false, |output| output.status.success())
220+
}
221+
142222
// Used to get the path for `Subcommand::Setup`
143223
pub fn interactive_path() -> io::Result<Profile> {
144224
fn abbrev_all() -> impl Iterator<Item = ((String, String), Profile)> {

0 commit comments

Comments
 (0)