Skip to content

Commit 01b2fff

Browse files
committed
Auto merge of rust-lang#130693 - jieyouxu:minicore, r=<try>
[PROTOTYPE] Add minicore test auxiliary and support `//@ use-minicore` directive in ui/assembly/codegen tests **TODO: work in progress prototype implementation, opened early for MCP to reference** Context: [Real cross-compiling tests instead of `#![no_core]` silliness rust-lang#130375](rust-lang#130375) This PR introduces a prototype implementation of `minicore` auxiliary test helper. `minicore` contains stub definitions of std/core prelude items intended for consumption by tests that want the typical prelude items like `Copy` or `Result` in cross-compilation scenarios, but don't want nor need full `-Z build-std` (e.g. `tests/ui/abi/compatibility.rs`). The `minicore` auxiliary is a single source file `tests/auxiliary/minicore.rs`. The path to this auxiliary is made avaiable from bootstrap to compiletest via the `--minicore-path` compiletest flag. The `minicore` auxiliary is then built, on demand via `//@ use-minicore` compiletest directives, for each test revision for the given target (this distinction is important for when host != target in cross-compilation scenario). ### Implementation steps - [ ] 1. File an MCP to describe `tests/auxiliary/minicore.rs`, `--minicore-path` compiletest flag, `//@ use-minicore` compiletest directive and the behavior. - [ ] 2. And some self-tests to sanity check the behavior. - [ ] 3. Update rustc-dev-guide to describe the new `use-minicore` directive and provide an example, noting that `use-minicore` both requires `no_std` + `no_core` and implies `-C panic=abort` for the test file. r? `@ghost` (not yet ready for full review, still needs some self-tests and some try-jobs) (TODO: cc interested people once this passes initial try jobs in cross-compilation scenarios) cc `@/workingjubilee` `@/RalfJung` `@/nikic` `@/chrisnc` (if this makes sense to you in terms of functionality and UX) try-job: aarch64-apple try-job: armhf-gnu try-job: x86_64-msvc try-job: test-various try-job: dist-various-1
2 parents 1f9a018 + 9d6f01a commit 01b2fff

File tree

10 files changed

+242
-162
lines changed

10 files changed

+242
-162
lines changed

src/bootstrap/src/core/build_steps/test.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
17311731
cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target));
17321732
cmd.arg("--rustc-path").arg(builder.rustc(compiler));
17331733

1734+
// Minicore auxiliary lib for tests that need std/core stubs in cross-compilation scenarios.
1735+
cmd.arg("--minicore-path").arg("tests/auxiliary/minicore.rs");
1736+
17341737
let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js");
17351738

17361739
if mode == "run-make" {

src/tools/compiletest/src/command-list.rs

+1
Original file line numberDiff line numberDiff line change
@@ -240,5 +240,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
240240
"unset-rustc-env",
241241
// Used by the tidy check `unknown_revision`.
242242
"unused-revision-names",
243+
"use-minicore",
243244
// tidy-alphabetical-end
244245
];

src/tools/compiletest/src/common.rs

+5
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,11 @@ pub struct Config {
392392
/// True if the profiler runtime is enabled for this target.
393393
/// Used by the "needs-profiler-support" header in test files.
394394
pub profiler_support: bool,
395+
396+
/// Path to minicore aux library, used for tests that need std and core stubs in
397+
/// cross-compilation scenarios that do not otherwise need to `-Zbuild-std`. Used in e.g. ABI
398+
/// tests.
399+
pub minicore_path: PathBuf,
395400
}
396401

397402
impl Config {

src/tools/compiletest/src/header.rs

+18
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ pub struct TestProps {
218218
pub filecheck_flags: Vec<String>,
219219
/// Don't automatically insert any `--check-cfg` args
220220
pub no_auto_check_cfg: bool,
221+
/// Build and use minicore as std/core stub for tests in cross-compilation scenarios that don't
222+
/// otherwise need `-Z build-std`.
223+
pub use_minicore: bool,
221224
}
222225

223226
mod directives {
@@ -263,6 +266,7 @@ mod directives {
263266
pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags";
264267
pub const FILECHECK_FLAGS: &'static str = "filecheck-flags";
265268
pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg";
269+
pub const USE_MINICORE: &'static str = "use-minicore";
266270
// This isn't a real directive, just one that is probably mistyped often
267271
pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
268272
}
@@ -322,6 +326,7 @@ impl TestProps {
322326
llvm_cov_flags: vec![],
323327
filecheck_flags: vec![],
324328
no_auto_check_cfg: false,
329+
use_minicore: false,
325330
}
326331
}
327332

@@ -597,6 +602,8 @@ impl TestProps {
597602
}
598603

599604
config.set_name_directive(ln, NO_AUTO_CHECK_CFG, &mut self.no_auto_check_cfg);
605+
606+
self.update_use_minicore(ln, config);
600607
},
601608
);
602609

