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.
This commit is contained in:
commit
8e46521d0e
15 changed files with 50 additions and 112 deletions
|
|
@ -257,6 +257,10 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
}
|
||||
writeln!(out).unwrap();
|
||||
}
|
||||
PrintKind::BackendHasZstd => {
|
||||
let has_zstd = llvm::LLVMRustLLVMHasZstdCompression();
|
||||
writeln!(out, "{has_zstd}").unwrap();
|
||||
}
|
||||
PrintKind::CodeModels => {
|
||||
writeln!(out, "Available code models:").unwrap();
|
||||
for name in &["tiny", "small", "kernel", "medium", "large"] {
|
||||
|
|
|
|||
|
|
@ -799,6 +799,7 @@ fn print_crate_info(
|
|||
println_info!("{}", calling_conventions.join("\n"));
|
||||
}
|
||||
RelocationModels
|
||||
| BackendHasZstd
|
||||
| CodeModels
|
||||
| TlsModels
|
||||
| TargetCPUs
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ pub struct PrintRequest {
|
|||
pub enum PrintKind {
|
||||
// tidy-alphabetical-start
|
||||
AllTargetSpecsJson,
|
||||
BackendHasZstd,
|
||||
CallingConventions,
|
||||
Cfg,
|
||||
CheckCfg,
|
||||
|
|
@ -59,6 +60,7 @@ impl PrintKind {
|
|||
match self {
|
||||
// tidy-alphabetical-start
|
||||
AllTargetSpecsJson => "all-target-specs-json",
|
||||
BackendHasZstd => "backend-has-zstd",
|
||||
CallingConventions => "calling-conventions",
|
||||
Cfg => "cfg",
|
||||
CheckCfg => "check-cfg",
|
||||
|
|
@ -111,6 +113,7 @@ impl PrintKind {
|
|||
|
||||
// Unstable values:
|
||||
AllTargetSpecsJson => false,
|
||||
BackendHasZstd => false, // (perma-unstable, for use by compiletest)
|
||||
CheckCfg => false,
|
||||
CrateRootLintLevels => false,
|
||||
SupportedCrateTypes => false,
|
||||
|
|
|
|||
|
|
@ -1096,7 +1096,11 @@ fn supported_crate_types(config: &Config) -> HashSet<String> {
|
|||
crate_types
|
||||
}
|
||||
|
||||
fn query_rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String {
|
||||
pub(crate) fn query_rustc_output(
|
||||
config: &Config,
|
||||
args: &[&str],
|
||||
envs: HashMap<String, String>,
|
||||
) -> String {
|
||||
let query_rustc_path = config.query_rustc_path.as_deref().unwrap_or(&config.rustc_path);
|
||||
|
||||
let mut command = Command::new(query_rustc_path);
|
||||
|
|
|
|||
|
|
@ -885,107 +885,6 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<Version> {
|
|||
None
|
||||
}
|
||||
|
||||
/// For tests using the `needs-llvm-zstd` directive:
|
||||
/// - for local LLVM builds, try to find the static zstd library in the llvm-config system libs.
|
||||
/// - for `download-ci-llvm`, see if `lld` was built with zstd support.
|
||||
pub fn llvm_has_libzstd(config: &Config) -> bool {
|
||||
// Strategy 1: works for local builds but not with `download-ci-llvm`.
|
||||
//
|
||||
// We check whether `llvm-config` returns the zstd library. Bootstrap's `llvm.libzstd` will only
|
||||
// ask to statically link it when building LLVM, so we only check if the list of system libs
|
||||
// contains a path to that static lib, and that it exists.
|
||||
//
|
||||
// See compiler/rustc_llvm/build.rs for more details and similar expectations.
|
||||
fn is_zstd_in_config(llvm_bin_dir: &Utf8Path) -> Option<()> {
|
||||
let llvm_config_path = llvm_bin_dir.join("llvm-config");
|
||||
let output = Command::new(llvm_config_path).arg("--system-libs").output().ok()?;
|
||||
assert!(output.status.success(), "running llvm-config --system-libs failed");
|
||||
|
||||
let libs = String::from_utf8(output.stdout).ok()?;
|
||||
for lib in libs.split_whitespace() {
|
||||
if lib.ends_with("libzstd.a") && Utf8Path::new(lib).exists() {
|
||||
return Some(());
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
// Strategy 2: `download-ci-llvm`'s `llvm-config --system-libs` will not return any libs to
|
||||
// use.
|
||||
//
|
||||
// The CI artifacts also don't contain the bootstrap config used to build them: otherwise we
|
||||
// could have looked at the `llvm.libzstd` config.
|
||||
//
|
||||
// We infer whether `LLVM_ENABLE_ZSTD` was used to build LLVM as a byproduct of testing whether
|
||||
// `lld` supports it. If not, an error will be emitted: "LLVM was not built with
|
||||
// LLVM_ENABLE_ZSTD or did not find zstd at build time".
|
||||
#[cfg(unix)]
|
||||
fn is_lld_built_with_zstd(llvm_bin_dir: &Utf8Path) -> Option<()> {
|
||||
let lld_path = llvm_bin_dir.join("lld");
|
||||
if lld_path.exists() {
|
||||
// We can't call `lld` as-is, it expects to be invoked by a compiler driver using a
|
||||
// different name. Prepare a temporary symlink to do that.
|
||||
let lld_symlink_path = llvm_bin_dir.join("ld.lld");
|
||||
if !lld_symlink_path.exists() {
|
||||
std::os::unix::fs::symlink(lld_path, &lld_symlink_path).ok()?;
|
||||
}
|
||||
|
||||
// Run `lld` with a zstd flag. We expect this command to always error here, we don't
|
||||
// want to link actual files and don't pass any.
|
||||
let output = Command::new(&lld_symlink_path)
|
||||
.arg("--compress-debug-sections=zstd")
|
||||
.output()
|
||||
.ok()?;
|
||||
assert!(!output.status.success());
|
||||
|
||||
// Look for a specific error caused by LLVM not being built with zstd support. We could
|
||||
// also look for the "no input files" message, indicating the zstd flag was accepted.
|
||||
let stderr = String::from_utf8(output.stderr).ok()?;
|
||||
let zstd_available = !stderr.contains("LLVM was not built with LLVM_ENABLE_ZSTD");
|
||||
|
||||
// We don't particularly need to clean the link up (so the previous commands could fail
|
||||
// in theory but won't in practice), but we can try.
|
||||
std::fs::remove_file(lld_symlink_path).ok()?;
|
||||
|
||||
if zstd_available {
|
||||
return Some(());
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn is_lld_built_with_zstd(_llvm_bin_dir: &Utf8Path) -> Option<()> {
|
||||
None
|
||||
}
|
||||
|
||||
if let Some(llvm_bin_dir) = &config.llvm_bin_dir {
|
||||
// Strategy 1: for local LLVM builds.
|
||||
if is_zstd_in_config(llvm_bin_dir).is_some() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Strategy 2: for LLVM artifacts built on CI via `download-ci-llvm`.
|
||||
//
|
||||
// It doesn't work for cases where the artifacts don't contain the linker, but it's
|
||||
// best-effort: CI has `llvm.libzstd` and `lld` enabled on the x64 linux artifacts, so it
|
||||
// will at least work there.
|
||||
//
|
||||
// If this can be improved and expanded to less common cases in the future, it should.
|
||||
if config.target == "x86_64-unknown-linux-gnu"
|
||||
&& config.host == config.target
|
||||
&& is_lld_built_with_zstd(llvm_bin_dir).is_some()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, all hope is lost.
|
||||
false
|
||||
}
|
||||
|
||||
/// Takes a directive of the form `"<version1> [- <version2>]"`, returns the numeric representation
|
||||
/// of `<version1>` and `<version2>` as tuple: `(<version1>, <version2>)`.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
|
||||
use crate::directives::{DirectiveLine, IgnoreDecision, llvm_has_libzstd};
|
||||
use crate::common::{
|
||||
Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer, query_rustc_output,
|
||||
};
|
||||
use crate::directives::{DirectiveLine, IgnoreDecision};
|
||||
|
||||
pub(super) fn handle_needs(
|
||||
cache: &CachedNeedsConditions,
|
||||
|
|
@ -377,7 +379,7 @@ impl CachedNeedsConditions {
|
|||
.join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" })
|
||||
.exists(),
|
||||
|
||||
llvm_zstd: llvm_has_libzstd(&config),
|
||||
llvm_zstd: llvm_has_zstd(&config),
|
||||
dlltool: find_dlltool(&config),
|
||||
symlinks: has_symlinks(),
|
||||
}
|
||||
|
|
@ -428,3 +430,18 @@ fn has_symlinks() -> bool {
|
|||
fn has_symlinks() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn llvm_has_zstd(config: &Config) -> bool {
|
||||
// The compiler already knows whether LLVM was built with zstd or not,
|
||||
// so compiletest can just ask the compiler.
|
||||
let output = query_rustc_output(
|
||||
config,
|
||||
&["-Zunstable-options", "--print=backend-has-zstd"],
|
||||
Default::default(),
|
||||
);
|
||||
match output.trim() {
|
||||
"true" => true,
|
||||
"false" => false,
|
||||
_ => panic!("unexpected output from `--print=backend-has-zstd`: {output:?}"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
error: unknown print request: `xxx`
|
||||
|
|
||||
- = 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`
|
||||
+ = 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`
|
||||
+ = 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`
|
||||
= help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: unknown print request: `xxx`
|
||||
|
|
||||
= 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`
|
||||
= 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`
|
||||
= help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ Options:
|
|||
--print <INFO>[=<FILE>]
|
||||
Compiler information to print on stdout (or to a file)
|
||||
INFO may be one of
|
||||
<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>.
|
||||
<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>.
|
||||
-g Equivalent to -C debuginfo=2
|
||||
-O Equivalent to -C opt-level=3
|
||||
-o <FILENAME> Write output to FILENAME
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ Options:
|
|||
--print <INFO>[=<FILE>]
|
||||
Compiler information to print on stdout (or to a file)
|
||||
INFO may be one of
|
||||
<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>.
|
||||
<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>.
|
||||
-g Equivalent to -C debuginfo=2
|
||||
-O Equivalent to -C opt-level=3
|
||||
-o <FILENAME> Write output to FILENAME
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ error: Argument to option 'print' missing
|
|||
--print <INFO>[=<FILE>]
|
||||
Compiler information to print on stdout (or to a file)
|
||||
INFO may be one of
|
||||
<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>.
|
||||
<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>.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: unknown print request: `yyyy`
|
||||
|
|
||||
= 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`
|
||||
= 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`
|
||||
= help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
|
||||
|
||||
|
|
|
|||
8
tests/ui/print-request/backend-has-zstd-unstable.rs
Normal file
8
tests/ui/print-request/backend-has-zstd-unstable.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//! Check that `--print=backend-has-zstd` is unstable.
|
||||
//!
|
||||
//! That print value is intended for use by compiletest, and should probably
|
||||
//! never be stabilized in this form.
|
||||
|
||||
//@ compile-flags: --print=backend-has-zstd
|
||||
|
||||
//~? ERROR: the `-Z unstable-options` flag must also be passed
|
||||
2
tests/ui/print-request/backend-has-zstd-unstable.stderr
Normal file
2
tests/ui/print-request/backend-has-zstd-unstable.stderr
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
error: the `-Z unstable-options` flag must also be passed to enable the `backend-has-zstd` print option
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
error: unknown print request: `lints`
|
||||
|
|
||||
= 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`
|
||||
= 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`
|
||||
= help: use `-Whelp` to print a list of lints
|
||||
= help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue