Skip to content

Commit f1974d7

Browse files
committed
Extract Crate to test_helpers
1 parent 06768f4 commit f1974d7

File tree

2 files changed

+152
-149
lines changed

2 files changed

+152
-149
lines changed

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

Lines changed: 0 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -362,152 +362,6 @@ impl Step for CrateLibrustc {
362362
}
363363
}
364364

365-
/// Runs `cargo test` for standard library crates.
366-
///
367-
/// (Also used internally to run `cargo test` for compiler crates.)
368-
///
369-
/// FIXME(Zalathar): Try to split this into two separate steps: a user-visible
370-
/// step for testing standard library crates, and an internal step used for both
371-
/// library crates and compiler crates.
372-
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
373-
pub struct Crate {
374-
pub compiler: Compiler,
375-
pub target: TargetSelection,
376-
pub mode: Mode,
377-
pub crates: Vec<String>,
378-
}
379-
380-
impl Step for Crate {
381-
type Output = ();
382-
const DEFAULT: bool = true;
383-
384-
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
385-
run.crate_or_deps("sysroot").crate_or_deps("coretests")
386-
}
387-
388-
fn make_run(run: RunConfig<'_>) {
389-
let builder = run.builder;
390-
let host = run.build_triple();
391-
let compiler = builder.compiler_for(builder.top_stage, host, host);
392-
let crates = run
393-
.paths
394-
.iter()
395-
.map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
396-
.collect();
397-
398-
builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates });
399-
}
400-
401-
/// Runs all unit tests plus documentation tests for a given crate defined
402-
/// by a `Cargo.toml` (single manifest)
403-
///
404-
/// This is what runs tests for crates like the standard library, compiler, etc.
405-
/// It essentially is the driver for running `cargo test`.
406-
///
407-
/// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
408-
/// arguments, and those arguments are discovered from `cargo metadata`.
409-
fn run(self, builder: &Builder<'_>) {
410-
let compiler = self.compiler;
411-
let target = self.target;
412-
let mode = self.mode;
413-
414-
// Prepare sysroot
415-
// See [field@compile::Std::force_recompile].
416-
builder.ensure(compile::Std::new(compiler, compiler.host).force_recompile(true));
417-
418-
// If we're not doing a full bootstrap but we're testing a stage2
419-
// version of libstd, then what we're actually testing is the libstd
420-
// produced in stage1. Reflect that here by updating the compiler that
421-
// we're working with automatically.
422-
let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
423-
424-
let mut cargo = if builder.kind == Kind::Miri {
425-
if builder.top_stage == 0 {
426-
eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
427-
std::process::exit(1);
428-
}
429-
430-
// Build `cargo miri test` command
431-
// (Implicitly prepares target sysroot)
432-
let mut cargo = builder::Cargo::new(
433-
builder,
434-
compiler,
435-
mode,
436-
SourceType::InTree,
437-
target,
438-
Kind::MiriTest,
439-
);
440-
// This hack helps bootstrap run standard library tests in Miri. The issue is as
441-
// follows: when running `cargo miri test` on libcore, cargo builds a local copy of core
442-
// and makes it a dependency of the integration test crate. This copy duplicates all the
443-
// lang items, so the build fails. (Regular testing avoids this because the sysroot is a
444-
// literal copy of what `cargo build` produces, but since Miri builds its own sysroot
445-
// this does not work for us.) So we need to make it so that the locally built libcore
446-
// contains all the items from `core`, but does not re-define them -- we want to replace
447-
// the entire crate but a re-export of the sysroot crate. We do this by swapping out the
448-
// source file: if `MIRI_REPLACE_LIBRS_IF_NOT_TEST` is set and we are building a
449-
// `lib.rs` file, and a `lib.miri.rs` file exists in the same folder, we build that
450-
// instead. But crucially we only do that for the library, not the test builds.
451-
cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
452-
// std needs to be built with `-Zforce-unstable-if-unmarked`. For some reason the builder
453-
// does not set this directly, but relies on the rustc wrapper to set it, and we are not using
454-
// the wrapper -- hence we have to set it ourselves.
455-
cargo.rustflag("-Zforce-unstable-if-unmarked");
456-
cargo
457-
} else {
458-
// Also prepare a sysroot for the target.
459-
if !builder.is_builder_target(target) {
460-
builder.ensure(compile::Std::new(compiler, target).force_recompile(true));
461-
builder.ensure(RemoteCopyLibs { compiler, target });
462-
}
463-
464-
// Build `cargo test` command
465-
builder::Cargo::new(builder, compiler, mode, SourceType::InTree, target, builder.kind)
466-
};
467-
468-
match mode {
469-
Mode::Std => {
470-
if builder.kind == Kind::Miri {
471-
// We can't use `std_cargo` as that uses `optimized-compiler-builtins` which
472-
// needs host tools for the given target. This is similar to what `compile::Std`
473-
// does when `is_for_mir_opt_tests` is true. There's probably a chance for
474-
// de-duplication here... `std_cargo` should support a mode that avoids needing
475-
// host tools.
476-
cargo
477-
.arg("--manifest-path")
478-
.arg(builder.src.join("library/sysroot/Cargo.toml"));
479-
} else {
480-
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
481-
// `std_cargo` actually does the wrong thing: it passes `--sysroot build/host/stage2`,
482-
// but we want to use the force-recompile std we just built in `build/host/stage2-test-sysroot`.
483-
// Override it.
484-
if builder.download_rustc() && compiler.stage > 0 {
485-
let sysroot = builder
486-
.out
487-
.join(compiler.host)
488-
.join(format!("stage{}-test-sysroot", compiler.stage));
489-
cargo.env("RUSTC_SYSROOT", sysroot);
490-
}
491-
}
492-
}
493-
Mode::Rustc => {
494-
compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
495-
}
496-
_ => panic!("can only test libraries"),
497-
};
498-
499-
run_cargo_test(
500-
cargo,
501-
&[],
502-
&self.crates,
503-
&self.crates[0],
504-
&*crate_description(&self.crates),
505-
target,
506-
builder,
507-
);
508-
}
509-
}
510-
511365
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
512366
pub struct Distcheck;
513367

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

