Skip to content

Commit 8e46521

Browse files
authored
Rollup merge of #149666 - Zalathar:backend-has-zstd, r=jieyouxu
Add perma-unstable `--print=backend-has-zstd` for use by compiletest Tests for `-Zdebuginfo-compression=zstd` need to be skipped if LLVM was built without support for zstd compression. Currently, compiletest relies on messy and fragile heuristics to detect whether the compiler's LLVM was built with zstd support. But the compiler itself already knows whether LLVM has zstd or not, so it's easier for compiletest to just ask the compiler. --- Originally I was intending for this to be a `--print=debuginfo-compression` flag that would print out a list of values supported by `-Zdebuginfo-compression=`. I got that working locally, but it was more complex than I was happy with (in both rustc and compiletest), so I decided to cut scope and instead add a very narrow perma-unstable print request instead. There is always a circularity hazard whenever we ask the compiler-under-test for information about how to test it. But in this case, the underlying compiler code is fairly simple, whereas the previous heuristics were inherently messy and unreliable anyway.
2 parents 9324982 + 84ff44c commit 8e46521

File tree

15 files changed

+50
-112
lines changed

15 files changed

+50
-112
lines changed

compiler/rustc_codegen_llvm/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@ impl CodegenBackend for LlvmCodegenBackend {
257257
}
258258
writeln!(out).unwrap();
259259
}
260+
PrintKind::BackendHasZstd => {
261+
let has_zstd = llvm::LLVMRustLLVMHasZstdCompression();
262+
writeln!(out, "{has_zstd}").unwrap();
263+
}
260264
PrintKind::CodeModels => {
261265
writeln!(out, "Available code models:").unwrap();
262266
for name in &["tiny", "small", "kernel", "medium", "large"] {

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ fn print_crate_info(
799799
println_info!("{}", calling_conventions.join("\n"));
800800
}
801801
RelocationModels
802+
| BackendHasZstd
802803
| CodeModels
803804
| TlsModels
804805
| TargetCPUs

compiler/rustc_session/src/config/print_request.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub struct PrintRequest {
2222
pub enum PrintKind {
2323
// tidy-alphabetical-start
2424
AllTargetSpecsJson,
25+
BackendHasZstd,
2526
CallingConventions,
2627
Cfg,
2728
CheckCfg,
@@ -59,6 +60,7 @@ impl PrintKind {
5960
match self {
6061
// tidy-alphabetical-start
6162
AllTargetSpecsJson => "all-target-specs-json",
63+
BackendHasZstd => "backend-has-zstd",
6264
CallingConventions => "calling-conventions",
6365
Cfg => "cfg",
6466
CheckCfg => "check-cfg",
@@ -111,6 +113,7 @@ impl PrintKind {
111113

112114
// Unstable values:
113115
AllTargetSpecsJson => false,
116+
BackendHasZstd => false, // (perma-unstable, for use by compiletest)
114117
CheckCfg => false,
115118
CrateRootLintLevels => false,
116119
SupportedCrateTypes => false,

src/tools/compiletest/src/common.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,11 @@ fn supported_crate_types(config: &Config) -> HashSet<String> {
10961096
crate_types
10971097
}
10981098

1099-
fn query_rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String {
1099+
pub(crate) fn query_rustc_output(
1100+
config: &Config,
1101+
args: &[&str],
1102+
envs: HashMap<String, String>,
1103+
) -> String {
11001104
let query_rustc_path = config.query_rustc_path.as_deref().unwrap_or(&config.rustc_path);
11011105

11021106
let mut command = Command::new(query_rustc_path);

src/tools/compiletest/src/directives.rs

Lines changed: 0 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -885,107 +885,6 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<Version> {
885885
None
886886
}
887887

888-
/// For tests using the `needs-llvm-zstd` directive:
889-
/// - for local LLVM builds, try to find the static zstd library in the llvm-config system libs.
890-
/// - for `download-ci-llvm`, see if `lld` was built with zstd support.
891-
pub fn llvm_has_libzstd(config: &Config) -> bool {
892-
// Strategy 1: works for local builds but not with `download-ci-llvm`.
893-
//
894-
// We check whether `llvm-config` returns the zstd library. Bootstrap's `llvm.libzstd` will only
895-
// ask to statically link it when building LLVM, so we only check if the list of system libs
896-
// contains a path to that static lib, and that it exists.
897-
//
898-
// See compiler/rustc_llvm/build.rs for more details and similar expectations.
899-
fn is_zstd_in_config(llvm_bin_dir: &Utf8Path) -> Option<()> {
900-
let llvm_config_path = llvm_bin_dir.join("llvm-config");
901-
let output = Command::new(llvm_config_path).arg("--system-libs").output().ok()?;
902-
assert!(output.status.success(), "running llvm-config --system-libs failed");
903-
904-
let libs = String::from_utf8(output.stdout).ok()?;
905-
for lib in libs.split_whitespace() {
906-
if lib.ends_with("libzstd.a") && Utf8Path::new(lib).exists() {
907-
return Some(());
908-
}
909-
}
910-
911-
None
912-
}
913-
914-
// Strategy 2: `download-ci-llvm`'s `llvm-config --system-libs` will not return any libs to
915-
// use.
916-
//
917-
// The CI artifacts also don't contain the bootstrap config used to build them: otherwise we
918-
// could have looked at the `llvm.libzstd` config.
919-
//
920-
// We infer whether `LLVM_ENABLE_ZSTD` was used to build LLVM as a byproduct of testing whether
921-
// `lld` supports it. If not, an error will be emitted: "LLVM was not built with
922-
// LLVM_ENABLE_ZSTD or did not find zstd at build time".
923-
#[cfg(unix)]
924-
fn is_lld_built_with_zstd(llvm_bin_dir: &Utf8Path) -> Option<()> {
925-
let lld_path = llvm_bin_dir.join("lld");
926-
if lld_path.exists() {
927-
// We can't call `lld` as-is, it expects to be invoked by a compiler driver using a
928-
// different name. Prepare a temporary symlink to do that.
929-
let lld_symlink_path = llvm_bin_dir.join("ld.lld");
930-
if !lld_symlink_path.exists() {
931-
std::os::unix::fs::symlink(lld_path, &lld_symlink_path).ok()?;
932-
}
933-
934-
// Run `lld` with a zstd flag. We expect this command to always error here, we don't
935-
// want to link actual files and don't pass any.
936-
let output = Command::new(&lld_symlink_path)
937-
.arg("--compress-debug-sections=zstd")
938-
.output()
939-
.ok()?;
940-
assert!(!output.status.success());
941-
942-
// Look for a specific error caused by LLVM not being built with zstd support. We could
943-
// also look for the "no input files" message, indicating the zstd flag was accepted.
944-
let stderr = String::from_utf8(output.stderr).ok()?;
945-
let zstd_available = !stderr.contains("LLVM was not built with LLVM_ENABLE_ZSTD");
946-
947-
// We don't particularly need to clean the link up (so the previous commands could fail
948-
// in theory but won't in practice), but we can try.
949-
std::fs::remove_file(lld_symlink_path).ok()?;
950-
951-
if zstd_available {
952-
return Some(());
953-
}
954-
}
955-
956-
None
957-
}
958-
959-
#[cfg(not(unix))]
960-
fn is_lld_built_with_zstd(_llvm_bin_dir: &Utf8Path) -> Option<()> {
961-
None
962-
}
963-
964-
if let Some(llvm_bin_dir) = &config.llvm_bin_dir {
965-
// Strategy 1: for local LLVM builds.
966-
if is_zstd_in_config(llvm_bin_dir).is_some() {
967-
return true;
968-
}
969-
970-
// Strategy 2: for LLVM artifacts built on CI via `download-ci-llvm`.
971-
//
972-
// It doesn't work for cases where the artifacts don't contain the linker, but it's
973-
// best-effort: CI has `llvm.libzstd` and `lld` enabled on the x64 linux artifacts, so it
974-
// will at least work there.
975-
//
976-
// If this can be improved and expanded to less common cases in the future, it should.
977-
if config.target == "x86_64-unknown-linux-gnu"
978-
&& config.host == config.target
979-
&& is_lld_built_with_zstd(llvm_bin_dir).is_some()
980-
{
981-
return true;
982-
}
983-
}
984-
985-
// Otherwise, all hope is lost.
986-
false
987-
}
988-
989888
/// Takes a directive of the form `"<version1> [- <version2>]"`, returns the numeric representation
990889
/// of `<version1>` and `<version2>` as tuple: `(<version1>, <version2>)`.
991890
///

src/tools/compiletest/src/directives/needs.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
2-
use crate::directives::{DirectiveLine, IgnoreDecision, llvm_has_libzstd};
1+
use crate::common::{
2+
Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer, query_rustc_output,
3+
};
4+
use crate::directives::{DirectiveLine, IgnoreDecision};
35

46
pub(super) fn handle_needs(
57
cache: &CachedNeedsConditions,
@@ -377,7 +379,7 @@ impl CachedNeedsConditions {
377379
.join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" })
378380
.exists(),
379381

380-
llvm_zstd: llvm_has_libzstd(&config),
382+
llvm_zstd: llvm_has_zstd(&config),
381383
dlltool: find_dlltool(&config),
382384
symlinks: has_symlinks(),
383385
}
@@ -428,3 +430,18 @@ fn has_symlinks() -> bool {
428430
fn has_symlinks() -> bool {
429431
true
430432
}
433+
434+
fn llvm_has_zstd(config: &Config) -> bool {
435+
// The compiler already knows whether LLVM was built with zstd or not,
436+
// so compiletest can just ask the compiler.
437+
let output = query_rustc_output(
438+
config,
439+
&["-Zunstable-options", "--print=backend-has-zstd"],
440+
Default::default(),
441+
);
442+
match output.trim() {
443+
"true" => true,
444+
"false" => false,
445+
_ => panic!("unexpected output from `--print=backend-has-zstd`: {output:?}"),
446+
}
447+
}

tests/run-make/print-request-help-stable-unstable/help-diff.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
error: unknown print request: `xxx`
33
|
44
- = help: valid print requests are: `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `tls-models`
5-
+ = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
5+
+ = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
66
= help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
77

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unknown print request: `xxx`
22
|
3-
= help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
3+
= help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
44
= help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
55

tests/run-make/rustc-help/help-v.stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Options:
4343
--print <INFO>[=<FILE>]
4444
Compiler information to print on stdout (or to a file)
4545
INFO may be one of
46-
<all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|target-spec-json-schema|tls-models>.
46+
<all-target-specs-json|backend-has-zstd|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|target-spec-json-schema|tls-models>.
4747
-g Equivalent to -C debuginfo=2
4848
-O Equivalent to -C opt-level=3
4949
-o <FILENAME> Write output to FILENAME

tests/run-make/rustc-help/help.stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Options:
4343
--print <INFO>[=<FILE>]
4444
Compiler information to print on stdout (or to a file)
4545
INFO may be one of
46-
<all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|target-spec-json-schema|tls-models>.
46+
<all-target-specs-json|backend-has-zstd|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|target-spec-json-schema|tls-models>.
4747
-g Equivalent to -C debuginfo=2
4848
-O Equivalent to -C opt-level=3
4949
-o <FILENAME> Write output to FILENAME

0 commit comments

Comments
 (0)