@@ -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,26 @@ 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+ let ( libdir, hostdir) = if self . force_recompile
485+ && builder. download_rustc ( )
486+ && self . target == builder. build . build
487+ {
488+ // NOTE: copies part of `sysroot_libdir` to avoid having to add a new `force_recompile` argument there too
489+ let lib = builder. sysroot_libdir_relative ( self . compiler ) ;
490+ let sysroot = builder. ensure ( crate :: compile:: Sysroot {
491+ compiler : self . compiler ,
492+ force_recompile : self . force_recompile ,
493+ } ) ;
494+ let libdir = sysroot. join ( lib) . join ( "rustlib" ) . join ( target. triple ) . join ( "lib" ) ;
495+ let hostdir = sysroot. join ( lib) . join ( "rustlib" ) . join ( compiler. host . triple ) . join ( "lib" ) ;
496+ ( INTERNER . intern_path ( libdir) , INTERNER . intern_path ( hostdir) )
497+ } else {
498+ let libdir = builder. sysroot_libdir ( target_compiler, target) ;
499+ let hostdir = builder. sysroot_libdir ( target_compiler, compiler. host ) ;
500+ ( libdir, hostdir)
501+ } ;
502+
465503 add_to_sysroot ( builder, & libdir, & hostdir, & libstd_stamp ( builder, compiler, target) ) ;
466504 }
467505}
@@ -594,6 +632,25 @@ impl Step for StartupObjects {
594632 }
595633}
596634
635+ fn cp_rustc_component_to_ci_sysroot (
636+ builder : & Builder < ' _ > ,
637+ compiler : Compiler ,
638+ contents : Vec < String > ,
639+ ) {
640+ let sysroot = builder. ensure ( Sysroot { compiler, force_recompile : false } ) ;
641+
642+ let ci_rustc_dir = builder. out . join ( & * builder. build . build . triple ) . join ( "ci-rustc" ) ;
643+ for file in contents {
644+ let src = ci_rustc_dir. join ( & file) ;
645+ let dst = sysroot. join ( file) ;
646+ if src. is_dir ( ) {
647+ t ! ( fs:: create_dir_all( dst) ) ;
648+ } else {
649+ builder. copy ( & src, & dst) ;
650+ }
651+ }
652+ }
653+
597654#[ derive( Debug , PartialOrd , Ord , Copy , Clone , PartialEq , Eq , Hash ) ]
598655pub struct Rustc {
599656 pub target : TargetSelection ,
@@ -653,18 +710,11 @@ impl Step for Rustc {
653710 if builder. download_rustc ( ) && compiler. stage != 0 {
654711 // Copy the existing artifacts instead of rebuilding them.
655712 // 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- }
713+ cp_rustc_component_to_ci_sysroot (
714+ builder,
715+ compiler,
716+ builder. config . ci_rustc_dev_contents ( ) ,
717+ ) ;
668718 return ;
669719 }
670720
@@ -1225,6 +1275,14 @@ pub fn compiler_file(
12251275#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
12261276pub struct Sysroot {
12271277 pub compiler : Compiler ,
1278+ /// See [`Std::force_recompile`].
1279+ force_recompile : bool ,
1280+ }
1281+
1282+ impl Sysroot {
1283+ pub ( crate ) fn new ( compiler : Compiler ) -> Self {
1284+ Sysroot { compiler, force_recompile : false }
1285+ }
12281286}
12291287
12301288impl Step for Sysroot {
@@ -1247,6 +1305,8 @@ impl Step for Sysroot {
12471305 let sysroot_dir = |stage| {
12481306 if stage == 0 {
12491307 host_dir. join ( "stage0-sysroot" )
1308+ } else if self . force_recompile && stage == compiler. stage {
1309+ host_dir. join ( format ! ( "stage{stage}-test-sysroot" ) )
12501310 } else if builder. download_rustc ( ) && compiler. stage != builder. top_stage {
12511311 host_dir. join ( "ci-rustc-sysroot" )
12521312 } else {
@@ -1286,14 +1346,19 @@ impl Step for Sysroot {
12861346 // 2. The sysroot is deleted and recreated between each invocation, so running `x test
12871347 // ui-fulldeps && x test ui` can't cause failures.
12881348 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 ( ) ) ;
1349+ let mut add_filtered_files = |suffix , contents| {
1350+ for path in contents {
1351+ let path = Path :: new ( & path ) ;
1352+ if path. parent ( ) . map_or ( false , |parent| parent . ends_with ( & suffix ) ) {
1353+ filtered_files . push ( path. file_name ( ) . unwrap ( ) . to_owned ( ) ) ;
1354+ }
12951355 }
1296- }
1356+ } ;
1357+ let suffix = format ! ( "lib/rustlib/{}/lib" , compiler. host) ;
1358+ add_filtered_files ( suffix. as_str ( ) , builder. config . ci_rustc_dev_contents ( ) ) ;
1359+ // NOTE: we can't copy std eagerly because `stage2-test-sysroot` needs to have only the
1360+ // newly compiled std, not the downloaded std.
1361+ add_filtered_files ( "lib" , builder. config . ci_rust_std_contents ( ) ) ;
12971362
12981363 let filtered_extensions = [ OsStr :: new ( "rmeta" ) , OsStr :: new ( "rlib" ) , OsStr :: new ( "so" ) ] ;
12991364 let ci_rustc_dir = builder. ci_rustc_dir ( builder. config . build ) ;
@@ -1411,7 +1476,8 @@ impl Step for Assemble {
14111476
14121477 // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
14131478 if builder. download_rustc ( ) {
1414- let sysroot = builder. ensure ( Sysroot { compiler : target_compiler } ) ;
1479+ let sysroot =
1480+ builder. ensure ( Sysroot { compiler : target_compiler, force_recompile : false } ) ;
14151481 // Ensure that `libLLVM.so` ends up in the newly created target directory,
14161482 // so that tools using `rustc_private` can use it.
14171483 dist:: maybe_install_llvm_target ( builder, target_compiler. host , & sysroot) ;
0 commit comments