Lines changed: 152 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ use std::env;
22
use std::path::PathBuf;
33

44
use crate::core::build_steps::compile;
5-
use crate::core::build_steps::tool::{self, Tool};
6-
use crate::core::builder::{self, Builder, Compiler, Kind, ShouldRun, Step};
5+
use crate::core::build_steps::tool::{self, SourceType, Tool};
6+
use crate::core::builder::{
7+
self, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, crate_description,
8+
};
79
use crate::core::config::TargetSelection;
810
use crate::utils::exec::{BootstrapCommand, command};
911
use crate::utils::helpers::{self, dylib_path, dylib_path_var, t};
1012
use crate::utils::render_tests::add_flags_and_try_run_tests;
11-
use crate::{DocTests, envify};
13+
use crate::{DocTests, Mode, envify};
1214

1315
/// Given a `cargo test` subcommand, add the appropriate flags and run it.
1416
///
@@ -175,3 +177,150 @@ impl Step for RemoteCopyLibs {
175177
}
176178
}
177179
}
180+
181+
// FIXME(#137178): `Crate` is very confusing, probably need to be split into two steps?
182+
183+
/// Runs `cargo test` for standard library crates.
184+
///
185+
/// (Also used internally to run `cargo test` for compiler crates.)
186+
///
187+
/// FIXME(Zalathar): Try to split this into two separate steps: a user-visible step for testing
188+
/// standard library crates, and an internal step used for both library crates and compiler crates.
189+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
190+
pub struct Crate {
191+
pub compiler: Compiler,
192+
pub target: TargetSelection,
193+
pub mode: Mode,
194+
pub crates: Vec<String>,
195+
}
196+
197+
impl Step for Crate {
198+
type Output = ();
199+
const DEFAULT: bool = true;
200+
201+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
202+
run.crate_or_deps("sysroot").crate_or_deps("coretests")
203+
}
204+
205+
fn make_run(run: RunConfig<'_>) {
206+
let builder = run.builder;
207+
let host = run.build_triple();
208+
let compiler = builder.compiler_for(builder.top_stage, host, host);
209+
let crates = run
210+
.paths
211+
.iter()
212+
.map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
213+
.collect();
214+
215+
builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates });
216+
}
217+
218+
/// Runs all unit tests plus documentation tests for a given crate defined
219+
/// by a `Cargo.toml` (single manifest)
220+
///
221+
/// This is what runs tests for crates like the standard library, compiler, etc.
222+
/// It essentially is the driver for running `cargo test`.
223+
///
224+
/// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
225+
/// arguments, and those arguments are discovered from `cargo metadata`.
226+
fn run(self, builder: &Builder<'_>) {
227+
let compiler = self.compiler;
228+
let target = self.target;
229+
let mode = self.mode;
230+
231+
// Prepare sysroot
232+
// See [field@compile::Std::force_recompile].
233+
builder.ensure(compile::Std::new(compiler, compiler.host).force_recompile(true));
234+
235+
// If we're not doing a full bootstrap but we're testing a stage2
236+
// version of libstd, then what we're actually testing is the libstd
237+
// produced in stage1. Reflect that here by updating the compiler that
238+
// we're working with automatically.
239+
let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
240+
241+
let mut cargo = if builder.kind == Kind::Miri {
242+
if builder.top_stage == 0 {
243+
eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
244+
std::process::exit(1);
245+
}
246+
247+
// Build `cargo miri test` command
248+
// (Implicitly prepares target sysroot)
249+
let mut cargo = builder::Cargo::new(
250+
builder,
251+
compiler,
252+
mode,
253+
SourceType::InTree,
254+
target,
255+
Kind::MiriTest,
256+
);
257+
// This hack helps bootstrap run standard library tests in Miri. The issue is as
258+
// follows: when running `cargo miri test` on libcore, cargo builds a local copy of core
259+
// and makes it a dependency of the integration test crate. This copy duplicates all the
260+
// lang items, so the build fails. (Regular testing avoids this because the sysroot is a
261+
// literal copy of what `cargo build` produces, but since Miri builds its own sysroot
262+
// this does not work for us.) So we need to make it so that the locally built libcore
263+
// contains all the items from `core`, but does not re-define them -- we want to replace
264+
// the entire crate but a re-export of the sysroot crate. We do this by swapping out the
265+
// source file: if `MIRI_REPLACE_LIBRS_IF_NOT_TEST` is set and we are building a
266+
// `lib.rs` file, and a `lib.miri.rs` file exists in the same folder, we build that
267+
// instead. But crucially we only do that for the library, not the test builds.
268+
cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
269+
// std needs to be built with `-Zforce-unstable-if-unmarked`. For some reason the builder
270+
// does not set this directly, but relies on the rustc wrapper to set it, and we are not using
271+
// the wrapper -- hence we have to set it ourselves.
272+
cargo.rustflag("-Zforce-unstable-if-unmarked");
273+
cargo
274+
} else {
275+
// Also prepare a sysroot for the target.
276+
if !builder.is_builder_target(target) {
277+
builder.ensure(compile::Std::new(compiler, target).force_recompile(true));
278+
builder.ensure(RemoteCopyLibs { compiler, target });
279+
}
280+
281+
// Build `cargo test` command
282+
builder::Cargo::new(builder, compiler, mode, SourceType::InTree, target, builder.kind)
283+
};
284+
285+
match mode {
286+
Mode::Std => {
287+
if builder.kind == Kind::Miri {
288+
// We can't use `std_cargo` as that uses `optimized-compiler-builtins` which
289+
// needs host tools for the given target. This is similar to what `compile::Std`
290+
// does when `is_for_mir_opt_tests` is true. There's probably a chance for
291+
// de-duplication here... `std_cargo` should support a mode that avoids needing
292+
// host tools.
293+
cargo
294+
.arg("--manifest-path")
295+
.arg(builder.src.join("library/sysroot/Cargo.toml"));
296+
} else {
297+
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
298+
// `std_cargo` actually does the wrong thing: it passes `--sysroot build/host/stage2`,
299+
// but we want to use the force-recompile std we just built in `build/host/stage2-test-sysroot`.
300+
// Override it.
301+
if builder.download_rustc() && compiler.stage > 0 {
302+
let sysroot = builder
303+
.out
304+
.join(compiler.host)
305+
.join(format!("stage{}-test-sysroot", compiler.stage));
306+
cargo.env("RUSTC_SYSROOT", sysroot);
307+
}
308+
}
309+
}
310+
Mode::Rustc => {
311+
compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
312+
}
313+
_ => panic!("can only test libraries"),
314+
};
315+
316+
run_cargo_test(
317+
cargo,
318+
&[],
319+
&self.crates,
320+
&self.crates[0],
321+
&*crate_description(&self.crates),
322+
target,
323+
builder,
324+
);
325+
}
326+
}

0 commit comments

Comments
 (0)