44//! However, this contains ~all test parts we expect people to be able to build and run locally.
55
66use std:: collections:: HashSet ;
7+ use std:: env:: join_paths;
78use std:: ffi:: { OsStr , OsString } ;
89use std:: path:: { Path , PathBuf } ;
910use std:: { env, fs, iter} ;
1011
12+ use build_helper:: exit;
1113#[ cfg( feature = "tracing" ) ]
1214use tracing:: instrument;
1315
@@ -242,8 +244,12 @@ impl Step for Cargotest {
242244 }
243245
244246 fn make_run ( run : RunConfig < ' _ > ) {
245- // FIXME: support testing stage 0 cargo?
246- assert ! ( run. builder. top_stage > 0 ) ;
247+ if run. builder . top_stage == 0 {
248+ eprintln ! (
249+ "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
250+ ) ;
251+ exit ! ( 1 ) ;
252+ }
247253 run. builder . ensure ( Cargotest {
248254 build_compiler : run. builder . compiler ( run. builder . top_stage - 1 , run. target ) ,
249255 host : run. target ,
@@ -322,14 +328,18 @@ impl Step for Cargo {
322328
323329 /// Runs `cargo test` for `cargo` packaged with Rust.
324330 fn run ( self , builder : & Builder < ' _ > ) {
325- // FIXME: we now use the same compiler to build cargo and then we also test that compiler
326- // using cargo.
327- // We could build cargo using a different compiler, but that complicates some things,
328- // because when we run cargo tests, the crates that are being compiled are accessing the
329- // sysroot of the build compiler, rather than the compiler being tested.
330- // Since these two compilers are currently the same, it works.
331+ // When we do a "stage 1 cargo test", it means that we test the stage 1 rustc
332+ // using stage 1 cargo. So we actually build cargo using the stage 0 compiler, and then
333+ // run its tests against the stage 1 compiler (called `tested_compiler` below).
331334 builder. ensure ( tool:: Cargo :: from_build_compiler ( self . build_compiler , self . host ) ) ;
332335
336+ let tested_compiler = builder. compiler ( self . build_compiler . stage + 1 , self . host ) ;
337+ builder. std ( tested_compiler, self . host ) ;
338+ // We also need to build rustdoc for cargo tests
339+ // It will be located in the bindir of `tested_compiler`, so we don't need to explicitly
340+ // pass its path to Cargo.
341+ builder. rustdoc_for_compiler ( tested_compiler) ;
342+
333343 let cargo = tool:: prepare_tool_cargo (
334344 builder,
335345 self . build_compiler ,
@@ -350,7 +360,27 @@ impl Step for Cargo {
350360 // Forcibly disable tests using nightly features since any changes to
351361 // those features won't be able to land.
352362 cargo. env ( "CARGO_TEST_DISABLE_NIGHTLY" , "1" ) ;
353- cargo. env ( "PATH" , path_for_cargo ( builder, self . build_compiler ) ) ;
363+
364+ // Configure PATH to find the right rustc. NB. we have to use PATH
365+ // and not RUSTC because the Cargo test suite has tests that will
366+ // fail if rustc is not spelled `rustc`.
367+ cargo. env ( "PATH" , bin_path_for_cargo ( builder, tested_compiler) ) ;
368+
369+ // The `cargo` command configured above has dylib dir path set to the `build_compiler`'s
370+ // libdir. That causes issues in cargo test, because the programs that cargo compiles are
371+ // incorrectly picking that libdir, even though they should be picking the
372+ // `tested_compiler`'s libdir. We thus have to override the precedence here.
373+ let existing_dylib_path = cargo
374+ . get_envs ( )
375+ . find ( |( k, _) | * k == OsStr :: new ( dylib_path_var ( ) ) )
376+ . and_then ( |( _, v) | v)
377+ . unwrap_or ( OsStr :: new ( "" ) ) ;
378+ cargo. env (
379+ dylib_path_var ( ) ,
380+ join_paths ( [ builder. rustc_libdir ( tested_compiler) . as_ref ( ) , existing_dylib_path] )
381+ . unwrap_or_default ( ) ,
382+ ) ;
383+
354384 // Cargo's test suite uses `CARGO_RUSTC_CURRENT_DIR` to determine the path that `file!` is
355385 // relative to. Cargo no longer sets this env var, so we have to do that. This has to be the
356386 // same value as `-Zroot-dir`.
@@ -859,10 +889,7 @@ impl Step for Clippy {
859889 }
860890}
861891
862- fn path_for_cargo ( builder : & Builder < ' _ > , compiler : Compiler ) -> OsString {
863- // Configure PATH to find the right rustc. NB. we have to use PATH
864- // and not RUSTC because the Cargo test suite has tests that will
865- // fail if rustc is not spelled `rustc`.
892+ fn bin_path_for_cargo ( builder : & Builder < ' _ > , compiler : Compiler ) -> OsString {
866893 let path = builder. sysroot ( compiler) . join ( "bin" ) ;
867894 let old_path = env:: var_os ( "PATH" ) . unwrap_or_default ( ) ;
868895 env:: join_paths ( iter:: once ( path) . chain ( env:: split_paths ( & old_path) ) ) . expect ( "" )
0 commit comments