diff --git a/src/tools/compiletest/src/directives/auxiliary.rs b/src/tools/compiletest/src/directives/auxiliary.rs index 1b72931949c5..1d5b7926a8e3 100644 --- a/src/tools/compiletest/src/directives/auxiliary.rs +++ b/src/tools/compiletest/src/directives/auxiliary.rs @@ -6,12 +6,20 @@ use std::iter; use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO}; use crate::common::Config; use crate::directives::DirectiveLine; +use crate::util::static_regex; + +#[cfg(test)] +mod tests; /// The value of an `aux-crate` directive. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct AuxCrate { + /// Contains `--extern` modifiers, if any. See the tracking issue for more + /// info: + /// With `aux-crate: noprelude:foo=bar.rs` this will be `noprelude`. + pub extern_modifiers: Option, /// With `aux-crate: foo=bar.rs` this will be `foo`. - /// With `aux-crate: noprelude:foo=bar.rs` this will be `noprelude:foo`. + /// With `aux-crate: noprelude:foo=bar.rs` this will be `foo`. pub name: String, /// With `aux-crate: foo=bar.rs` this will be `bar.rs`. pub path: String, @@ -74,9 +82,20 @@ pub(super) fn parse_and_update_aux( } fn parse_aux_crate(r: String) -> AuxCrate { - let mut parts = r.trim().splitn(2, '='); - AuxCrate { - name: parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(), - path: parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(), - } + let r = r.trim(); + + // Matches: + // name=path + // modifiers:name=path + let caps = static_regex!(r"^(?:(?[^=]*?):)?(?[^=]*)=(?.*)$") + .captures(r) + .unwrap_or_else(|| { + panic!("couldn't parse aux-crate value `{r}` (should be e.g. `log=log.rs`)") + }); + + let modifiers = caps.name("modifiers").map(|m| m.as_str().to_string()); + let name = caps["name"].to_string(); + let path = caps["path"].to_string(); + + AuxCrate { extern_modifiers: modifiers, name, path } } diff --git a/src/tools/compiletest/src/directives/auxiliary/tests.rs b/src/tools/compiletest/src/directives/auxiliary/tests.rs new file mode 100644 index 000000000000..ad205eaabfda --- /dev/null +++ b/src/tools/compiletest/src/directives/auxiliary/tests.rs @@ -0,0 +1,27 @@ +use super::*; + +#[test] +fn test_aux_crate_value_no_modifiers() { + assert_eq!( + AuxCrate { extern_modifiers: None, name: "foo".to_string(), path: "foo.rs".to_string() }, + parse_aux_crate("foo=foo.rs".to_string()) + ); +} + +#[test] +fn test_aux_crate_value_with_modifiers() { + assert_eq!( + AuxCrate { + extern_modifiers: Some("noprelude".to_string()), + name: "foo".to_string(), + path: "foo.rs".to_string() + }, + parse_aux_crate("noprelude:foo=foo.rs".to_string()) + ); +} + +#[test] +#[should_panic(expected = "couldn't parse aux-crate value `foo.rs` (should be e.g. `log=log.rs`)")] +fn test_aux_crate_value_invalid() { + parse_aux_crate("foo.rs".to_string()); +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 901ce8421ebf..dfbe84d5da72 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1277,23 +1277,36 @@ impl<'test> TestCx<'test> { .replace('-', "_") }; - let add_extern = - |rustc: &mut Command, aux_name: &str, aux_path: &str, aux_type: AuxType| { - let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type); - if let Some(lib_name) = lib_name { - rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir, lib_name)); - } - }; + let add_extern = |rustc: &mut Command, + extern_modifiers: Option<&str>, + aux_name: &str, + aux_path: &str, + aux_type: AuxType| { + let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type); + if let Some(lib_name) = lib_name { + let modifiers_and_name = match extern_modifiers { + Some(modifiers) => format!("{modifiers}:{aux_name}"), + None => aux_name.to_string(), + }; + rustc.arg("--extern").arg(format!("{modifiers_and_name}={aux_dir}/{lib_name}")); + } + }; - for AuxCrate { name, path } in &self.props.aux.crates { + for AuxCrate { extern_modifiers, name, path } in &self.props.aux.crates { let aux_type = self.build_auxiliary(&path, &aux_dir, None); - add_extern(rustc, name, path, aux_type); + add_extern(rustc, extern_modifiers.as_deref(), name, path, aux_type); } for proc_macro in &self.props.aux.proc_macros { self.build_auxiliary(proc_macro, &aux_dir, Some(AuxType::ProcMacro)); let crate_name = path_to_crate_name(proc_macro); - add_extern(rustc, &crate_name, proc_macro, AuxType::ProcMacro); + add_extern( + rustc, + None, // `extern_modifiers` + &crate_name, + proc_macro, + AuxType::ProcMacro, + ); } // Build any `//@ aux-codegen-backend`, and pass the resulting library