about summary refs log tree commit diff
path: root/src/bootstrap
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2023-04-04 08:01:31 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2023-04-04 08:01:31 +0000
commit76863306c32b8953fdca4077fe585d4ed526ce89 (patch)
tree13c6549a5109f48d98c08fc11f141009b7b58413 /src/bootstrap
parentaef713b8ffb32825e9a954c6618f5de2738540bc (diff)
parentbd991d9953625e9d51fc4fcb5e19aa9c3ea598a8 (diff)
downloadrust-76863306c32b8953fdca4077fe585d4ed526ce89.tar.gz
rust-76863306c32b8953fdca4077fe585d4ed526ce89.zip
Merge from rustc
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/Cargo.lock72
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/bootstrap.py3
-rw-r--r--src/bootstrap/builder.rs20
-rw-r--r--src/bootstrap/compile.rs69
-rw-r--r--src/bootstrap/config.rs12
-rw-r--r--src/bootstrap/config/tests.rs2
-rw-r--r--src/bootstrap/defaults/config.user.toml4
-rw-r--r--src/bootstrap/dist.rs12
-rw-r--r--src/bootstrap/doc.rs9
-rw-r--r--src/bootstrap/download.rs2
-rw-r--r--src/bootstrap/dylib_util.rs2
-rw-r--r--src/bootstrap/lib.rs28
-rw-r--r--src/bootstrap/llvm.rs (renamed from src/bootstrap/native.rs)73
-rw-r--r--src/bootstrap/metrics.rs13
-rw-r--r--src/bootstrap/render_tests.rs19
-rw-r--r--src/bootstrap/test.rs79
17 files changed, 248 insertions, 173 deletions
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 27236e191fd..965dfa5f398 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -12,17 +12,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
-
-[[package]]
 name = "autocfg"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -47,7 +36,6 @@ dependencies = [
 name = "bootstrap"
 version = "0.0.0"
 dependencies = [
- "atty",
  "build_helper",
  "cc",
  "cmake",
@@ -56,6 +44,7 @@ dependencies = [
  "getopts",
  "hex",
  "ignore",
+ "is-terminal",
  "libc",
  "object",
  "once_cell",
@@ -212,13 +201,13 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
 
 [[package]]
 name = "errno"
-version = "0.2.8"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
+checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0"
 dependencies = [
  "errno-dragonfly",
  "libc",
- "winapi",
+ "windows-sys",
 ]
 
 [[package]]
@@ -233,9 +222,9 @@ dependencies = [
 
 [[package]]
 name = "fd-lock"
-version = "3.0.8"
+version = "3.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb21c69b9fea5e15dbc1049e4b77145dd0ba1c84019c488102de0dc4ea4b0a27"
+checksum = "9799aefb4a2e4a01cc47610b1dd47c18ab13d991f27bbcaed9296f5a53d5cbad"
 dependencies = [
  "cfg-if",
  "rustix",
@@ -302,6 +291,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
 name = "hex"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -327,15 +322,28 @@ dependencies = [
 
 [[package]]
 name = "io-lifetimes"
-version = "1.0.1"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87"
+checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
 dependencies = [
+ "hermit-abi 0.3.1",
  "libc",
  "windows-sys",
 ]
 
 [[package]]
+name = "is-terminal"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "io-lifetimes",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
 name = "itoa"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -349,15 +357,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.137"
+version = "0.2.140"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
+checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.1.3"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
+checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
 
 [[package]]
 name = "log"
@@ -409,7 +417,7 @@ version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
  "libc",
 ]
 
@@ -540,9 +548,9 @@ checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
 
 [[package]]
 name = "rustix"
-version = "0.36.3"
+version = "0.37.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e"
+checksum = "d097081ed288dfe45699b72f5b5d648e5f15d64d900c7080273baa20c16a6849"
 dependencies = [
  "bitflags",
  "errno",
@@ -753,17 +761,11 @@ dependencies = [
 
 [[package]]
 name = "windows-sys"
-version = "0.42.0"
+version = "0.45.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
 dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows-targets",
 ]
 
 [[package]]
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 5c659800bdb..2fbe7aa57aa 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -30,7 +30,7 @@ path = "bin/sccache-plus-cl.rs"
 test = false
 
 [dependencies]
-atty = "0.2.14"
+is-terminal = "0.4"
 build_helper = { path = "../tools/build_helper" }
 cmake = "0.1.38"
 filetime = "0.2"
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 013d1ab525b..d12781cc33a 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -741,6 +741,9 @@ class RustBuild(object):
         env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
             (os.pathsep + env["LIBRARY_PATH"]) \
             if "LIBRARY_PATH" in env else ""
+        env["LIBPATH"] = os.path.join(self.bin_root(), "lib") + \
+            (os.pathsep + env["LIBPATH"]) \
+            if "LIBPATH" in env else ""
 
         # Export Stage0 snapshot compiler related env variables
         build_section = "target.{}".format(self.build)
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 83a6d0ad292..4d528a767e4 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -16,7 +16,7 @@ use crate::config::{SplitDebuginfo, TargetSelection};
 use crate::doc;
 use crate::flags::{Color, Subcommand};
 use crate::install;
-use crate::native;
+use crate::llvm;
 use crate::run;
 use crate::setup;
 use crate::test;
@@ -636,13 +636,13 @@ impl<'a> Builder<'a> {
                 tool::Rustdoc,
                 tool::Clippy,
                 tool::CargoClippy,
-                native::Llvm,
-                native::Sanitizers,
+                llvm::Llvm,
+                llvm::Sanitizers,
                 tool::Rustfmt,
                 tool::Miri,
                 tool::CargoMiri,
-                native::Lld,
-                native::CrtBeginEnd
+                llvm::Lld,
+                llvm::CrtBeginEnd
             ),
             Kind::Check | Kind::Clippy | Kind::Fix => describe!(
                 check::Std,
@@ -1101,7 +1101,7 @@ impl<'a> Builder<'a> {
     /// check build or dry-run, where there's no need to build all of LLVM.
     fn llvm_config(&self, target: TargetSelection) -> Option<PathBuf> {
         if self.config.llvm_enabled() && self.kind != Kind::Check && !self.config.dry_run() {
-            let native::LlvmResult { llvm_config, .. } = self.ensure(native::Llvm { target });
+            let llvm::LlvmResult { llvm_config, .. } = self.ensure(llvm::Llvm { target });
             if llvm_config.is_file() {
                 return Some(llvm_config);
             }
@@ -1227,7 +1227,7 @@ impl<'a> Builder<'a> {
             // rustc_llvm. But if LLVM is stale, that'll be a tiny amount
             // of work comparatively, and we'd likely need to rebuild it anyway,
             // so that's okay.
-            if crate::native::prebuilt_llvm_config(self, target).is_err() {
+            if crate::llvm::prebuilt_llvm_config(self, target).is_err() {
                 cargo.env("RUST_CHECK", "1");
             }
         }
@@ -1941,6 +1941,12 @@ impl<'a> Builder<'a> {
                 rustflags.arg("-Zvalidate-mir");
                 rustflags.arg(&format!("-Zmir-opt-level={}", mir_opt_level));
             }
+            // Always enable inlining MIR when building the standard library.
+            // Without this flag, MIR inlining is disabled when incremental compilation is enabled.
+            // That causes some mir-opt tests which inline functions from the standard library to
+            // break when incremental compilation is enabled. So this overrides the "no inlining
+            // during incremental builds" heuristic for the standard library.
+            rustflags.arg("-Zinline-mir");
         }
 
         Cargo { command: cargo, rustflags, rustdocflags, allow_features }
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 54971af644c..e3581943f2c 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -20,11 +20,11 @@ use serde_derive::Deserialize;
 
 use crate::builder::crate_description;
 use crate::builder::Cargo;
-use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
+use crate::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath};
 use crate::cache::{Interned, INTERNER};
 use crate::config::{LlvmLibunwind, RustcLto, TargetSelection};
 use crate::dist;
-use crate::native;
+use crate::llvm;
 use crate::tool::SourceType;
 use crate::util::get_clang_cl_resource_dir;
 use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date};
@@ -191,7 +191,7 @@ fn copy_and_stamp(
 }
 
 fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
-    let libunwind_path = builder.ensure(native::Libunwind { target });
+    let libunwind_path = builder.ensure(llvm::Libunwind { target });
     let libunwind_source = libunwind_path.join("libunwind.a");
     let libunwind_target = libdir.join("libunwind.a");
     builder.copy(&libunwind_source, &libunwind_target);
@@ -266,7 +266,7 @@ fn copy_self_contained_objects(
                 DependencyType::TargetSelfContained,
             );
         }
-        let crt_path = builder.ensure(native::CrtBeginEnd { target });
+        let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
         for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
             let src = crt_path.join(obj);
             let target = libdir_self_contained.join(obj);
@@ -474,7 +474,7 @@ fn copy_sanitizers(
     compiler: &Compiler,
     target: TargetSelection,
 ) -> Vec<PathBuf> {
-    let runtimes: Vec<native::SanitizerRuntime> = builder.ensure(native::Sanitizers { target });
+    let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
 
     if builder.config.dry_run() {
         return Vec::new();
@@ -876,12 +876,12 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
     // busting caches (e.g. like #71152).
     if builder.config.llvm_enabled()
         && (builder.kind != Kind::Check
-            || crate::native::prebuilt_llvm_config(builder, target).is_ok())
+            || crate::llvm::prebuilt_llvm_config(builder, target).is_ok())
     {
         if builder.is_rust_llvm(target) {
             cargo.env("LLVM_RUSTLLVM", "1");
         }
-        let native::LlvmResult { llvm_config, .. } = builder.ensure(native::Llvm { target });
+        let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
         cargo.env("LLVM_CONFIG", &llvm_config);
         if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
             cargo.env("CFG_LLVM_ROOT", s);
@@ -995,6 +995,44 @@ pub struct CodegenBackend {
     pub backend: Interned<String>,
 }
 
+fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
+    let mut needs_codegen_cfg = false;
+    for path_set in &run.paths {
+        needs_codegen_cfg = match path_set {
+            PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
+            PathSet::Suite(suite) => is_codegen_cfg_needed(&suite, run),
+        }
+    }
+    needs_codegen_cfg
+}
+
+const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
+
+fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
+    if path.path.to_str().unwrap().contains(&CODEGEN_BACKEND_PREFIX) {
+        let mut needs_codegen_backend_config = true;
+        for &backend in &run.builder.config.rust_codegen_backends {
+            if path
+                .path
+                .to_str()
+                .unwrap()
+                .ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + &backend))
+            {
+                needs_codegen_backend_config = false;
+            }
+        }
+        if needs_codegen_backend_config {
+            run.builder.info(
+                "Warning: no codegen-backends config matched the requested path to build a codegen backend. \
+                Help: add backend to codegen-backends in config.toml.",
+            );
+            return true;
+        }
+    }
+
+    return false;
+}
+
 impl Step for CodegenBackend {
     type Output = ();
     const ONLY_HOSTS: bool = true;
@@ -1006,6 +1044,10 @@ impl Step for CodegenBackend {
     }
 
     fn make_run(run: RunConfig<'_>) {
+        if needs_codegen_config(&run) {
+            return;
+        }
+
         for &backend in &run.builder.config.rust_codegen_backends {
             if backend == "llvm" {
                 continue; // Already built as part of rustc
@@ -1346,6 +1388,13 @@ impl Step for Assemble {
         // when not performing a full bootstrap).
         builder.ensure(Rustc::new(build_compiler, target_compiler.host));
 
+        // FIXME: For now patch over problems noted in #90244 by early returning here, even though
+        // we've not properly assembled the target sysroot. A full fix is pending further investigation,
+        // for now full bootstrap usage is rare enough that this is OK.
+        if target_compiler.stage >= 3 && !builder.config.full_bootstrap {
+            return target_compiler;
+        }
+
         for &backend in builder.config.rust_codegen_backends.iter() {
             if backend == "llvm" {
                 continue; // Already built as part of rustc
@@ -1359,7 +1408,7 @@ impl Step for Assemble {
         }
 
         let lld_install = if builder.config.lld_enabled {
-            Some(builder.ensure(native::Lld { target: target_compiler.host }))
+            Some(builder.ensure(llvm::Lld { target: target_compiler.host }))
         } else {
             None
         };
@@ -1423,8 +1472,8 @@ impl Step for Assemble {
         }
 
         if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
-            let native::LlvmResult { llvm_config, .. } =
-                builder.ensure(native::Llvm { target: target_compiler.host });
+            let llvm::LlvmResult { llvm_config, .. } =
+                builder.ensure(llvm::Llvm { target: target_compiler.host });
             if !builder.config.dry_run() {
                 let llvm_bin_dir = output(Command::new(llvm_config).arg("--bindir"));
                 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 95625170478..b8b6b7b2d4e 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -808,6 +808,8 @@ define_config! {
 
 impl Config {
     pub fn default_opts() -> Config {
+        use is_terminal::IsTerminal;
+
         let mut config = Config::default();
         config.llvm_optimize = true;
         config.ninja_in_file = true;
@@ -828,8 +830,8 @@ impl Config {
         config.dist_include_mingw_linker = true;
         config.dist_compression_profile = "fast".into();
 
-        config.stdout_is_tty = atty::is(atty::Stream::Stdout);
-        config.stderr_is_tty = atty::is(atty::Stream::Stderr);
+        config.stdout_is_tty = std::io::stdout().is_terminal();
+        config.stderr_is_tty = std::io::stderr().is_terminal();
 
         // set by build.rs
         config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
@@ -1207,11 +1209,11 @@ impl Config {
             config.llvm_from_ci = match llvm.download_ci_llvm {
                 Some(StringOrBool::String(s)) => {
                     assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s);
-                    crate::native::is_ci_llvm_available(&config, asserts)
+                    crate::llvm::is_ci_llvm_available(&config, asserts)
                 }
                 Some(StringOrBool::Bool(b)) => b,
                 None => {
-                    config.channel == "dev" && crate::native::is_ci_llvm_available(&config, asserts)
+                    config.channel == "dev" && crate::llvm::is_ci_llvm_available(&config, asserts)
                 }
             };
 
@@ -1254,7 +1256,7 @@ impl Config {
             }
         } else {
             config.llvm_from_ci =
-                config.channel == "dev" && crate::native::is_ci_llvm_available(&config, false);
+                config.channel == "dev" && crate::llvm::is_ci_llvm_available(&config, false);
         }
 
         if let Some(t) = toml.target {
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index 16dc8c63abc..5cea143e0a7 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -11,7 +11,7 @@ fn parse(config: &str) -> Config {
 
 #[test]
 fn download_ci_llvm() {
-    if crate::native::is_ci_llvm_modified(&parse("")) {
+    if crate::llvm::is_ci_llvm_modified(&parse("")) {
         eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change");
         return;
     }
diff --git a/src/bootstrap/defaults/config.user.toml b/src/bootstrap/defaults/config.user.toml
index ee271c3fb51..25d9e649f23 100644
--- a/src/bootstrap/defaults/config.user.toml
+++ b/src/bootstrap/defaults/config.user.toml
@@ -8,9 +8,11 @@ doc-stage = 2
 # When compiling from source, you usually want all tools.
 extended = true
 
+# Most users installing from source want to build all parts of the project from source.
 [llvm]
-# Most users installing from source want to build all parts of the project from source, not just rustc itself.
 download-ci-llvm = false
+[rust]
+download-rustc = false
 
 [dist]
 # Use better compression when preparing tarballs.
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index dceb4bd1b89..2ce54d9a3b4 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -27,7 +27,7 @@ use crate::channel;
 use crate::compile;
 use crate::config::TargetSelection;
 use crate::doc::DocumentationFormat;
-use crate::native;
+use crate::llvm;
 use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
 use crate::tool::{self, Tool};
 use crate::util::{exe, is_dylib, output, t, timeit};
@@ -1965,8 +1965,8 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
         }
         !builder.config.dry_run()
-    } else if let Ok(native::LlvmResult { llvm_config, .. }) =
-        native::prebuilt_llvm_config(builder, target)
+    } else if let Ok(llvm::LlvmResult { llvm_config, .. }) =
+        llvm::prebuilt_llvm_config(builder, target)
     {
         let mut cmd = Command::new(llvm_config);
         cmd.arg("--libfiles");
@@ -2154,7 +2154,7 @@ impl Step for LlvmTools {
             }
         }
 
-        builder.ensure(crate::native::Llvm { target });
+        builder.ensure(crate::llvm::Llvm { target });
 
         let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
         tarball.set_overlay(OverlayKind::LLVM);
@@ -2213,10 +2213,10 @@ impl Step for RustDev {
         let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
         tarball.set_overlay(OverlayKind::LLVM);
 
-        builder.ensure(crate::native::Llvm { target });
+        builder.ensure(crate::llvm::Llvm { target });
 
         // We want to package `lld` to use it with `download-ci-llvm`.
-        builder.ensure(crate::native::Lld { target });
+        builder.ensure(crate::llvm::Lld { target });
 
         let src_bindir = builder.llvm_out(target).join("bin");
         // If updating this list, you likely want to change
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 36fdd4abf4f..be43affa404 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -1027,10 +1027,11 @@ impl Step for RustcBook {
         if self.validate {
             cmd.arg("--validate");
         }
-        if !builder.unstable_features() {
-            // We need to validate nightly features, even on the stable channel.
-            cmd.env("RUSTC_BOOTSTRAP", "1");
-        }
+        // We need to validate nightly features, even on the stable channel.
+        // Set this unconditionally as the stage0 compiler may be being used to
+        // document.
+        cmd.env("RUSTC_BOOTSTRAP", "1");
+
         // If the lib directories are in an unusual location (changed in
         // config.toml), then this needs to explicitly update the dylib search
         // path.
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index d1e2149d3f9..8fbc034965a 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -12,7 +12,7 @@ use xz2::bufread::XzDecoder;
 
 use crate::{
     config::RustfmtMetadata,
-    native::detect_llvm_sha,
+    llvm::detect_llvm_sha,
     t,
     util::{check_run, exe, program_out_of_date, try_run},
     Config,
diff --git a/src/bootstrap/dylib_util.rs b/src/bootstrap/dylib_util.rs
index 6d75272c501..b14c0bed66c 100644
--- a/src/bootstrap/dylib_util.rs
+++ b/src/bootstrap/dylib_util.rs
@@ -12,6 +12,8 @@ pub fn dylib_path_var() -> &'static str {
         "DYLD_LIBRARY_PATH"
     } else if cfg!(target_os = "haiku") {
         "LIBRARY_PATH"
+    } else if cfg!(target_os = "aix") {
+        "LIBPATH"
     } else {
         "LD_LIBRARY_PATH"
     }
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 54aa5a585bb..e3f3ab5243e 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -21,7 +21,6 @@ use std::collections::{HashMap, HashSet};
 use std::env;
 use std::fs::{self, File};
 use std::io;
-use std::io::ErrorKind;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 use std::str;
@@ -53,8 +52,8 @@ mod download;
 mod flags;
 mod format;
 mod install;
+mod llvm;
 mod metadata;
-mod native;
 mod render_tests;
 mod run;
 mod sanity;
@@ -125,6 +124,7 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
     (Some(Mode::Std), "no_rc", None),
     (Some(Mode::Std), "no_sync", None),
     (Some(Mode::Std), "freebsd12", None),
+    (Some(Mode::Std), "freebsd13", None),
     (Some(Mode::Std), "backtrace_in_libstd", None),
     /* Extra values not defined in the built-in targets yet, but used in std */
     (Some(Mode::Std), "target_env", Some(&["libnx"])),
@@ -149,6 +149,8 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
     // Needed to avoid the need to copy windows.lib into the sysroot.
     (Some(Mode::Rustc), "windows_raw_dylib", None),
     (Some(Mode::ToolRustc), "windows_raw_dylib", None),
+    // #[cfg(bootstrap)] ohos
+    (Some(Mode::Std), "target_env", Some(&["ohos"])),
 ];
 
 /// A structure representing a Rust compiler.
@@ -502,16 +504,18 @@ impl Build {
         let build_triple = build.out.join(&build.build.triple);
         t!(fs::create_dir_all(&build_triple));
         let host = build.out.join("host");
-        if let Err(e) = symlink_dir(&build.config, &build_triple, &host) {
-            if e.kind() != ErrorKind::AlreadyExists {
-                panic!(
-                    "symlink_dir({} => {}) failed with {}",
-                    host.display(),
-                    build_triple.display(),
-                    e
-                );
-            }
-        }
+        if host.is_symlink() {
+            // Left over from a previous build; overwrite it.
+            // This matters if `build.build` has changed between invocations.
+            #[cfg(windows)]
+            t!(fs::remove_dir(&host));
+            #[cfg(not(windows))]
+            t!(fs::remove_file(&host));
+        }
+        t!(
+            symlink_dir(&build.config, &build_triple, &host),
+            format!("symlink_dir({} => {}) failed", host.display(), build_triple.display())
+        );
 
         build
     }
diff --git a/src/bootstrap/native.rs b/src/bootstrap/llvm.rs
index f27db5c91e2..cc2b45a9bdb 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/llvm.rs
@@ -434,11 +434,6 @@ impl Step for Llvm {
             }
         }
 
-        // Workaround for ppc32 lld limitation
-        if target == "powerpc-unknown-freebsd" {
-            ldflags.exe.push(" -fuse-ld=bfd");
-        }
-
         // https://llvm.org/docs/HowToCrossCompileLLVM.html
         if target != builder.config.build {
             let LlvmResult { llvm_config, .. } =
@@ -870,71 +865,6 @@ impl Step for Lld {
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct TestHelpers {
-    pub target: TargetSelection,
-}
-
-impl Step for TestHelpers {
-    type Output = ();
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("tests/auxiliary/rust_test_helpers.c")
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(TestHelpers { target: run.target })
-    }
-
-    /// Compiles the `rust_test_helpers.c` library which we used in various
-    /// `run-pass` tests for ABI testing.
-    fn run(self, builder: &Builder<'_>) {
-        if builder.config.dry_run() {
-            return;
-        }
-        // The x86_64-fortanix-unknown-sgx target doesn't have a working C
-        // toolchain. However, some x86_64 ELF objects can be linked
-        // without issues. Use this hack to compile the test helpers.
-        let target = if self.target == "x86_64-fortanix-unknown-sgx" {
-            TargetSelection::from_user("x86_64-unknown-linux-gnu")
-        } else {
-            self.target
-        };
-        let dst = builder.test_helpers_out(target);
-        let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
-        if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
-            return;
-        }
-
-        builder.info("Building test helpers");
-        t!(fs::create_dir_all(&dst));
-        let mut cfg = cc::Build::new();
-        // FIXME: Workaround for https://github.com/emscripten-core/emscripten/issues/9013
-        if target.contains("emscripten") {
-            cfg.pic(false);
-        }
-
-        // We may have found various cross-compilers a little differently due to our
-        // extra configuration, so inform cc of these compilers. Note, though, that
-        // on MSVC we still need cc's detection of env vars (ugh).
-        if !target.contains("msvc") {
-            if let Some(ar) = builder.ar(target) {
-                cfg.archiver(ar);
-            }
-            cfg.compiler(builder.cc(target));
-        }
-        cfg.cargo_metadata(false)
-            .out_dir(&dst)
-            .target(&target.triple)
-            .host(&builder.config.build.triple)
-            .opt_level(0)
-            .warnings(false)
-            .debug(false)
-            .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
-            .compile("rust_test_helpers");
-    }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Sanitizers {
     pub target: TargetSelection,
 }
@@ -1073,6 +1003,9 @@ fn supported_sanitizers(
         "aarch64-unknown-linux-gnu" => {
             common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"])
         }
+        "aarch64-unknown-linux-ohos" => {
+            common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"])
+        }
         "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
         "x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
         "x86_64-apple-ios" => darwin_libs("iossim", &["asan", "tsan"]),
diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/metrics.rs
index 5f254761aa1..82b123ec8a5 100644
--- a/src/bootstrap/metrics.rs
+++ b/src/bootstrap/metrics.rs
@@ -11,7 +11,7 @@ use serde_derive::{Deserialize, Serialize};
 use std::cell::RefCell;
 use std::fs::File;
 use std::io::BufWriter;
-use std::time::{Duration, Instant};
+use std::time::{Duration, Instant, SystemTime};
 use sysinfo::{CpuExt, System, SystemExt};
 
 pub(crate) struct BuildMetrics {
@@ -27,6 +27,7 @@ impl BuildMetrics {
             system_info: System::new(),
             timer_start: None,
             invocation_timer_start: Instant::now(),
+            invocation_start: SystemTime::now(),
         });
 
         BuildMetrics { state }
@@ -124,6 +125,11 @@ impl BuildMetrics {
             }
         };
         invocations.push(JsonInvocation {
+            start_time: state
+                .invocation_start
+                .duration_since(SystemTime::UNIX_EPOCH)
+                .unwrap()
+                .as_secs(),
             duration_including_children_sec: state.invocation_timer_start.elapsed().as_secs_f64(),
             children: steps.into_iter().map(|step| self.prepare_json_step(step)).collect(),
         });
@@ -166,6 +172,7 @@ struct MetricsState {
     system_info: System,
     timer_start: Option<Instant>,
     invocation_timer_start: Instant,
+    invocation_start: SystemTime,
 }
 
 struct StepMetrics {
@@ -194,6 +201,10 @@ struct JsonRoot {
 #[derive(Serialize, Deserialize)]
 #[serde(rename_all = "snake_case")]
 struct JsonInvocation {
+    // Unix timestamp in seconds
+    //
+    // This is necessary to easily correlate this invocation with logs or other data.
+    start_time: u64,
     duration_including_children_sec: f64,
     children: Vec<JsonNode>,
 }
diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs
index af2370d439e..19019ad2c08 100644
--- a/src/bootstrap/render_tests.rs
+++ b/src/bootstrap/render_tests.rs
@@ -100,18 +100,13 @@ impl<'a> Renderer<'a> {
                 break;
             }
 
-            let trimmed = line.trim();
-            if trimmed.starts_with("{") && trimmed.ends_with("}") {
-                self.render_message(match serde_json::from_str(&trimmed) {
-                    Ok(parsed) => parsed,
-                    Err(err) => {
-                        panic!("failed to parse libtest json output; error: {err}, line: {line:?}");
-                    }
-                });
-            } else {
-                // Handle non-JSON output, for example when --nocapture is passed.
-                print!("{line}");
-                let _ = std::io::stdout().flush();
+            match serde_json::from_str(&line) {
+                Ok(parsed) => self.render_message(parsed),
+                Err(_err) => {
+                    // Handle non-JSON output, for example when --nocapture is passed.
+                    print!("{line}");
+                    let _ = std::io::stdout().flush();
+                }
             }
         }
     }
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 29d37c09d88..92a7603a9df 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -19,11 +19,11 @@ use crate::config::TargetSelection;
 use crate::dist;
 use crate::doc::DocumentationFormat;
 use crate::flags::Subcommand;
-use crate::native;
+use crate::llvm;
 use crate::render_tests::add_flags_and_try_run_tests;
 use crate::tool::{self, SourceType, Tool};
 use crate::toolstate::ToolState;
-use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t};
+use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t, up_to_date};
 use crate::{envify, CLang, DocTests, GitRepo, Mode};
 
 const ADB_TEST_DIR: &str = "/data/local/tmp/work";
@@ -1434,11 +1434,11 @@ note: if you're sure you want to do this, please open an issue as to why. In the
         builder.ensure(compile::Std::new(compiler, compiler.host));
 
         // Also provide `rust_test_helpers` for the host.
-        builder.ensure(native::TestHelpers { target: compiler.host });
+        builder.ensure(TestHelpers { target: compiler.host });
 
         // As well as the target, except for plain wasm32, which can't build it
         if !target.contains("wasm") || target.contains("emscripten") {
-            builder.ensure(native::TestHelpers { target });
+            builder.ensure(TestHelpers { target });
         }
 
         builder.ensure(RemoteCopyLibs { compiler, target });
@@ -1625,8 +1625,8 @@ note: if you're sure you want to do this, please open an issue as to why. In the
         let mut llvm_components_passed = false;
         let mut copts_passed = false;
         if builder.config.llvm_enabled() {
-            let native::LlvmResult { llvm_config, .. } =
-                builder.ensure(native::Llvm { target: builder.config.build });
+            let llvm::LlvmResult { llvm_config, .. } =
+                builder.ensure(llvm::Llvm { target: builder.config.build });
             if !builder.config.dry_run() {
                 let llvm_version = output(Command::new(&llvm_config).arg("--version"));
                 let llvm_components = output(Command::new(&llvm_config).arg("--components"));
@@ -1664,7 +1664,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
                 // If LLD is available, add it to the PATH
                 if builder.config.lld_enabled {
                     let lld_install_root =
-                        builder.ensure(native::Lld { target: builder.config.build });
+                        builder.ensure(llvm::Lld { target: builder.config.build });
 
                     let lld_bin_path = lld_install_root.join("bin");
 
@@ -2747,3 +2747,68 @@ impl Step for RustInstaller {
         run.builder.ensure(Self);
     }
 }
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct TestHelpers {
+    pub target: TargetSelection,
+}
+
+impl Step for TestHelpers {
+    type Output = ();
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("tests/auxiliary/rust_test_helpers.c")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(TestHelpers { target: run.target })
+    }
+
+    /// Compiles the `rust_test_helpers.c` library which we used in various
+    /// `run-pass` tests for ABI testing.
+    fn run(self, builder: &Builder<'_>) {
+        if builder.config.dry_run() {
+            return;
+        }
+        // The x86_64-fortanix-unknown-sgx target doesn't have a working C
+        // toolchain. However, some x86_64 ELF objects can be linked
+        // without issues. Use this hack to compile the test helpers.
+        let target = if self.target == "x86_64-fortanix-unknown-sgx" {
+            TargetSelection::from_user("x86_64-unknown-linux-gnu")
+        } else {
+            self.target
+        };
+        let dst = builder.test_helpers_out(target);
+        let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
+        if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
+            return;
+        }
+
+        builder.info("Building test helpers");
+        t!(fs::create_dir_all(&dst));
+        let mut cfg = cc::Build::new();
+        // FIXME: Workaround for https://github.com/emscripten-core/emscripten/issues/9013
+        if target.contains("emscripten") {
+            cfg.pic(false);
+        }
+
+        // We may have found various cross-compilers a little differently due to our
+        // extra configuration, so inform cc of these compilers. Note, though, that
+        // on MSVC we still need cc's detection of env vars (ugh).
+        if !target.contains("msvc") {
+            if let Some(ar) = builder.ar(target) {
+                cfg.archiver(ar);
+            }
+            cfg.compiler(builder.cc(target));
+        }
+        cfg.cargo_metadata(false)
+            .out_dir(&dst)
+            .target(&target.triple)
+            .host(&builder.config.build.triple)
+            .opt_level(0)
+            .warnings(false)
+            .debug(false)
+            .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
+            .compile("rust_test_helpers");
+    }
+}