@@ -710,6 +717,17 @@ impl TestProps {
710717
pub fn local_pass_mode(&self) -> Option<PassMode> {
711718
self.pass_mode
712719
}
720+
721+
pub fn update_use_minicore(&mut self, ln: &str, config: &Config) {
722+
let use_minicore = config.parse_name_directive(ln, directives::USE_MINICORE);
723+
if use_minicore {
724+
if !matches!(config.mode, Mode::Ui | Mode::Codegen | Mode::Assembly) {
725+
panic!("`use-minicore` is only supported for ui, codegen and assembly test modes");
726+
}
727+
728+
self.use_minicore = use_minicore;
729+
}
730+
}
713731
}
714732

715733
/// Extract an `(Option<line_revision>, directive)` directive from a line if comment is present.

src/tools/compiletest/src/header/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ impl ConfigBuilder {
149149
"--git-repository=",
150150
"--nightly-branch=",
151151
"--git-merge-commit-email=",
152+
"--minicore-path=",
152153
];
153154
let mut args: Vec<String> = args.iter().map(ToString::to_string).collect();
154155

src/tools/compiletest/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
170170
"git-merge-commit-email",
171171
"email address used for finding merge commits",
172172
"EMAIL",
173-
);
173+
)
174+
.reqopt("", "minicore-path", "path to minicore aux library", "PATH");
174175

175176
let (argv0, args_) = args.split_first().unwrap();
176177
if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
@@ -357,6 +358,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
357358
git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(),
358359

359360
profiler_support: matches.opt_present("profiler-support"),
361+
362+
minicore_path: opt_path(matches, "minicore-path"),
360363
}
361364
}
362365

@@ -394,6 +397,7 @@ pub fn log_config(config: &Config) {
394397
logv(c, format!("host-linker: {:?}", config.host_linker));
395398
logv(c, format!("verbose: {}", config.verbose));
396399
logv(c, format!("format: {:?}", config.format));
400+
logv(c, format!("minicore_path: {:?}", config.minicore_path.display()));
397401
logv(c, "\n".to_string());
398402
}
399403

src/tools/compiletest/src/runtest.rs

+45-39
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ impl<'test> TestCx<'test> {
827827
_ => AllowUnused::No,
828828
};
829829

830-
let rustc = self.make_compile_args(
830+
let mut rustc = self.make_compile_args(
831831
&self.testpaths.file,
832832
output_file,
833833
emit,
@@ -836,6 +836,12 @@ impl<'test> TestCx<'test> {
836836
passes,
837837
);
838838

839+
if self.props.use_minicore {
840+
let minicore_path = self.build_minicore();
841+
rustc.arg("--extern");
842+
rustc.arg(&format!("minicore={}", minicore_path.to_str().unwrap()));
843+
}
844+
839845
self.compose_and_run_compiler(rustc, None, self.testpaths)
840846
}
841847

@@ -1108,8 +1114,8 @@ impl<'test> TestCx<'test> {
11081114
}
11091115
}
11101116

1111-
/// `root_testpaths` refers to the path of the original test.
1112-
/// the auxiliary and the test with an aux-build have the same `root_testpaths`.
1117+
/// `root_testpaths` refers to the path of the original test. the auxiliary and the test with an
1118+
/// aux-build have the same `root_testpaths`.
11131119
fn compose_and_run_compiler(
11141120
&self,
11151121
mut rustc: Command,
@@ -1129,6 +1135,37 @@ impl<'test> TestCx<'test> {
11291135
)
11301136
}
11311137

