about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2024-08-10 08:11:22 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2024-08-11 04:16:53 +0200
commit486864f23593d7aedddf1831f748660311f9ff3c (patch)
tree55d32cbb8b8334af8bd76c9edeb1f49f7b53e71e
parent736a249954aedaff9b3562f073e295d6c4c6d94d (diff)
downloadrust-486864f23593d7aedddf1831f748660311f9ff3c.tar.gz
rust-486864f23593d7aedddf1831f748660311f9ff3c.zip
Don't statically link `std` into `rustc_driver` for `windows-gnu`
-rw-r--r--src/bootstrap/src/bin/rustc.rs8
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs12
-rw-r--r--src/bootstrap/src/core/builder.rs14
3 files changed, 30 insertions, 4 deletions
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index f3198338dc3..d04e2fbeb78 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -92,9 +92,11 @@ fn main() {
     // Get the name of the crate we're compiling, if any.
     let crate_name = parse_value_from_args(&orig_args, "--crate-name");
 
-    // We want everything statically linked into `rustc_driver`, so remove `-C prefer-dynamic`
-    if crate_name == Some("rustc_driver") && stage != "0" {
-        // Remove `-C prefer-dynamic` to link `std` statically into `rustc_driver`
+    // When statically linking `std` into `rustc_driver`, remove `-C prefer-dynamic`
+    if env::var("RUSTC_LINK_STD_INTO_RUSTC_DRIVER").unwrap() == "1"
+        && crate_name == Some("rustc_driver")
+        && stage != "0"
+    {
         if let Some(pos) = args.iter().enumerate().position(|(i, a)| {
             a == "-C" && args.get(i + 1).map(|a| a == "prefer-dynamic").unwrap_or(false)
         }) {
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 76006bfe0e5..2e521ff7544 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1830,15 +1830,25 @@ impl Step for Assemble {
             })
             .collect::<HashSet<_>>();
 
+        let link_std_into_rustc_driver = builder.link_std_into_rustc_driver(target_compiler.host);
         let sysroot = builder.sysroot(target_compiler);
         let rustc_libdir = builder.rustc_libdir(target_compiler);
         t!(fs::create_dir_all(&rustc_libdir));
         let src_libdir = builder.sysroot_libdir(build_compiler, host);
         for f in builder.read_dir(&src_libdir) {
             let filename = f.file_name().into_string().unwrap();
+
+            // For the later stages which gets distributed only copy over the
+            // `rustc_driver` library so we don't end up with an extra copy of `std`.
+            // If we're not statically linking `std` into `rustc_driver`, just copy every library
+            // to ensure `std` is included.
+            // We still need `std` for the initial stage as the bootstrap compiler may not
+            // have the new `rustc_private` linking behavior.
             let can_be_rustc_dep = filename.starts_with("rustc_driver-")
                 || filename.starts_with("librustc_driver-")
-                || build_compiler.stage == 0;
+                || build_compiler.stage == 0
+                || !link_std_into_rustc_driver;
+
             if can_be_rustc_dep
                 && (is_dylib(&filename) || is_debug_info(&filename))
                 && !proc_macros.contains(&filename)
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 41837c0eb89..ccdeb442af4 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -1106,6 +1106,12 @@ impl<'a> Builder<'a> {
         StepDescription::run(v, self, paths);
     }
 
+    /// Returns if `std` should be statically linked into `rustc_driver`.
+    /// It's currently not done on `windows-gnu` due to linker bugs.
+    pub fn link_std_into_rustc_driver(&self, target: TargetSelection) -> bool {
+        !target.triple.ends_with("-windows-gnu")
+    }
+
     /// Obtain a compiler at a given stage and for a given host (i.e., this is the target that the
     /// compiler will run on, *not* the target it will build code for). Explicitly does not take
     /// `Compiler` since all `Compiler` instances are meant to be obtained through this function,
@@ -2165,6 +2171,14 @@ impl<'a> Builder<'a> {
         if matches!(mode, Mode::Std) {
             rustflags.arg("-Cprefer-dynamic");
         }
+        if matches!(mode, Mode::Rustc) && !self.link_std_into_rustc_driver(target) {
+            rustflags.arg("-Cprefer-dynamic");
+        }
+
+        cargo.env(
+            "RUSTC_LINK_STD_INTO_RUSTC_DRIVER",
+            if self.link_std_into_rustc_driver(target) { "1" } else { "0" },
+        );
 
         // When building incrementally we default to a lower ThinLTO import limit
         // (unless explicitly specified otherwise). This will produce a somewhat