@@ -40,11 +40,18 @@ pub struct Std {
4040 ///
4141 /// This shouldn't be used from other steps; see the comment on [`Rustc`].
4242 crates : Interned < Vec < String > > ,
43+ /// When using download-rustc, we need to use a new build of `std` for running unit tests of Std itself,
44+ /// but we need to use the downloaded copy of std for linking to rustdoc. Allow this to be overriden by `builder.ensure` from other steps.
45+ force_recompile : bool ,
4346}
4447
4548impl Std {
4649 pub fn new ( compiler : Compiler , target : TargetSelection ) -> Self {
47- Self { target, compiler, crates : Default :: default ( ) }
50+ Self { target, compiler, crates : Default :: default ( ) , force_recompile : false }
51+ }
52+
53+ pub fn force_recompile ( compiler : Compiler , target : TargetSelection ) -> Self {
54+ Self { target, compiler, crates : Default :: default ( ) , force_recompile : true }
4855 }
4956}
5057
@@ -77,6 +84,7 @@ impl Step for Std {
7784 compiler : run. builder . compiler ( run. builder . top_stage , run. build_triple ( ) ) ,
7885 target : run. target ,
7986 crates : make_run_crates ( & run, "library" ) ,
87+ force_recompile : false ,
8088 } ) ;
8189 }
8290
@@ -89,11 +97,20 @@ impl Step for Std {
8997 let target = self . target ;
9098 let compiler = self . compiler ;
9199
92- // When using `download-rustc`, we already have artifacts for the host available
93- // (they were copied in `impl Step for Sysroot`). Don't recompile them.
94- // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
95- // so its artifacts can't be reused.
96- if builder. download_rustc ( ) && compiler. stage != 0 && target == builder. build . build {
100+ // When using `download-rustc`, we already have artifacts for the host available. Don't
101+ // recompile them.
102+ if builder. download_rustc ( ) && target == builder. build . build
103+ // NOTE: the beta compiler may generate different artifacts than the downloaded compiler, so
104+ // its artifacts can't be reused.
105+ && compiler. stage != 0
106+ // This check is specific to testing std itself; see `test::Std` for more details.
107+ && !self . force_recompile
108+ {
109+ cp_rustc_component_to_ci_sysroot (
110+ builder,
111+ compiler,
112+ builder. config . ci_rust_std_contents ( ) ,
113+ ) ;
97114 return ;
98115 }
99116
@@ -428,6 +445,8 @@ struct StdLink {
428445 pub target : TargetSelection ,
429446 /// Not actually used; only present to make sure the cache invalidation is correct.
430447 crates : Interned < Vec < String > > ,
448+ /// See [`Std::force_recompile`].
449+ force_recompile : bool ,
431450}
432451
433452impl StdLink {
@@ -437,6 +456,7 @@ impl StdLink {
437456 target_compiler : std. compiler ,
438457 target : std. target ,
439458 crates : std. crates ,
459+ force_recompile : std. force_recompile ,
440460 }
441461 }
442462}
@@ -460,8 +480,24 @@ impl Step for StdLink {
460480 let compiler = self . compiler ;
461481 let target_compiler = self . target_compiler ;
462482 let target = self . target ;
463- let libdir = builder. sysroot_libdir ( target_compiler, target) ;
464- let hostdir = builder. sysroot_libdir ( target_compiler, compiler. host ) ;
483+
484+ // NOTE: intentionally does *not* check `target == builder.build` to avoid having to add the same check in `test::Crate`.
485+ let ( libdir, hostdir) = if self . force_recompile && builder. download_rustc ( ) {
486+ // NOTE: copies part of `sysroot_libdir` to avoid having to add a new `force_recompile` argument there too
487+ let lib = builder. sysroot_libdir_relative ( self . compiler ) ;
488+ let sysroot = builder. ensure ( crate :: compile:: Sysroot {
489+ compiler : self . compiler ,
490+ force_recompile : self . force_recompile ,
491+ } ) ;
492+ let libdir = sysroot. join ( lib) . join ( "rustlib" ) . join ( target. triple ) . join ( "lib" ) ;
493+ let hostdir = sysroot. join ( lib) . join ( "rustlib" ) . join ( compiler. host . triple ) . join ( "lib" ) ;
494+ ( INTERNER . intern_path ( libdir) , INTERNER . intern_path ( hostdir) )
495+ } else {
496+ let libdir = builder. sysroot_libdir ( target_compiler, target) ;
497+ let hostdir = builder. sysroot_libdir ( target_compiler, compiler. host ) ;
498+ ( libdir, hostdir)
499+ } ;
500+
465501 add_to_sysroot ( builder, & libdir, & hostdir, & libstd_stamp ( builder, compiler, target) ) ;
466502 }
467503}
@@ -594,6 +630,25 @@ impl Step for StartupObjects {
594630 }
595631}
596632
633+ fn cp_rustc_component_to_ci_sysroot (
634+ builder : & Builder < ' _ > ,
635+ compiler : Compiler ,
636+ contents : Vec < String > ,
637+ ) {
638+ let sysroot = builder. ensure ( Sysroot { compiler, force_recompile : false } ) ;
639+
640+ let ci_rustc_dir = builder. out . join ( & * builder. build . build . triple ) . join ( "ci-rustc" ) ;
641+ for file in contents {
642+ let src = ci_rustc_dir. join ( & file) ;
643+ let dst = sysroot. join ( file) ;
644+ if src. is_dir ( ) {
645+ t ! ( fs:: create_dir_all( dst) ) ;
646+ } else {
647+ builder. copy ( & src, & dst) ;
648+ }
649+ }
650+ }
651+
597652#[ derive( Debug , PartialOrd , Ord , Copy , Clone , PartialEq , Eq , Hash ) ]
598653pub struct Rustc {
599654 pub target : TargetSelection ,
@@ -653,18 +708,11 @@ impl Step for Rustc {
653708 if builder. download_rustc ( ) && compiler. stage != 0 {
654709 // Copy the existing artifacts instead of rebuilding them.
655710 // NOTE: this path is only taken for tools linking to rustc-dev (including ui-fulldeps tests).
656- let sysroot = builder. ensure ( Sysroot { compiler } ) ;
657-
658- let ci_rustc_dir = builder. out . join ( & * builder. build . build . triple ) . join ( "ci-rustc" ) ;
659- for file in builder. config . rustc_dev_contents ( ) {
660- let src = ci_rustc_dir. join ( & file) ;
661- let dst = sysroot. join ( file) ;
662- if src. is_dir ( ) {
663- t ! ( fs:: create_dir_all( dst) ) ;
664- } else {
665- builder. copy ( & src, & dst) ;
666- }
667- }
711+ cp_rustc_component_to_ci_sysroot (
712+ builder,
713+ compiler,
714+ builder. config . ci_rustc_dev_contents ( ) ,
715+ ) ;
668716 return ;
669717 }
670718
@@ -1225,6 +1273,14 @@ pub fn compiler_file(
12251273#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
12261274pub struct Sysroot {
12271275 pub compiler : Compiler ,
1276+ /// See [`Std::force_recompile`].
1277+ force_recompile : bool ,
1278+ }
1279+
1280+ impl Sysroot {
1281+ pub ( crate ) fn new ( compiler : Compiler ) -> Self {
1282+ Sysroot { compiler, force_recompile : false }
1283+ }
12281284}
12291285
12301286impl Step for Sysroot {
@@ -1247,6 +1303,8 @@ impl Step for Sysroot {
12471303 let sysroot_dir = |stage| {
12481304 if stage == 0 {
12491305 host_dir. join ( "stage0-sysroot" )
1306+ } else if self . force_recompile && stage == compiler. stage {
1307+ host_dir. join ( format ! ( "stage{stage}-test-sysroot" ) )
12501308 } else if builder. download_rustc ( ) && compiler. stage != builder. top_stage {
12511309 host_dir. join ( "ci-rustc-sysroot" )
12521310 } else {
@@ -1286,14 +1344,19 @@ impl Step for Sysroot {
12861344 // 2. The sysroot is deleted and recreated between each invocation, so running `x test
12871345 // ui-fulldeps && x test ui` can't cause failures.
12881346 let mut filtered_files = Vec :: new ( ) ;
1289- // Don't trim directories or files that aren't loaded per-target; they can't cause conflicts.
1290- let suffix = format ! ( "lib/rustlib/{}/lib" , compiler . host ) ;
1291- for path in builder . config . rustc_dev_contents ( ) {
1292- let path = Path :: new ( & path ) ;
1293- if path. parent ( ) . map_or ( false , |parent| parent . ends_with ( & suffix ) ) {
1294- filtered_files . push ( path . file_name ( ) . unwrap ( ) . to_owned ( ) ) ;
1347+ let mut add_filtered_files = |suffix , contents| {
1348+ for path in contents {
1349+ let path = Path :: new ( & path ) ;
1350+ if path. parent ( ) . map_or ( false , |parent| parent . ends_with ( & suffix ) ) {
1351+ filtered_files . push ( path. file_name ( ) . unwrap ( ) . to_owned ( ) ) ;
1352+ }
12951353 }
1296- }
1354+ } ;
1355+ let suffix = format ! ( "lib/rustlib/{}/lib" , compiler. host) ;
1356+ add_filtered_files ( suffix. as_str ( ) , builder. config . ci_rustc_dev_contents ( ) ) ;
1357+ // NOTE: we can't copy std eagerly because `stage2-test-sysroot` needs to have only the
1358+ // newly compiled std, not the downloaded std.
1359+ add_filtered_files ( "lib" , builder. config . ci_rust_std_contents ( ) ) ;
12971360
12981361 let filtered_extensions = [ OsStr :: new ( "rmeta" ) , OsStr :: new ( "rlib" ) , OsStr :: new ( "so" ) ] ;
12991362 let ci_rustc_dir = builder. ci_rustc_dir ( builder. config . build ) ;
@@ -1411,7 +1474,8 @@ impl Step for Assemble {
14111474
14121475 // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
14131476 if builder. download_rustc ( ) {
1414- let sysroot = builder. ensure ( Sysroot { compiler : target_compiler } ) ;
1477+ let sysroot =
1478+ builder. ensure ( Sysroot { compiler : target_compiler, force_recompile : false } ) ;
14151479 // Ensure that `libLLVM.so` ends up in the newly created target directory,
14161480 // so that tools using `rustc_private` can use it.
14171481 dist:: maybe_install_llvm_target ( builder, target_compiler. host , & sysroot) ;
0 commit comments