@@ -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,26 @@ 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
+ 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
+
465
503
add_to_sysroot ( builder, & libdir, & hostdir, & libstd_stamp ( builder, compiler, target) ) ;
466
504
}
467
505
}
@@ -594,6 +632,25 @@ impl Step for StartupObjects {
594
632
}
595
633
}
596
634
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
+
597
654
#[ derive( Debug , PartialOrd , Ord , Copy , Clone , PartialEq , Eq , Hash ) ]
598
655
pub struct Rustc {
599
656
pub target : TargetSelection ,
@@ -653,18 +710,11 @@ impl Step for Rustc {
653
710
if builder. download_rustc ( ) && compiler. stage != 0 {
654
711
// Copy the existing artifacts instead of rebuilding them.
655
712
// 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
+ ) ;
668
718
return ;
669
719
}
670
720
@@ -1225,6 +1275,14 @@ pub fn compiler_file(
1225
1275
#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
1226
1276
pub struct Sysroot {
1227
1277
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
+ }
1228
1286
}
1229
1287
1230
1288
impl Step for Sysroot {
@@ -1247,6 +1305,8 @@ impl Step for Sysroot {
1247
1305
let sysroot_dir = |stage| {
1248
1306
if stage == 0 {
1249
1307
host_dir. join ( "stage0-sysroot" )
1308
+ } else if self . force_recompile && stage == compiler. stage {
1309
+ host_dir. join ( format ! ( "stage{stage}-test-sysroot" ) )
1250
1310
} else if builder. download_rustc ( ) && compiler. stage != builder. top_stage {
1251
1311
host_dir. join ( "ci-rustc-sysroot" )
1252
1312
} else {
@@ -1286,14 +1346,19 @@ impl Step for Sysroot {
1286
1346
// 2. The sysroot is deleted and recreated between each invocation, so running `x test
1287
1347
// ui-fulldeps && x test ui` can't cause failures.
1288
1348
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
+ }
1295
1355
}
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 ( ) ) ;
1297
1362
1298
1363
let filtered_extensions = [ OsStr :: new ( "rmeta" ) , OsStr :: new ( "rlib" ) , OsStr :: new ( "so" ) ] ;
1299
1364
let ci_rustc_dir = builder. ci_rustc_dir ( builder. config . build ) ;
@@ -1411,7 +1476,8 @@ impl Step for Assemble {
1411
1476
1412
1477
// If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
1413
1478
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 } ) ;
1415
1481
// Ensure that `libLLVM.so` ends up in the newly created target directory,
1416
1482
// so that tools using `rustc_private` can use it.
1417
1483
dist:: maybe_install_llvm_target ( builder, target_compiler. host , & sysroot) ;
0 commit comments