diff --git a/Cargo.lock b/Cargo.lock
index d7d221ee66f2a..2ee9a872d3ee2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -214,7 +214,6 @@ dependencies = [
 name = "bootstrap"
 version = "0.0.0"
 dependencies = [
- "build_helper",
  "cc",
  "cmake",
  "filetime",
@@ -256,10 +255,6 @@ dependencies = [
  "toml",
 ]
 
-[[package]]
-name = "build_helper"
-version = "0.1.0"
-
 [[package]]
 name = "bump-stage0"
 version = "0.1.0"
@@ -3891,7 +3886,6 @@ dependencies = [
 name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
- "build_helper",
  "cc",
  "libc",
 ]
diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml
index d8dfcc84e68da..34556df3c6d79 100644
--- a/compiler/rustc_llvm/Cargo.toml
+++ b/compiler/rustc_llvm/Cargo.toml
@@ -11,5 +11,4 @@ emscripten = []
 libc = "0.2.73"
 
 [build-dependencies]
-build_helper = { path = "../../src/build_helper" }
 cc = "1.0.69"
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 3b6808d693f21..ac758c15cca78 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -1,8 +1,8 @@
 use std::env;
+use std::ffi::{OsStr, OsString};
+use std::fmt::Display;
 use std::path::{Path, PathBuf};
-use std::process::Command;
-
-use build_helper::{output, tracked_env_var_os};
+use std::process::{Command, Stdio};
 
 fn detect_llvm_link() -> (&'static str, &'static str) {
     // Force the link mode we want, preferring static by default, but
@@ -14,13 +14,74 @@ fn detect_llvm_link() -> (&'static str, &'static str) {
     }
 }
 
+// Because Cargo adds the compiler's dylib path to our library search path, llvm-config may
+// break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM
+// shared library, which means that when our freshly built llvm-config goes to load it's
+// associated LLVM, it actually loads the compiler's LLVM. In particular when building the first
+// compiler (i.e., in stage 0) that's a problem, as the compiler's LLVM is likely different from
+// the one we want to use. As such, we restore the environment to what bootstrap saw. This isn't
+// perfect -- we might actually want to see something from Cargo's added library paths -- but
+// for now it works.
+fn restore_library_path() {
+    let key = tracked_env_var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR");
+    if let Some(env) = tracked_env_var_os("REAL_LIBRARY_PATH") {
+        env::set_var(&key, &env);
+    } else {
+        env::remove_var(&key);
+    }
+}
+
+/// Reads an environment variable and adds it to dependencies.
+/// Supposed to be used for all variables except those set for build scripts by cargo
+/// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
+fn tracked_env_var_os<K: AsRef<OsStr> + Display>(key: K) -> Option<OsString> {
+    println!("cargo:rerun-if-env-changed={}", key);
+    env::var_os(key)
+}
+
+fn rerun_if_changed_anything_in_dir(dir: &Path) {
+    let mut stack = dir
+        .read_dir()
+        .unwrap()
+        .map(|e| e.unwrap())
+        .filter(|e| &*e.file_name() != ".git")
+        .collect::<Vec<_>>();
+    while let Some(entry) = stack.pop() {
+        let path = entry.path();
+        if entry.file_type().unwrap().is_dir() {
+            stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
+        } else {
+            println!("cargo:rerun-if-changed={}", path.display());
+        }
+    }
+}
+
+#[track_caller]
+fn output(cmd: &mut Command) -> String {
+    let output = match cmd.stderr(Stdio::inherit()).output() {
+        Ok(status) => status,
+        Err(e) => {
+            println!("\n\nfailed to execute command: {:?}\nerror: {}\n\n", cmd, e);
+            std::process::exit(1);
+        }
+    };
+    if !output.status.success() {
+        panic!(
+            "command did not execute successfully: {:?}\n\
+             expected success, got: {}",
+            cmd, output.status
+        );
+    }
+    String::from_utf8(output.stdout).unwrap()
+}
+
 fn main() {
     if tracked_env_var_os("RUST_CHECK").is_some() {
         // If we're just running `check`, there's no need for LLVM to be built.
         return;
     }
 
-    build_helper::restore_library_path();
+    restore_library_path();
 
     let target = env::var("TARGET").expect("TARGET was not set");
     let llvm_config =
@@ -160,7 +221,7 @@ fn main() {
         cfg.debug(false);
     }
 
-    build_helper::rerun_if_changed_anything_in_dir(Path::new("llvm-wrapper"));
+    rerun_if_changed_anything_in_dir(Path::new("llvm-wrapper"));
     cfg.file("llvm-wrapper/PassWrapper.cpp")
         .file("llvm-wrapper/RustWrapper.cpp")
         .file("llvm-wrapper/ArchiveWrapper.cpp")
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 02efc08cc791f..fe9d6a727ed1e 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -34,7 +34,6 @@ path = "bin/llvm-config-wrapper.rs"
 test = false
 
 [dependencies]
-build_helper = { path = "../build_helper" }
 cmake = "0.1.38"
 filetime = "0.2"
 getopts = "0.2.19"
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 00aebc21f581a..fc55c8626d99f 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -11,8 +11,6 @@ use std::path::{Component, Path, PathBuf};
 use std::process::Command;
 use std::time::{Duration, Instant};
 
-use build_helper::{output, t};
-
 use crate::cache::{Cache, Interned, INTERNER};
 use crate::check;
 use crate::compile;
@@ -25,7 +23,7 @@ use crate::native;
 use crate::run;
 use crate::test;
 use crate::tool::{self, SourceType};
-use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir};
+use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t};
 use crate::EXTRA_CHECK_CFGS;
 use crate::{Build, CLang, DocTests, GitRepo, Mode};
 
diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs
index 8c47f625d732b..7ce446876118a 100644
--- a/src/bootstrap/cc_detect.rs
+++ b/src/bootstrap/cc_detect.rs
@@ -26,9 +26,8 @@ use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::{env, iter};
 
-use build_helper::output;
-
 use crate::config::{Target, TargetSelection};
+use crate::util::output;
 use crate::{Build, CLang, GitRepo};
 
 // The `cc` crate doesn't provide a way to obtain a path to the detected archiver,
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 6478578c3c402..1932a0017ee25 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -8,8 +8,7 @@
 use std::path::Path;
 use std::process::Command;
 
-use build_helper::output;
-
+use crate::util::output;
 use crate::Build;
 
 pub enum GitInfo {
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index 3b73dc1c7df74..069f3d6acf158 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -9,8 +9,7 @@ use std::fs;
 use std::io::{self, ErrorKind};
 use std::path::Path;
 
-use build_helper::t;
-
+use crate::util::t;
 use crate::Build;
 
 pub fn clean(build: &Build, all: bool) {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 9971778034601..9cfd9f92aa7cd 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -16,7 +16,6 @@ use std::path::{Path, PathBuf};
 use std::process::{exit, Command, Stdio};
 use std::str;
 
-use build_helper::{output, t, up_to_date};
 use serde::Deserialize;
 
 use crate::builder::Cargo;
@@ -26,7 +25,7 @@ use crate::config::{LlvmLibunwind, TargetSelection};
 use crate::dist;
 use crate::native;
 use crate::tool::SourceType;
-use crate::util::{exe, is_debug_info, is_dylib, symlink_dir};
+use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date};
 use crate::LLVM_TOOLS;
 use crate::{CLang, Compiler, DependencyType, GitRepo, Mode};
 
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 997e811e214df..b17b94f289395 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -17,8 +17,7 @@ use crate::cache::{Interned, INTERNER};
 use crate::channel::GitInfo;
 pub use crate::flags::Subcommand;
 use crate::flags::{Color, Flags};
-use crate::util::exe;
-use build_helper::t;
+use crate::util::{exe, t};
 use serde::Deserialize;
 
 macro_rules! check_ci_llvm {
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 8693e85e4742f..5f92cc2ca6fad 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -14,15 +14,13 @@ use std::fs;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-use build_helper::{output, t};
-
 use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::{Interned, INTERNER};
 use crate::compile;
 use crate::config::TargetSelection;
 use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
 use crate::tool::{self, Tool};
-use crate::util::{exe, is_dylib, timeit};
+use crate::util::{exe, is_dylib, output, t, timeit};
 use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
 
 pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
@@ -635,14 +633,6 @@ impl Step for RustcDev {
             &[],
             &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
         );
-        // This particular crate is used as a build dependency of the above.
-        copy_src_dirs(
-            builder,
-            &builder.src,
-            &["src/build_helper"],
-            &[],
-            &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
-        );
         for file in src_files {
             tarball.add_file(builder.src.join(file), "lib/rustlib/rustc-src/rust", 0o644);
         }
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 23b5ddcd47a0e..be55871b56a28 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -12,15 +12,13 @@ use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
 
-use crate::Mode;
-use build_helper::{t, up_to_date};
-
 use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::{Interned, INTERNER};
 use crate::compile;
 use crate::config::{Config, TargetSelection};
 use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
-use crate::util::symlink_dir;
+use crate::util::{symlink_dir, t, up_to_date};
+use crate::Mode;
 
 macro_rules! submodule_helper {
     ($path:expr, submodule) => {
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 74528f2752f5f..e34b40a93ff47 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -7,12 +7,12 @@ use std::env;
 use std::path::PathBuf;
 use std::process;
 
-use build_helper::t;
 use getopts::Options;
 
 use crate::builder::Builder;
 use crate::config::{Config, TargetSelection};
 use crate::setup::Profile;
+use crate::util::t;
 use crate::{Build, DocTests};
 
 pub enum Color {
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index 530cc829320d1..10b846e6db208 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -1,7 +1,7 @@
 //! Runs rustfmt on the repository.
 
+use crate::util::{output, t};
 use crate::Build;
-use build_helper::{output, t};
 use ignore::WalkBuilder;
 use std::collections::VecDeque;
 use std::path::{Path, PathBuf};
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 06acf1a9a0083..27b9196d9868e 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -8,7 +8,7 @@ use std::fs;
 use std::path::{Component, PathBuf};
 use std::process::Command;
 
-use build_helper::t;
+use crate::util::t;
 
 use crate::dist::{self, sanitize_sh};
 use crate::tarball::GeneratedTarball;
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 4089a63f881d1..ccc8516a89abf 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -116,12 +116,13 @@ use std::os::unix::fs::symlink as symlink_file;
 #[cfg(windows)]
 use std::os::windows::fs::symlink_file;
 
-use build_helper::{mtime, output, run, run_suppressed, t, try_run, try_run_suppressed};
 use filetime::FileTime;
 
 use crate::builder::Kind;
 use crate::config::{LlvmLibunwind, TargetSelection};
-use crate::util::{exe, libdir, CiEnv};
+use crate::util::{
+    exe, libdir, mtime, output, run, run_suppressed, t, try_run, try_run_suppressed, CiEnv,
+};
 
 mod builder;
 mod cache;
@@ -1301,13 +1302,10 @@ impl Build {
                 }
                 // Don't include optional deps if their features are not
                 // enabled. Ideally this would be computed from `cargo
-                // metadata --features …`, but that is somewhat slow. Just
-                // skip `build_helper` since there aren't any operations we
-                // want to perform on it. In the future, we may want to
-                // consider just filtering all build and dev dependencies in
-                // metadata::build.
+                // metadata --features …`, but that is somewhat slow. In
+                // the future, we may want to consider just filtering all
+                // build and dev dependencies in metadata::build.
                 if visited.insert(dep)
-                    && dep != "build_helper"
                     && (dep != "profiler_builtins"
                         || target
                             .map(|t| self.config.profiler_enabled(t))
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index 65e229697dc87..59dc50be47f06 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -1,10 +1,10 @@
 use std::path::PathBuf;
 use std::process::Command;
 
-use build_helper::output;
 use serde::Deserialize;
 
 use crate::cache::INTERNER;
+use crate::util::output;
 use crate::{Build, Crate};
 
 #[derive(Deserialize)]
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index a751a6e3ece7f..d27ad9644b56c 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -16,13 +16,10 @@ use std::io;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-use build_helper::{output, t};
-
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::config::TargetSelection;
-use crate::util::{self, exe};
+use crate::util::{self, exe, output, t, up_to_date};
 use crate::{CLang, GitRepo};
-use build_helper::up_to_date;
 
 pub struct Meta {
     stamp: HashStamp,
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index 11b393857e74c..25abe7a72fdc8 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -1,7 +1,7 @@
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::dist::distdir;
 use crate::tool::Tool;
-use build_helper::output;
+use crate::util::output;
 use std::process::Command;
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index d7db2cef24f2b..8c2899c1ac01e 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -15,10 +15,9 @@ use std::fs;
 use std::path::PathBuf;
 use std::process::Command;
 
-use build_helper::output;
-
 use crate::cache::INTERNER;
 use crate::config::Target;
+use crate::util::output;
 use crate::Build;
 
 pub struct Finder {
diff --git a/src/bootstrap/tarball.rs b/src/bootstrap/tarball.rs
index 9ff5c2327e0f7..c743c5188e754 100644
--- a/src/bootstrap/tarball.rs
+++ b/src/bootstrap/tarball.rs
@@ -3,9 +3,8 @@ use std::{
     process::Command,
 };
 
-use build_helper::t;
-
 use crate::builder::Builder;
+use crate::util::t;
 
 #[derive(Copy, Clone)]
 pub(crate) enum OverlayKind {
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 19d98df3ce902..e4fcb287f1228 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -11,8 +11,6 @@ use std::iter;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 
-use build_helper::{self, output, t};
-
 use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::Interned;
 use crate::compile;
@@ -22,7 +20,7 @@ use crate::flags::Subcommand;
 use crate::native;
 use crate::tool::{self, SourceType, Tool};
 use crate::toolstate::ToolState;
-use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var};
+use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t};
 use crate::Crate as CargoCrate;
 use crate::{envify, CLang, DocTests, GitRepo, Mode};
 
@@ -2306,9 +2304,7 @@ impl Step for Distcheck {
                 .current_dir(&dir),
         );
         builder.run(
-            Command::new(build_helper::make(&builder.config.build.triple))
-                .arg("check")
-                .current_dir(&dir),
+            Command::new(util::make(&builder.config.build.triple)).arg("check").current_dir(&dir),
         );
 
         // Now make sure that rust-src has all of libstd's dependencies
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 1317c3f983975..2ae4d830721e8 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -4,14 +4,12 @@ use std::fs;
 use std::path::{Path, PathBuf};
 use std::process::{exit, Command};
 
-use build_helper::t;
-
 use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
 use crate::channel::GitInfo;
 use crate::compile;
 use crate::config::TargetSelection;
 use crate::toolstate::ToolState;
-use crate::util::{add_dylib_path, exe};
+use crate::util::{add_dylib_path, exe, t};
 use crate::Compiler;
 use crate::Mode;
 
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index 08d0815806207..c7ea254c5b1d7 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -1,5 +1,5 @@
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
-use build_helper::t;
+use crate::util::t;
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
 use std::env;
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 2c78ceb1e5bec..8e770d4d57fa6 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -7,15 +7,38 @@ use std::env;
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
-use std::process::Command;
+use std::process::{Command, Stdio};
 use std::str;
-use std::time::Instant;
-
-use build_helper::t;
+use std::time::{Instant, SystemTime, UNIX_EPOCH};
 
 use crate::builder::Builder;
 use crate::config::{Config, TargetSelection};
 
+/// A helper macro to `unwrap` a result except also print out details like:
+///
+/// * The file/line of the panic
+/// * The expression that failed
+/// * The error itself
+///
+/// This is currently used judiciously throughout the build system rather than
+/// using a `Result` with `try!`, but this may change one day...
+macro_rules! t {
+    ($e:expr) => {
+        match $e {
+            Ok(e) => e,
+            Err(e) => panic!("{} failed with {}", stringify!($e), e),
+        }
+    };
+    // it can show extra info in the second parameter
+    ($e:expr, $extra:expr) => {
+        match $e {
+            Ok(e) => e,
+            Err(e) => panic!("{} failed with {} ({:?})", stringify!($e), e, $extra),
+        }
+    };
+}
+pub(crate) use t;
+
 /// Given an executable called `name`, return the filename for the
 /// executable for a particular target.
 pub fn exe(name: &str, target: TargetSelection) -> String {
@@ -301,3 +324,119 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>(
         _ => None,
     }
 }
+
+pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) {
+    if !try_run(cmd, print_cmd_on_fail) {
+        std::process::exit(1);
+    }
+}
+
+pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
+    let status = match cmd.status() {
+        Ok(status) => status,
+        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
+    };
+    if !status.success() && print_cmd_on_fail {
+        println!(
+            "\n\ncommand did not execute successfully: {:?}\n\
+             expected success, got: {}\n\n",
+            cmd, status
+        );
+    }
+    status.success()
+}
+
+pub fn run_suppressed(cmd: &mut Command) {
+    if !try_run_suppressed(cmd) {
+        std::process::exit(1);
+    }
+}
+
+pub fn try_run_suppressed(cmd: &mut Command) -> bool {
+    let output = match cmd.output() {
+        Ok(status) => status,
+        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
+    };
+    if !output.status.success() {
+        println!(
+            "\n\ncommand did not execute successfully: {:?}\n\
+             expected success, got: {}\n\n\
+             stdout ----\n{}\n\
+             stderr ----\n{}\n\n",
+            cmd,
+            output.status,
+            String::from_utf8_lossy(&output.stdout),
+            String::from_utf8_lossy(&output.stderr)
+        );
+    }
+    output.status.success()
+}
+
+pub fn make(host: &str) -> PathBuf {
+    if host.contains("dragonfly")
+        || host.contains("freebsd")
+        || host.contains("netbsd")
+        || host.contains("openbsd")
+    {
+        PathBuf::from("gmake")
+    } else {
+        PathBuf::from("make")
+    }
+}
+
+#[track_caller]
+pub fn output(cmd: &mut Command) -> String {
+    let output = match cmd.stderr(Stdio::inherit()).output() {
+        Ok(status) => status,
+        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
+    };
+    if !output.status.success() {
+        panic!(
+            "command did not execute successfully: {:?}\n\
+             expected success, got: {}",
+            cmd, output.status
+        );
+    }
+    String::from_utf8(output.stdout).unwrap()
+}
+
+/// Returns the last-modified time for `path`, or zero if it doesn't exist.
+pub fn mtime(path: &Path) -> SystemTime {
+    fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)
+}
+
+/// Returns `true` if `dst` is up to date given that the file or files in `src`
+/// are used to generate it.
+///
+/// Uses last-modified time checks to verify this.
+pub fn up_to_date(src: &Path, dst: &Path) -> bool {
+    if !dst.exists() {
+        return false;
+    }
+    let threshold = mtime(dst);
+    let meta = match fs::metadata(src) {
+        Ok(meta) => meta,
+        Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
+    };
+    if meta.is_dir() {
+        dir_up_to_date(src, threshold)
+    } else {
+        meta.modified().unwrap_or(UNIX_EPOCH) <= threshold
+    }
+}
+
+fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
+    t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
+        let meta = t!(e.metadata());
+        if meta.is_dir() {
+            dir_up_to_date(&e.path(), threshold)
+        } else {
+            meta.modified().unwrap_or(UNIX_EPOCH) < threshold
+        }
+    })
+}
+
+fn fail(s: &str) -> ! {
+    println!("\n\n{}\n\n", s);
+    std::process::exit(1);
+}
diff --git a/src/build_helper/Cargo.toml b/src/build_helper/Cargo.toml
deleted file mode 100644
index d88df0e08fab3..0000000000000
--- a/src/build_helper/Cargo.toml
+++ /dev/null
@@ -1,7 +0,0 @@
-[package]
-name = "build_helper"
-version = "0.1.0"
-edition = "2021"
-
-[lib]
-path = "lib.rs"
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
deleted file mode 100644
index 24aded547315e..0000000000000
--- a/src/build_helper/lib.rs
+++ /dev/null
@@ -1,189 +0,0 @@
-use std::ffi::{OsStr, OsString};
-use std::fmt::Display;
-use std::path::{Path, PathBuf};
-use std::process::{Command, Stdio};
-use std::time::{SystemTime, UNIX_EPOCH};
-use std::{env, fs};
-
-/// A helper macro to `unwrap` a result except also print out details like:
-///
-/// * The file/line of the panic
-/// * The expression that failed
-/// * The error itself
-///
-/// This is currently used judiciously throughout the build system rather than
-/// using a `Result` with `try!`, but this may change one day...
-#[macro_export]
-macro_rules! t {
-    ($e:expr) => {
-        match $e {
-            Ok(e) => e,
-            Err(e) => panic!("{} failed with {}", stringify!($e), e),
-        }
-    };
-    // it can show extra info in the second parameter
-    ($e:expr, $extra:expr) => {
-        match $e {
-            Ok(e) => e,
-            Err(e) => panic!("{} failed with {} ({:?})", stringify!($e), e, $extra),
-        }
-    };
-}
-
-/// Reads an environment variable and adds it to dependencies.
-/// Supposed to be used for all variables except those set for build scripts by cargo
-/// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
-pub fn tracked_env_var_os<K: AsRef<OsStr> + Display>(key: K) -> Option<OsString> {
-    println!("cargo:rerun-if-env-changed={}", key);
-    env::var_os(key)
-}
-
-// Because Cargo adds the compiler's dylib path to our library search path, llvm-config may
-// break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM
-// shared library, which means that when our freshly built llvm-config goes to load it's
-// associated LLVM, it actually loads the compiler's LLVM. In particular when building the first
-// compiler (i.e., in stage 0) that's a problem, as the compiler's LLVM is likely different from
-// the one we want to use. As such, we restore the environment to what bootstrap saw. This isn't
-// perfect -- we might actually want to see something from Cargo's added library paths -- but
-// for now it works.
-pub fn restore_library_path() {
-    let key = tracked_env_var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR");
-    if let Some(env) = tracked_env_var_os("REAL_LIBRARY_PATH") {
-        env::set_var(&key, &env);
-    } else {
-        env::remove_var(&key);
-    }
-}
-
-pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) {
-    if !try_run(cmd, print_cmd_on_fail) {
-        std::process::exit(1);
-    }
-}
-
-pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
-    let status = match cmd.status() {
-        Ok(status) => status,
-        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
-    };
-    if !status.success() && print_cmd_on_fail {
-        println!(
-            "\n\ncommand did not execute successfully: {:?}\n\
-             expected success, got: {}\n\n",
-            cmd, status
-        );
-    }
-    status.success()
-}
-
-pub fn run_suppressed(cmd: &mut Command) {
-    if !try_run_suppressed(cmd) {
-        std::process::exit(1);
-    }
-}
-
-pub fn try_run_suppressed(cmd: &mut Command) -> bool {
-    let output = match cmd.output() {
-        Ok(status) => status,
-        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
-    };
-    if !output.status.success() {
-        println!(
-            "\n\ncommand did not execute successfully: {:?}\n\
-             expected success, got: {}\n\n\
-             stdout ----\n{}\n\
-             stderr ----\n{}\n\n",
-            cmd,
-            output.status,
-            String::from_utf8_lossy(&output.stdout),
-            String::from_utf8_lossy(&output.stderr)
-        );
-    }
-    output.status.success()
-}
-
-pub fn make(host: &str) -> PathBuf {
-    if host.contains("dragonfly")
-        || host.contains("freebsd")
-        || host.contains("netbsd")
-        || host.contains("openbsd")
-    {
-        PathBuf::from("gmake")
-    } else {
-        PathBuf::from("make")
-    }
-}
-
-#[track_caller]
-pub fn output(cmd: &mut Command) -> String {
-    let output = match cmd.stderr(Stdio::inherit()).output() {
-        Ok(status) => status,
-        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
-    };
-    if !output.status.success() {
-        panic!(
-            "command did not execute successfully: {:?}\n\
-             expected success, got: {}",
-            cmd, output.status
-        );
-    }
-    String::from_utf8(output.stdout).unwrap()
-}
-
-pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
-    let mut stack = dir
-        .read_dir()
-        .unwrap()
-        .map(|e| e.unwrap())
-        .filter(|e| &*e.file_name() != ".git")
-        .collect::<Vec<_>>();
-    while let Some(entry) = stack.pop() {
-        let path = entry.path();
-        if entry.file_type().unwrap().is_dir() {
-            stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
-        } else {
-            println!("cargo:rerun-if-changed={}", path.display());
-        }
-    }
-}
-
-/// Returns the last-modified time for `path`, or zero if it doesn't exist.
-pub fn mtime(path: &Path) -> SystemTime {
-    fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)
-}
-
-/// Returns `true` if `dst` is up to date given that the file or files in `src`
-/// are used to generate it.
-///
-/// Uses last-modified time checks to verify this.
-pub fn up_to_date(src: &Path, dst: &Path) -> bool {
-    if !dst.exists() {
-        return false;
-    }
-    let threshold = mtime(dst);
-    let meta = match fs::metadata(src) {
-        Ok(meta) => meta,
-        Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
-    };
-    if meta.is_dir() {
-        dir_up_to_date(src, threshold)
-    } else {
-        meta.modified().unwrap_or(UNIX_EPOCH) <= threshold
-    }
-}
-
-fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
-    t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
-        let meta = t!(e.metadata());
-        if meta.is_dir() {
-            dir_up_to_date(&e.path(), threshold)
-        } else {
-            meta.modified().unwrap_or(UNIX_EPOCH) < threshold
-        }
-    })
-}
-
-fn fail(s: &str) -> ! {
-    println!("\n\n{}\n\n", s);
-    std::process::exit(1);
-}