Skip to content

Commit eafcdf4

Browse files
committed
Auto merge of rust-lang#125642 - khuey:zstd, r=<try>
Enable zstd for debug compression. Set LLVM_ENABLE_ZSTD alongside LLVM_ENABLE_ZLIB so that --compress-debug-sections=zstd is an option. See rust-lang#120953
2 parents 188ddf4 + c788d1e commit eafcdf4

File tree

10 files changed

+112
-13
lines changed

10 files changed

+112
-13
lines changed

compiler/rustc_llvm/build.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -259,15 +259,32 @@ fn main() {
259259
cmd.args(&components);
260260

261261
for lib in output(&mut cmd).split_whitespace() {
262+
let mut is_static = false;
262263
let name = if let Some(stripped) = lib.strip_prefix("-l") {
263264
stripped
264265
} else if let Some(stripped) = lib.strip_prefix('-') {
265266
stripped
266267
} else if Path::new(lib).exists() {
267268
// On MSVC llvm-config will print the full name to libraries, but
268269
// we're only interested in the name part
269-
let name = Path::new(lib).file_name().unwrap().to_str().unwrap();
270-
name.trim_end_matches(".lib")
270+
// On Unix when we get a static library llvm-config will print the
271+
// full name and we *are* interested in the path, but we need to
272+
// handle it separately. For example, when statically linking to
273+
// libzstd llvm-config will output something like
274+
// -lrt -ldl -lm -lz /usr/local/lib/libzstd.a -lxml2
275+
// and we transform the zstd part into
276+
// cargo:rustc-link-search-native=/usr/local/lib
277+
// cargo:rustc-link-lib=static=zstd
278+
let path = Path::new(lib);
279+
if lib.ends_with(".a") {
280+
is_static = true;
281+
println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display());
282+
let name = path.file_stem().unwrap().to_str().unwrap();
283+
name.trim_start_matches("lib")
284+
} else {
285+
let name = path.file_name().unwrap().to_str().unwrap();
286+
name.trim_end_matches(".lib")
287+
}
271288
} else if lib.ends_with(".lib") {
272289
// Some MSVC libraries just come up with `.lib` tacked on, so chop
273290
// that off
@@ -285,7 +302,13 @@ fn main() {
285302
continue;
286303
}
287304

288-
let kind = if name.starts_with("LLVM") { llvm_kind } else { "dylib" };
305+
let kind = if name.starts_with("LLVM") {
306+
llvm_kind
307+
} else if is_static {
308+
"static"
309+
} else {
310+
"dylib"
311+
};
289312
println!("cargo:rustc-link-lib={kind}={name}");
290313
}
291314

config.example.toml

+8
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,11 @@
713713
# option will override this if set.
714714
#llvm-libunwind = 'no'
715715

716+
# Global default for llvm-libzstd for all targets. See the target-specific
717+
# documentation for llvm-libzstd below. Note that the target-specific
718+
# option will override this if set.
719+
#llvm-libzstd = false
720+
716721
# Enable Windows Control Flow Guard checks in the standard library.
717722
# This only applies from stage 1 onwards, and only for Windows targets.
718723
#control-flow-guard = false
@@ -816,6 +821,9 @@
816821
# it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
817822
#llvm-libunwind = 'no' if Linux, 'in-tree' if Fuchsia
818823

824+
# Enable LLVM to use zstd for compression.
825+
#llvm-libzstd = if linux { true } else { false }
826+
819827
# Build the sanitizer runtimes for this target.
820828
# This option will override the same option under [build] section.
821829
#sanitizers = build.sanitizers (bool)

src/bootstrap/download-ci-llvm-stamp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
Change this file to make users of the `download-ci-llvm` configuration download
22
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
33

4-
Last change is for: https://github.com/rust-lang/rust/pull/126298
4+
Last change is for: https://github.com/rust-lang/rust/pull/125642

src/bootstrap/src/core/build_steps/llvm.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -369,15 +369,6 @@ impl Step for Llvm {
369369
cfg.define("LLVM_PROFDATA_FILE", path);
370370
}
371371

372-
// Disable zstd to avoid a dependency on libzstd.so.
373-
cfg.define("LLVM_ENABLE_ZSTD", "OFF");
374-
375-
if !target.is_windows() {
376-
cfg.define("LLVM_ENABLE_ZLIB", "ON");
377-
} else {
378-
cfg.define("LLVM_ENABLE_ZLIB", "OFF");
379-
}
380-
381372
// Are we compiling for iOS/tvOS/watchOS/visionOS?
382373
if target.contains("apple-ios")
383374
|| target.contains("apple-tvos")
@@ -825,6 +816,18 @@ fn configure_llvm(builder: &Builder<'_>, target: TargetSelection, cfg: &mut cmak
825816
}
826817
}
827818

