Skip to content

Commit

Permalink
Link stage1 build to toolchain automatically
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Sl1mb0 committed Sep 27, 2021
1 parent 0132f82 commit adbb608
Showing 1 changed file with 80 additions and 0 deletions.
80 changes: 80 additions & 0 deletions src/bootstrap/setup.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::TargetSelection;
use crate::{t, VERSION};
use std::fmt::Write as _;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -107,6 +108,17 @@ pub fn setup(src_path: &Path, profile: Profile) {
let include_path = profile.include_path(src_path);
println!("`x.py` will now use the configuration at {}", include_path.display());

let build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
let stage_path = ["build", build.rustc_target_arg(), "stage1"].join("/");

println!();

if !rustup_installed() && profile != Profile::User {
println!("`rustup` is not installed; cannot link `stage1` toolchain");
} else if stage_dir_exists(&stage_path[..]) {
attempt_toolchain_link(&stage_path[..]);
}

let suggestions = match profile {
Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
Profile::Tools => &[
Expand Down Expand Up @@ -139,6 +151,74 @@ pub fn setup(src_path: &Path, profile: Profile) {
}
}

fn rustup_installed() -> bool {
Command::new("rustup")
.arg("--version")
.stdout(std::process::Stdio::null())
.output()
.map_or(false, |output| output.status.success())
}

fn stage_dir_exists(stage_path: &str) -> bool {
match fs::create_dir(&stage_path[..]) {
Ok(_) => true,
Err(_) => Path::new(&stage_path[..]).exists(),
}
}

fn attempt_toolchain_link(stage_path: &str) {
if toolchain_is_linked() {
return;
}

if try_link_toolchain(&stage_path[..]) {
println!(
"Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
);
} else {
println!("`rustup` failed to link stage 1 build to `stage1` toolchain");
println!(
"To manually link stage 1 build to `stage1` toolchain, run:\n
`rustup toolchain link stage1 {}`",
&stage_path[..]
);
}
}

fn toolchain_is_linked() -> bool {
match Command::new("rustup")
.args(&["toolchain", "list"])
.stdout(std::process::Stdio::piped())
.output()
{
Ok(toolchain_list) => {
if !String::from_utf8_lossy(&toolchain_list.stdout).contains("stage1") {
return false;
}
// The toolchain has already been linked.
println!(
"`stage1` toolchain already linked; not attempting to link `stage1` toolchain"
);
}
Err(_) => {
// In this case, we don't know if the `stage1` toolchain has been linked;
// but `rustup` failed, so let's not go any further.
println!(
"`rustup` failed to list current toolchains; not attempting to link `stage1` toolchain"
);
}
}
true
}

fn try_link_toolchain(stage_path: &str) -> bool {
Command::new("rustup")
.stdout(std::process::Stdio::null())
.args(&["toolchain", "link", "stage1", &stage_path[..]])
.output()
.map_or(false, |output| output.status.success())
}

// Used to get the path for `Subcommand::Setup`
pub fn interactive_path() -> io::Result<Profile> {
fn abbrev_all() -> impl Iterator<Item = ((String, String), Profile)> {
Expand Down

0 comments on commit adbb608

Please sign in to comment.