Rollup merge of #151353 - Enselic:aux-crate-opts, r=Zalathar

compiletest: Make `aux-crate` directive explicitly handle `--extern` modifiers

With `-Zunstable-options` it is possible to pass options to `--extern`. See here for an exhaustive list of possible options:
b5dd72d292/compiler/rustc_session/src/config.rs (L2356-L2367)

Using these options works with the `aux-crate` directive, but only because the options pretend to be part of the name. Make it clearer what `aux-crate` supports by explicitly handling `--extern` options.

This PR is step one of splitting up https://github.com/rust-lang/rust/pull/151258 into smaller pieces.

r? @Zalathar
This commit is contained in:
Matthias Krüger 2026-01-24 21:04:15 +01:00 committed by GitHub
commit 0a1b437760
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 87 additions and 26 deletions

View file

@ -665,7 +665,9 @@ to link to the extern crate to make the crate be available as an extern prelude.
That allows you to specify the additional syntax of the `--extern` flag, such as
renaming a dependency. For example, `//@ aux-crate:foo=bar.rs` will compile
`auxiliary/bar.rs` and make it available under then name `foo` within the test.
This is similar to how Cargo does dependency renaming.
This is similar to how Cargo does dependency renaming. It is also possible to
specify [`--extern` modifiers](https://github.com/rust-lang/rust/issues/98405).
For example, `//@ aux-crate:noprelude:foo=bar.rs`.
`aux-bin` is similar to `aux-build` but will build a binary instead of a
library. The binary will be available in `auxiliary/bin` relative to the working

View file

@ -53,14 +53,14 @@ Directives can generally be found by browsing the
See [Building auxiliary crates](compiletest.html#building-auxiliary-crates)
| Directive | Explanation | Supported test suites | Possible values |
|-----------------------|-------------------------------------------------------------------------------------------------------|----------------------------------------|-----------------------------------------------|
| `aux-bin` | Build a aux binary, made available in `auxiliary/bin` relative to test directory | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file |
| `aux-build` | Build a separate crate from the named source file | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file |
| `aux-crate` | Like `aux-build` but makes available as extern prelude | All except `run-make`/`run-make-cargo` | `<extern_prelude_name>=<path/to/aux/file.rs>` |
| `aux-codegen-backend` | Similar to `aux-build` but pass the compiled dylib to `-Zcodegen-backend` when building the main file | `ui-fulldeps` | Path to codegen backend file |
| `proc-macro` | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm]. | All except `run-make`/`run-make-cargo` | Path to auxiliary proc-macro `.rs` file |
| `build-aux-docs` | Build docs for auxiliaries as well. Note that this only works with `aux-build`, not `aux-crate`. | All except `run-make`/`run-make-cargo` | N/A |
| Directive | Explanation | Supported test suites | Possible values |
|-----------------------|-------------------------------------------------------------------------------------------------------|----------------------------------------|--------------------------------------------------------------------|
| `aux-bin` | Build a aux binary, made available in `auxiliary/bin` relative to test directory | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file |
| `aux-build` | Build a separate crate from the named source file | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file |
| `aux-crate` | Like `aux-build` but makes available as extern prelude | All except `run-make`/`run-make-cargo` | `[<extern_modifiers>:]<extern_prelude_name>=<path/to/aux/file.rs>` |
| `aux-codegen-backend` | Similar to `aux-build` but pass the compiled dylib to `-Zcodegen-backend` when building the main file | `ui-fulldeps` | Path to codegen backend file |
| `proc-macro` | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm]. | All except `run-make`/`run-make-cargo` | Path to auxiliary proc-macro `.rs` file |
| `build-aux-docs` | Build docs for auxiliaries as well. Note that this only works with `aux-build`, not `aux-crate`. | All except `run-make`/`run-make-cargo` | N/A |
[^pm]: please see the [Auxiliary proc-macro section](compiletest.html#auxiliary-proc-macro) in the compiletest chapter for specifics.

View file

@ -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: <https://github.com/rust-lang/rust/issues/98405>
/// With `aux-crate: noprelude:foo=bar.rs` this will be `noprelude`.
pub extern_modifiers: Option<String>,
/// 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"^(?:(?<modifiers>[^=]*?):)?(?<name>[^=]*)=(?<path>.*)$")
.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 }
}

View file

@ -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());
}

View file

@ -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