|
9 | 9 | use std::borrow::Cow;
|
10 | 10 | use std::collections::HashSet;
|
11 | 11 | use std::env;
|
| 12 | +use std::ffi::OsStr; |
12 | 13 | use std::fs;
|
13 | 14 | use std::io::prelude::*;
|
14 | 15 | use std::io::BufReader;
|
@@ -652,8 +653,19 @@ impl Step for Rustc {
|
652 | 653 | // so its artifacts can't be reused.
|
653 | 654 | if builder.download_rustc() && compiler.stage != 0 {
|
654 | 655 | // Copy the existing artifacts instead of rebuilding them.
|
655 |
| - // NOTE: this path is only taken for tools linking to rustc-dev. |
656 |
| - builder.ensure(Sysroot { compiler }); |
| 656 | + // NOTE: this path is only taken for tools linking to rustc-dev (including ui-fulldeps tests). |
| 657 | + let sysroot = builder.ensure(Sysroot { compiler }); |
| 658 | + |
| 659 | + let ci_rustc_dir = builder.out.join(&*builder.build.build.triple).join("ci-rustc"); |
| 660 | + for file in builder.config.rustc_dev_contents() { |
| 661 | + let src = ci_rustc_dir.join(&file); |
| 662 | + let dst = sysroot.join(file); |
| 663 | + if src.is_dir() { |
| 664 | + t!(fs::create_dir_all(dst)); |
| 665 | + } else { |
| 666 | + builder.copy(&src, &dst); |
| 667 | + } |
| 668 | + } |
657 | 669 | return;
|
658 | 670 | }
|
659 | 671 |
|
@@ -1282,7 +1294,40 @@ impl Step for Sysroot {
|
1282 | 1294 | }
|
1283 | 1295 |
|
1284 | 1296 | // Copy the compiler into the correct sysroot.
|
1285 |
| - builder.cp_r(&builder.ci_rustc_dir(builder.build.build), &sysroot); |
| 1297 | + // NOTE(#108767): We intentionally don't copy `rustc-dev` artifacts until they're requested with `builder.ensure(Rustc)`. |
| 1298 | + // This fixes an issue where we'd have multiple copies of libc in the sysroot with no way to tell which to load. |
| 1299 | + // There are a few quirks of bootstrap that interact to make this reliable: |
| 1300 | + // 1. The order `Step`s are run is hard-coded in `builder.rs` and not configurable. This |
| 1301 | + // avoids e.g. reordering `test::UiFulldeps` before `test::Ui` and causing the latter to |
| 1302 | + // fail because of duplicate metadata. |
| 1303 | + // 2. The sysroot is deleted and recreated between each invocation, so running `x test |
| 1304 | + // ui-fulldeps && x test ui` can't cause failures. |
| 1305 | + let mut filtered_files = Vec::new(); |
| 1306 | + // Don't trim directories or files that aren't loaded per-target; they can't cause conflicts. |
| 1307 | + let suffix = format!("lib/rustlib/{}/lib", compiler.host); |
| 1308 | + for path in builder.config.rustc_dev_contents() { |
| 1309 | + let path = Path::new(&path); |
| 1310 | + if path.parent().map_or(false, |parent| parent.ends_with(&suffix)) { |
| 1311 | + filtered_files.push(path.file_name().unwrap().to_owned()); |
| 1312 | + } |
| 1313 | + } |
| 1314 | + |
| 1315 | + let filtered_extensions = [OsStr::new("rmeta"), OsStr::new("rlib"), OsStr::new("so")]; |
| 1316 | + let ci_rustc_dir = builder.ci_rustc_dir(builder.config.build); |
| 1317 | + builder.cp_filtered(&ci_rustc_dir, &sysroot, &|path| { |
| 1318 | + if path.extension().map_or(true, |ext| !filtered_extensions.contains(&ext)) { |
| 1319 | + return true; |
| 1320 | + } |
| 1321 | + if !path.parent().map_or(true, |p| p.ends_with(&suffix)) { |
| 1322 | + return true; |
| 1323 | + } |
| 1324 | + if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) { |
| 1325 | + builder.verbose_than(1, &format!("ignoring {}", path.display())); |
| 1326 | + false |
| 1327 | + } else { |
| 1328 | + true |
| 1329 | + } |
| 1330 | + }); |
1286 | 1331 | return INTERNER.intern_path(sysroot);
|
1287 | 1332 | }
|
1288 | 1333 |
|
|
0 commit comments