about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_llvm/build.rs29
-rw-r--r--config.example.toml3
-rw-r--r--src/bootstrap/download-ci-llvm-stamp2
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs12
-rw-r--r--src/bootstrap/src/core/config/config.rs6
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile5
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile2
-rwxr-xr-xsrc/ci/docker/scripts/zstd.sh29
-rw-r--r--tests/run-make/rust-lld-compress-debug-sections/main.rs1
-rw-r--r--tests/run-make/rust-lld-compress-debug-sections/rmake.rs39
11 files changed, 126 insertions, 7 deletions
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 4c1f78e6bee..b2ff9efb41c 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -259,6 +259,7 @@ fn main() {
     cmd.args(&components);
 
     for lib in output(&mut cmd).split_whitespace() {
+        let mut is_static = false;
         let name = if let Some(stripped) = lib.strip_prefix("-l") {
             stripped
         } else if let Some(stripped) = lib.strip_prefix('-') {
@@ -266,8 +267,24 @@ fn main() {
         } else if Path::new(lib).exists() {
             // On MSVC llvm-config will print the full name to libraries, but
             // we're only interested in the name part
-            let name = Path::new(lib).file_name().unwrap().to_str().unwrap();
-            name.trim_end_matches(".lib")
+            // On Unix when we get a static library llvm-config will print the
+            // full name and we *are* interested in the path, but we need to
+            // handle it separately. For example, when statically linking to
+            // libzstd llvm-config will output something like
+            //   -lrt -ldl -lm -lz /usr/local/lib/libzstd.a -lxml2
+            // and we transform the zstd part into
+            //   cargo:rustc-link-search-native=/usr/local/lib
+            //   cargo:rustc-link-lib=static=zstd
+            let path = Path::new(lib);
+            if lib.ends_with(".a") {
+                is_static = true;
+                println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display());
+                let name = path.file_stem().unwrap().to_str().unwrap();
+                name.trim_start_matches("lib")
+            } else {
+                let name = path.file_name().unwrap().to_str().unwrap();
+                name.trim_end_matches(".lib")
+            }
         } else if lib.ends_with(".lib") {
             // Some MSVC libraries just come up with `.lib` tacked on, so chop
             // that off
@@ -285,7 +302,13 @@ fn main() {
             continue;
         }
 
-        let kind = if name.starts_with("LLVM") { llvm_kind } else { "dylib" };
+        let kind = if name.starts_with("LLVM") {
+            llvm_kind
+        } else if is_static {
+            "static"
+        } else {
+            "dylib"
+        };
         println!("cargo:rustc-link-lib={kind}={name}");
     }
 
diff --git a/config.example.toml b/config.example.toml
index 1a7bdc4737f..1b7de662e84 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -87,6 +87,9 @@
 # library provided by LLVM.
 #static-libstdcpp = false
 
+# Enable LLVM to use zstd for compression.
+#libzstd = false
+
 # Whether to use Ninja to build LLVM. This runs much faster than make.
 #ninja = true
 
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index 258a0347451..11316004412 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
 Change this file to make users of the `download-ci-llvm` configuration download
 a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
 
-Last change is for: https://github.com/rust-lang/rust/pull/126298
+Last change is for: https://github.com/rust-lang/rust/pull/125642
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 81e591be699..ffae245dfb5 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -368,9 +368,7 @@ impl Step for Llvm {
             cfg.define("LLVM_PROFDATA_FILE", path);
         }
 
-        // Disable zstd to avoid a dependency on libzstd.so.
-        cfg.define("LLVM_ENABLE_ZSTD", "OFF");
-
+        // Libraries for ELF section compression.
         if !target.is_windows() {
             cfg.define("LLVM_ENABLE_ZLIB", "ON");
         } else {
@@ -824,6 +822,14 @@ fn configure_llvm(builder: &Builder<'_>, target: TargetSelection, cfg: &mut cmak
         }
     }
 
+    // Libraries for ELF section compression.
+    if builder.config.llvm_libzstd {
+        cfg.define("LLVM_ENABLE_ZSTD", "FORCE_ON");
+        cfg.define("LLVM_USE_STATIC_ZSTD", "TRUE");
+    } else {
+        cfg.define("LLVM_ENABLE_ZSTD", "OFF");
+    }
+
     if let Some(ref linker) = builder.config.llvm_use_linker {
         cfg.define("LLVM_USE_LINKER", linker);
     }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index f0a55830167..915fcb449e8 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -218,6 +218,7 @@ pub struct Config {
     pub llvm_thin_lto: bool,
     pub llvm_release_debuginfo: bool,
     pub llvm_static_stdcpp: bool,
+    pub llvm_libzstd: bool,
     /// `None` if `llvm_from_ci` is true and we haven't yet downloaded llvm.
     #[cfg(not(test))]
     llvm_link_shared: Cell<Option<bool>>,
@@ -878,6 +879,7 @@ define_config! {
         plugins: Option<bool> = "plugins",
         ccache: Option<StringOrBool> = "ccache",
         static_libstdcpp: Option<bool> = "static-libstdcpp",
+        libzstd: Option<bool> = "libzstd",
         ninja: Option<bool> = "ninja",
         targets: Option<String> = "targets",
         experimental_targets: Option<String> = "experimental-targets",
@@ -1153,6 +1155,7 @@ impl Config {
             llvm_optimize: true,
             ninja_in_file: true,
             llvm_static_stdcpp: false,
+            llvm_libzstd: false,
             backtrace: true,
             rust_optimize: RustOptimize::Bool(true),
             rust_optimize_tests: true,
@@ -1791,6 +1794,7 @@ impl Config {
                 plugins,
                 ccache,
                 static_libstdcpp,
+                libzstd,
                 ninja,
                 targets,
                 experimental_targets,
@@ -1825,6 +1829,7 @@ impl Config {
             set(&mut config.llvm_thin_lto, thin_lto);
             set(&mut config.llvm_release_debuginfo, release_debuginfo);
             set(&mut config.llvm_static_stdcpp, static_libstdcpp);
+            set(&mut config.llvm_libzstd, libzstd);
             if let Some(v) = link_shared {
                 config.llvm_link_shared.set(Some(v));
             }
@@ -1875,6 +1880,7 @@ impl Config {
                 check_ci_llvm!(optimize_toml);
                 check_ci_llvm!(thin_lto);
                 check_ci_llvm!(release_debuginfo);
+                check_ci_llvm!(libzstd);
                 check_ci_llvm!(targets);
                 check_ci_llvm!(experimental_targets);
                 check_ci_llvm!(clang_cl);
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index b8f70fdf6a8..84dac25188e 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -220,4 +220,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "For tarball sources, default value for `rust.channel` will be taken from `src/ci/channel` file.",
     },
+    ChangeInfo {
+        change_id: 125642,
+        severity: ChangeSeverity::Info,
+        summary: "New option `llvm.libzstd` to control whether llvm is built with zstd support.",
+    },
 ];
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 4aa1a3ccc2a..61e9694f1e2 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -62,6 +62,10 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/
 RUN ./build-clang.sh
 ENV CC=clang CXX=clang++
 
+# rustc's LLVM needs zstd.
+COPY scripts/zstd.sh /tmp/
+RUN ./zstd.sh
+
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
@@ -79,6 +83,7 @@ ENV RUST_CONFIGURE_ARGS \
       --set target.x86_64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \
       --set llvm.thin-lto=true \
       --set llvm.ninja=false \
+      --set llvm.libzstd=true \
       --set rust.jemalloc \
       --set rust.use-lld=true \
       --set rust.lto=thin \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
index 9025e9bb0a3..19683317126 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
@@ -17,6 +17,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config \
   xz-utils \
   mingw-w64 \
+  zlib1g-dev \
+  libzstd-dev \
   && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
diff --git a/src/ci/docker/scripts/zstd.sh b/src/ci/docker/scripts/zstd.sh
new file mode 100755
index 00000000000..a3d37ccc311
--- /dev/null
+++ b/src/ci/docker/scripts/zstd.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+set -ex
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/zstd_build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  "$@" &> /tmp/zstd_build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  rm /tmp/zstd_build.log
+  set -x
+}
+
+ZSTD=1.5.6
+curl -L https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz | tar xzf -
+
+cd zstd-$ZSTD
+CFLAGS=-fPIC hide_output make -j$(nproc) VERBOSE=1
+hide_output make install
+
+cd ..
+rm -rf zstd-$ZSTD
diff --git a/tests/run-make/rust-lld-compress-debug-sections/main.rs b/tests/run-make/rust-lld-compress-debug-sections/main.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/rust-lld-compress-debug-sections/main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/rust-lld-compress-debug-sections/rmake.rs b/tests/run-make/rust-lld-compress-debug-sections/rmake.rs
new file mode 100644
index 00000000000..df9691ccbcf
--- /dev/null
+++ b/tests/run-make/rust-lld-compress-debug-sections/rmake.rs
@@ -0,0 +1,39 @@
+// Checks the `compress-debug-sections` option on rust-lld.
+
+//@ needs-rust-lld
+//@ only-linux
+//@ ignore-cross-compile
+
+// FIXME: This test isn't comprehensive and isn't covering all possible combinations.
+
+use run_make_support::{assert_contains, cmd, llvm_readobj, run_in_tmpdir, rustc};
+
+fn check_compression(compression: &str, to_find: &str) {
+    run_in_tmpdir(|| {
+        let out = rustc()
+            .arg("-Zlinker-features=+lld")
+            .arg("-Clink-self-contained=+linker")
+            .arg("-Zunstable-options")
+            .arg("-Cdebuginfo=full")
+            .link_arg(&format!("-Wl,--compress-debug-sections={compression}"))
+            .input("main.rs")
+            .run_unchecked();
+        let stderr = out.stderr_utf8();
+        if stderr.is_empty() {
+            llvm_readobj().arg("-t").arg("main").run().assert_stdout_contains(to_find);
+        } else {
+            assert_contains(
+                stderr,
+                format!(
+                    "LLVM was not built with LLVM_ENABLE_{to_find} \
+                     or did not find {compression} at build time"
+                ),
+            );
+        }
+    });
+}
+
+fn main() {
+    check_compression("zlib", "ZLIB");
+    check_compression("zstd", "ZSTD");
+}