1138+
/// Builds `minicore`. Returns the path to the minicore rlib within the base test output
1139+
/// directory.
1140+
fn build_minicore(&self) -> PathBuf {
1141+
let output_file_path = self.output_base_dir().join("libminicore.rlib");
1142+
let mut rustc = self.make_compile_args(
1143+
&self.config.minicore_path,
1144+
TargetLocation::ThisFile(output_file_path.clone()),
1145+
Emit::None,
1146+
AllowUnused::Yes,
1147+
LinkToAux::No,
1148+
vec![],
1149+
);
1150+
1151+
rustc.args(&["--crate-type", "rlib"]);
1152+
rustc.arg("-Cpanic=abort");
1153+
1154+
let res =
1155+
self.compose_and_run(rustc, self.config.compile_lib_path.to_str().unwrap(), None, None);
1156+
if !res.status.success() {
1157+
self.fatal_proc_rec(
1158+
&format!(
1159+
"auxiliary build of {:?} failed to compile: ",
1160+
self.config.minicore_path.display()
1161+
),
1162+
&res,
1163+
);
1164+
}
1165+
1166+
output_file_path
1167+
}
1168+
11321169
/// Builds an aux dependency.
11331170
fn build_auxiliary(
11341171
&self,
@@ -1420,6 +1457,11 @@ impl<'test> TestCx<'test> {
14201457
rustc.arg(dir_opt);
14211458
};
14221459

1460+
// `use-minicore` requires `#![no_std]` and `#![no_core]`, which means no unwinding panics.
1461+
if self.props.use_minicore {
1462+
rustc.arg("-Cpanic=abort");
1463+
}
1464+
14231465
match self.config.mode {
14241466
Incremental => {
14251467
// If we are extracting and matching errors in the new
@@ -1846,42 +1888,6 @@ impl<'test> TestCx<'test> {
18461888
(proc_res, output_path)
18471889
}
18481890

1849-
fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
1850-
let output_file = self.get_output_file("s");
1851-
let input_file = &self.testpaths.file;
1852-
1853-
let mut emit = Emit::None;
1854-
match self.props.assembly_output.as_ref().map(AsRef::as_ref) {
1855-
Some("emit-asm") => {
1856-
emit = Emit::Asm;
1857-
}
1858-
1859-
Some("bpf-linker") => {
1860-
emit = Emit::LinkArgsAsm;
1861-
}
1862-
1863-
Some("ptx-linker") => {
1864-
// No extra flags needed.
1865-
}
1866-
1867-
Some(header) => self.fatal(&format!("unknown 'assembly-output' header: {header}")),
1868-
None => self.fatal("missing 'assembly-output' header"),
1869-
}
1870-
1871-
let rustc = self.make_compile_args(
1872-
input_file,
1873-
output_file,
1874-
emit,
1875-
AllowUnused::No,
1876-
LinkToAux::Yes,
1877-
Vec::new(),
1878-
);
1879-
1880-
let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths);
1881-
let output_path = self.get_filecheck_file("s");
1882-
(proc_res, output_path)
1883-
}
1884-
18851891
fn verify_with_filecheck(&self, output: &Path) -> ProcRes {
18861892
let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
18871893
filecheck.arg("--input-file").arg(output).arg(&self.testpaths.file);

src/tools/compiletest/src/runtest/assembly.rs

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use super::TestCx;
1+
use std::path::PathBuf;
2+
3+
use super::{AllowUnused, Emit, LinkToAux, ProcRes, TestCx};
24

35
impl TestCx<'_> {
46
pub(super) fn run_assembly_test(&self) {
@@ -16,4 +18,40 @@ impl TestCx<'_> {
1618
self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
1719
}
1820
}
21+
22+
fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
23+
let output_file = self.get_output_file("s");
24+
let input_file = &self.testpaths.file;
25+
26+
let mut emit = Emit::None;
27+
match self.props.assembly_output.as_ref().map(AsRef::as_ref) {
28+
Some("emit-asm") => {
29+
emit = Emit::Asm;
30+
}
31+
32+
Some("bpf-linker") => {
33+
emit = Emit::LinkArgsAsm;
34+
}
35+
36+
Some("ptx-linker") => {
37+
// No extra flags needed.
38+
}
39+
40+
Some(header) => self.fatal(&format!("unknown 'assembly-output' header: {header}")),
41+
None => self.fatal("missing 'assembly-output' header"),
42+
}
43+
44+
let rustc = self.make_compile_args(
45+
input_file,
46+
output_file,
47+
emit,
48+
AllowUnused::No,
49+
LinkToAux::Yes,
50+
Vec::new(),
51+
);
52+
53+
let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths);
54+
let output_path = self.get_filecheck_file("s");
55+
(proc_res, output_path)
56+
}
1957
}

0 commit comments

Comments
 (0)