Rollup merge of #139469 - jieyouxu:compiletest-supports-crate-type, r=onur-ozkan
Introduce a `//@ needs-crate-type` compiletest directive The `//@ needs-crate-type: $crate_types...` directive takes a comma-separated list of crate types that the target platform must support in order for the test to be run. This allows the test writer to semantically convey that the ignore condition is based on target crate type needs, instead of using a general purpose `//@ ignore-$target` directive (often without comment). Fixes #132309. ### Example ```rs //@ needs-crate-type: dylib (ignored on e.g. wasm32-unknown-unknown) //@ compile-flags: --crate-type=dylib fn foo() {} ``` ### Review advice - Best reviewed commit-by-commit. - The impl is not very clean, I briefly attempted to clean up the directive handling but found that more invasive changes are needed, so I'd like to not block on the cleanup for now. try-job: test-various try-job: armhf-gnu
This commit is contained in:
commit
ea1a31b150
16 changed files with 156 additions and 43 deletions
|
|
@ -395,6 +395,7 @@ pub struct Config {
|
|||
|
||||
pub target_cfgs: OnceLock<TargetCfgs>,
|
||||
pub builtin_cfg_names: OnceLock<HashSet<String>>,
|
||||
pub supported_crate_types: OnceLock<HashSet<String>>,
|
||||
|
||||
pub nocapture: bool,
|
||||
|
||||
|
|
@ -472,6 +473,11 @@ impl Config {
|
|||
self.builtin_cfg_names.get_or_init(|| builtin_cfg_names(self))
|
||||
}
|
||||
|
||||
/// Get the list of crate types that the target platform supports.
|
||||
pub fn supported_crate_types(&self) -> &HashSet<String> {
|
||||
self.supported_crate_types.get_or_init(|| supported_crate_types(self))
|
||||
}
|
||||
|
||||
pub fn has_threads(&self) -> bool {
|
||||
// Wasm targets don't have threads unless `-threads` is in the target
|
||||
// name, such as `wasm32-wasip1-threads`.
|
||||
|
|
@ -745,6 +751,31 @@ fn builtin_cfg_names(config: &Config) -> HashSet<String> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub const KNOWN_CRATE_TYPES: &[&str] =
|
||||
&["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"];
|
||||
|
||||
fn supported_crate_types(config: &Config) -> HashSet<String> {
|
||||
let crate_types: HashSet<_> = rustc_output(
|
||||
config,
|
||||
&["--target", &config.target, "--print=supported-crate-types", "-Zunstable-options"],
|
||||
Default::default(),
|
||||
)
|
||||
.lines()
|
||||
.map(|l| l.to_string())
|
||||
.collect();
|
||||
|
||||
for crate_type in crate_types.iter() {
|
||||
assert!(
|
||||
KNOWN_CRATE_TYPES.contains(&crate_type.as_str()),
|
||||
"unexpected crate type `{}`: known crate types are {:?}",
|
||||
crate_type,
|
||||
KNOWN_CRATE_TYPES
|
||||
);
|
||||
}
|
||||
|
||||
crate_types
|
||||
}
|
||||
|
||||
fn rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String {
|
||||
let mut command = Command::new(&config.rustc_path);
|
||||
add_dylib_path(&mut command, iter::once(&config.compile_lib_path));
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
|
|||
"min-llvm-version",
|
||||
"min-system-llvm-version",
|
||||
"needs-asm-support",
|
||||
"needs-crate-type",
|
||||
"needs-deterministic-layouts",
|
||||
"needs-dlltool",
|
||||
"needs-dynamic-linking",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::common::{Config, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
|
||||
use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
|
||||
use crate::header::{IgnoreDecision, llvm_has_libzstd};
|
||||
|
||||
pub(super) fn handle_needs(
|
||||
|
|
@ -6,7 +6,7 @@ pub(super) fn handle_needs(
|
|||
config: &Config,
|
||||
ln: &str,
|
||||
) -> IgnoreDecision {
|
||||
// Note thet we intentionally still put the needs- prefix here to make the file show up when
|
||||
// Note that we intentionally still put the needs- prefix here to make the file show up when
|
||||
// grepping for a directive name, even though we could technically strip that.
|
||||
let needs = &[
|
||||
Need {
|
||||
|
|
@ -224,6 +224,50 @@ pub(super) fn handle_needs(
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(jieyouxu): share multi-value directive logic with `needs-target-has-atomic` above.
|
||||
if name == "needs-crate-type" {
|
||||
let Some(rest) = rest else {
|
||||
return IgnoreDecision::Error {
|
||||
message:
|
||||
"expected `needs-crate-type` to have a comma-separated list of crate types"
|
||||
.to_string(),
|
||||
};
|
||||
};
|
||||
|
||||
// Expect directive value to be a list of comma-separated crate-types.
|
||||
let specified_crate_types = rest
|
||||
.split(',')
|
||||
.map(|crate_type| crate_type.trim())
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
for crate_type in &specified_crate_types {
|
||||
if !KNOWN_CRATE_TYPES.contains(&crate_type.as_str()) {
|
||||
return IgnoreDecision::Error {
|
||||
message: format!(
|
||||
"unknown crate type specified in `needs-crate-type`: `{crate_type}` is not \
|
||||
a known crate type, known values are `{:?}`",
|
||||
KNOWN_CRATE_TYPES
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let satisfies_all_crate_types = specified_crate_types
|
||||
.iter()
|
||||
.all(|specified| config.supported_crate_types().contains(specified));
|
||||
if satisfies_all_crate_types {
|
||||
return IgnoreDecision::Continue;
|
||||
} else {
|
||||
return IgnoreDecision::Ignore {
|
||||
reason: format!(
|
||||
"skipping test as target does not support all of the crate types `{:?}`",
|
||||
specified_crate_types
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if !name.starts_with("needs-") {
|
||||
return IgnoreDecision::Continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -902,3 +902,41 @@ fn test_rustc_abi() {
|
|||
assert!(!check_ignore(&config, "//@ ignore-rustc_abi-x86-sse2"));
|
||||
assert!(check_ignore(&config, "//@ only-rustc_abi-x86-sse2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_supported_crate_types() {
|
||||
// Basic assumptions check on under-test compiler's `--print=supported-crate-types` output based
|
||||
// on knowledge about the cherry-picked `x86_64-unknown-linux-gnu` and `wasm32-unknown-unknown`
|
||||
// targets. Also smoke tests the `needs-crate-type` directive itself.
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
let config = cfg().target("x86_64-unknown-linux-gnu").build();
|
||||
assert_eq!(
|
||||
config.supported_crate_types().iter().map(String::as_str).collect::<HashSet<_>>(),
|
||||
HashSet::from(["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"]),
|
||||
);
|
||||
assert!(!check_ignore(&config, "//@ needs-crate-type: rlib"));
|
||||
assert!(!check_ignore(&config, "//@ needs-crate-type: dylib"));
|
||||
assert!(!check_ignore(
|
||||
&config,
|
||||
"//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib"
|
||||
));
|
||||
|
||||
let config = cfg().target("wasm32-unknown-unknown").build();
|
||||
assert_eq!(
|
||||
config.supported_crate_types().iter().map(String::as_str).collect::<HashSet<_>>(),
|
||||
HashSet::from(["bin", "cdylib", "lib", "rlib", "staticlib"]),
|
||||
);
|
||||
|
||||
// rlib is supported
|
||||
assert!(!check_ignore(&config, "//@ needs-crate-type: rlib"));
|
||||
// dylib is not
|
||||
assert!(check_ignore(&config, "//@ needs-crate-type: dylib"));
|
||||
// If multiple crate types are specified, then all specified crate types need to be supported.
|
||||
assert!(check_ignore(&config, "//@ needs-crate-type: cdylib, dylib"));
|
||||
assert!(check_ignore(
|
||||
&config,
|
||||
"//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib"
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -431,6 +431,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
|
||||
target_cfgs: OnceLock::new(),
|
||||
builtin_cfg_names: OnceLock::new(),
|
||||
supported_crate_types: OnceLock::new(),
|
||||
|
||||
nocapture: matches.opt_present("no-capture"),
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue