@@ -40,11 +40,18 @@ pub struct Std {
40
40
///
41
41
/// This shouldn't be used from other steps; see the comment on [`Rustc`].
42
42
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 ,
43
46
}
44
47
45
48
impl Std {
46
49
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 }
48
55
}
49
56
}
50
57
@@ -77,6 +84,7 @@ impl Step for Std {
77
84
compiler : run. builder . compiler ( run. builder . top_stage , run. build_triple ( ) ) ,
78
85
target : run. target ,
79
86
crates : make_run_crates ( & run, "library" ) ,
87
+ force_recompile : false ,
80
88
} ) ;
81
89
}
82
90
@@ -89,11 +97,20 @@ impl Step for Std {
89
97
let target = self . target ;
90
98
let compiler = self . compiler ;
91
99
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
+ ) ;
97
114
return ;
98
115
}
99
116
@@ -428,6 +445,8 @@ struct StdLink {
428
445
pub target : TargetSelection ,
429
446
/// Not actually used; only present to make sure the cache invalidation is correct.
430
447
crates : Interned < Vec < String > > ,
448
+ /// See [`Std::force_recompile`].
449
+ force_recompile : bool ,
431
450
}
432
451
433
452
impl StdLink {
@@ -437,6 +456,7 @@ impl StdLink {
437
456
target_compiler : std. compiler ,
438
457
target : std. target ,
439
458
crates : std. crates ,
459
+ force_recompile : std. force_recompile ,
440
460
}
441
461
}
442
462
}
@@ -460,8 +480,24 @@ impl Step for StdLink {
460
480
let compiler = self . compiler ;
461
481
let target_compiler = self . target_compiler ;
462
482
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
+
465
501
add_to_sysroot ( builder, & libdir, & hostdir, & libstd_stamp ( builder, compiler, target) ) ;
466
502
}
467
503
}
@@ -594,6 +630,25 @@ impl Step for StartupObjects {
594
630
}
595
631
}
596
632
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
+
597
652
#[ derive( Debug , PartialOrd , Ord , Copy , Clone , PartialEq , Eq , Hash ) ]
598
653
pub struct Rustc {
599
654
pub target : TargetSelection ,
@@ -653,18 +708,11 @@ impl Step for Rustc {
653
708
if builder. download_rustc ( ) && compiler. stage != 0 {
654
709
// Copy the existing artifacts instead of rebuilding them.
655
710
// 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
+ ) ;
668
716
return ;
669
717
}
670
718
@@ -1225,6 +1273,14 @@ pub fn compiler_file(
1225
1273
#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
1226
1274
pub struct Sysroot {
1227
1275
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
+ }
1228
1284
}
1229
1285
1230
1286
impl Step for Sysroot {
@@ -1247,6 +1303,8 @@ impl Step for Sysroot {
1247
1303
let sysroot_dir = |stage| {
1248
1304
if stage == 0 {
1249
1305
host_dir. join ( "stage0-sysroot" )
1306
+ } else if self . force_recompile && stage == compiler. stage {
1307
+ host_dir. join ( format ! ( "stage{stage}-test-sysroot" ) )
1250
1308
} else if builder. download_rustc ( ) && compiler. stage != builder. top_stage {
1251
1309
host_dir. join ( "ci-rustc-sysroot" )
1252
1310
} else {
@@ -1286,14 +1344,19 @@ impl Step for Sysroot {
1286
1344
// 2. The sysroot is deleted and recreated between each invocation, so running `x test
1287
1345
// ui-fulldeps && x test ui` can't cause failures.
1288
1346
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
+ }
1295
1353
}
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 ( ) ) ;
1297
1360
1298
1361
let filtered_extensions = [ OsStr :: new ( "rmeta" ) , OsStr :: new ( "rlib" ) , OsStr :: new ( "so" ) ] ;
1299
1362
let ci_rustc_dir = builder. ci_rustc_dir ( builder. config . build ) ;
@@ -1411,7 +1474,8 @@ impl Step for Assemble {
1411
1474
1412
1475
// If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
1413
1476
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 } ) ;
1415
1479
// Ensure that `libLLVM.so` ends up in the newly created target directory,
1416
1480
// so that tools using `rustc_private` can use it.
1417
1481
dist:: maybe_install_llvm_target ( builder, target_compiler. host , & sysroot) ;
0 commit comments