819+
// Libraries for ELF section compression.
820+
if !target.is_windows() {
821+
cfg.define("LLVM_ENABLE_ZLIB", "ON");
822+
} else {
823+
cfg.define("LLVM_ENABLE_ZLIB", "OFF");
824+
}
825+
826+
if builder.config.llvm_libzstd(target) {
827+
cfg.define("LLVM_ENABLE_ZSTD", "FORCE_ON");
828+
cfg.define("LLVM_USE_STATIC_ZSTD", "TRUE");
829+
}
830+
828831
if let Some(ref linker) = builder.config.llvm_use_linker {
829832
cfg.define("LLVM_USE_LINKER", linker);
830833
}

src/bootstrap/src/core/config/config.rs

+16
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ pub struct Config {
282282
pub llvm_profile_use: Option<String>,
283283
pub llvm_profile_generate: bool,
284284
pub llvm_libunwind_default: Option<LlvmLibunwind>,
285+
pub llvm_libzstd_default: Option<bool>,
285286
pub enable_bolt_settings: bool,
286287

287288
pub reproducible_artifacts: Vec<String>,
@@ -547,6 +548,7 @@ pub struct Target {
547548
/// Some(path to FileCheck) if one was specified.
548549
pub llvm_filecheck: Option<PathBuf>,
549550
pub llvm_libunwind: Option<LlvmLibunwind>,
551+
pub llvm_libzstd: Option<bool>,
550552
pub cc: Option<PathBuf>,
551553
pub cxx: Option<PathBuf>,
552554
pub ar: Option<PathBuf>,
@@ -1103,6 +1105,7 @@ define_config! {
11031105
jemalloc: Option<bool> = "jemalloc",
11041106
test_compare_mode: Option<bool> = "test-compare-mode",
11051107
llvm_libunwind: Option<String> = "llvm-libunwind",
1108+
llvm_libzstd: Option<bool> = "llvm-libzstd",
11061109
control_flow_guard: Option<bool> = "control-flow-guard",
11071110
ehcont_guard: Option<bool> = "ehcont-guard",
11081111
new_symbol_mangling: Option<bool> = "new-symbol-mangling",
@@ -1129,6 +1132,7 @@ define_config! {
11291132
llvm_has_rust_patches: Option<bool> = "llvm-has-rust-patches",
11301133
llvm_filecheck: Option<String> = "llvm-filecheck",
11311134
llvm_libunwind: Option<String> = "llvm-libunwind",
1135+
llvm_libzstd: Option<bool> = "llvm-libzstd",
11321136
sanitizers: Option<bool> = "sanitizers",
11331137
profiler: Option<StringOrBool> = "profiler",
11341138
rpath: Option<bool> = "rpath",
@@ -1630,6 +1634,7 @@ impl Config {
16301634
jemalloc,
16311635
test_compare_mode,
16321636
llvm_libunwind,
1637+
llvm_libzstd,
16331638
control_flow_guard,
16341639
ehcont_guard,
16351640
new_symbol_mangling,
@@ -1716,6 +1721,7 @@ impl Config {
17161721
set(&mut config.ehcont_guard, ehcont_guard);
17171722
config.llvm_libunwind_default =
17181723
llvm_libunwind.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
1724+
config.llvm_libzstd_default = llvm_libzstd;
17191725

17201726
if let Some(ref backends) = codegen_backends {
17211727
let available_backends = ["llvm", "cranelift", "gcc"];
@@ -1908,6 +1914,7 @@ impl Config {
19081914
panic!("failed to parse target.{triple}.llvm-libunwind")
19091915
})
19101916
});
1917+
target.llvm_libzstd = cfg.llvm_libzstd;
19111918
if let Some(s) = cfg.no_std {
19121919
target.no_std = s;
19131920
}
@@ -2394,6 +2401,14 @@ impl Config {
23942401
})
23952402
}
23962403

2404+
pub fn llvm_libzstd(&self, target: TargetSelection) -> bool {
2405+
self.target_config
2406+
.get(&target)
2407+
.and_then(|t| t.llvm_libzstd)
2408+
.or(self.llvm_libzstd_default)
2409+
.unwrap_or(target.contains("linux"))
2410+
}
2411+
23972412
pub fn split_debuginfo(&self, target: TargetSelection) -> SplitDebuginfo {
23982413
self.target_config
23992414
.get(&target)
@@ -2698,6 +2713,7 @@ fn check_incompatible_options_for_ci_rustc(rust: &Rust) -> Result<(), String> {
26982713
remap_debuginfo: _,
26992714
test_compare_mode: _,
27002715
llvm_libunwind: _,
2716+
llvm_libzstd: _,
27012717
control_flow_guard: _,
27022718
ehcont_guard: _,
27032719
new_symbol_mangling: _,

src/bootstrap/src/utils/change_tracker.rs

+5
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
220220
severity: ChangeSeverity::Warning,
221221
summary: "For tarball sources, default value for `rust.channel` will be taken from `src/ci/channel` file.",
222222
},
223+
ChangeInfo {
224+
change_id: 125642,
225+
severity: ChangeSeverity::Info,
226+
summary: "New option `llvm-libzstd` to control whether llvm is built with zstd support.",
227+
},
223228
];

src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ RUN sed -i /etc/yum.repos.d/*.repo -e 's!^mirrorlist!#mirrorlist!' \
1212
RUN sed -i 's/enabled=1/enabled=0/' /etc/yum/pluginconf.d/fastestmirror.conf
1313

1414
RUN yum upgrade -y && \
15+
yum install -y epel-release && \
1516
yum install -y \
1617
automake \
1718
bzip2 \
@@ -24,6 +25,7 @@ RUN yum upgrade -y && \
2425
libedit-devel \
2526
libstdc++-devel.i686 \
2627
libstdc++-devel.x86_64 \
28+
libzstd-devel.x86_64 \
2729
make \
2830
ncurses-devel \
2931
openssl-devel \

src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
1717
pkg-config \
1818
xz-utils \
1919
mingw-w64 \
20+
zlib1g-dev \
21+
libzstd-dev \
2022
&& rm -rf /var/lib/apt/lists/*
2123

2224
COPY scripts/sccache.sh /scripts/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Checks the `compress-debug-sections` option on rust-lld.
2+
3+
//@ needs-rust-lld
4+
//@ only-linux
5+
//@ ignore-cross-compile
6+
7+
// FIXME: This test isn't comprehensive and isn't covering all possible combinations.
8+
9+
use run_make_support::{assert_contains, cmd, llvm_readobj, run_in_tmpdir, rustc};
10+
11+
fn check_compression(compression: &str, to_find: &str) {
12+
run_in_tmpdir(|| {
13+
let out = rustc()
14+
.arg("-Zlinker-features=+lld")
15+
.arg("-Clink-self-contained=+linker")
16+
.arg("-Zunstable-options")
17+
.arg("-Cdebuginfo=full")
18+
.link_arg(&format!("-Wl,--compress-debug-sections={compression}"))
19+
.input("main.rs")
20+
.run_unchecked();
21+
let stderr = out.stderr_utf8();
22+
if stderr.is_empty() {
23+
llvm_readobj().arg("-t").arg("main").run().assert_stdout_contains(to_find);
24+
} else {
25+
assert_contains(
26+
stderr,
27+
format!(
28+
"LLVM was not built with LLVM_ENABLE_{to_find} \
29+
or did not find {compression} at build time"
30+
),
31+
);
32+
}
33+
});
34+
}
35+
36+
fn main() {
37+
check_compression("zlib", "ZLIB");
38+
check_compression("zstd", "ZSTD");
39+
}

0 commit comments

Comments
 (0)