Skip to content

Commit 494cbd8

Browse files
committed
bootstrap: implement new feature bootstrap-self-test
Some of the bootstrap logics should be ignored during unit tests because they either make the tests take longer or cause them to fail. Therefore we need to be able to exclude them from the bootstrap when it's called by unit tests. This change introduces a new feature called `bootstrap-self-test`, which is enabled on bootstrap unit tests by default. This allows us to keep the logic separate between compiler builds and bootstrap tests without needing messy workarounds (like checking if target names match those in the unit tests). Signed-off-by: onur-ozkan <[email protected]>
1 parent 7c73595 commit 494cbd8

File tree

6 files changed

+54
-29
lines changed

6 files changed

+54
-29
lines changed

src/bootstrap/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ default-run = "bootstrap"
77

88
[features]
99
build-metrics = ["sysinfo"]
10+
bootstrap-self-test = [] # enabled in the bootstrap unit tests
1011

1112
[lib]
1213
path = "src/lib.rs"

src/bootstrap/src/core/build_steps/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3061,6 +3061,7 @@ impl Step for Bootstrap {
30613061

30623062
let mut cmd = Command::new(&builder.initial_cargo);
30633063
cmd.arg("test")
3064+
.args(["--features", "bootstrap-self-test"])
30643065
.current_dir(builder.src.join("src/bootstrap"))
30653066
.env("RUSTFLAGS", "-Cdebuginfo=2")
30663067
.env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))

src/bootstrap/src/core/config/config.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ use crate::utils::cache::{Interned, INTERNER};
2222
use crate::utils::channel::{self, GitInfo};
2323
use crate::utils::helpers::{exe, output, t};
2424
use build_helper::exit;
25-
use build_helper::util::fail;
26-
use semver::Version;
2725
use serde::{Deserialize, Deserializer};
2826
use serde_derive::Deserialize;
2927

@@ -1249,11 +1247,13 @@ impl Config {
12491247
// has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path.
12501248
cmd.arg("rev-parse").arg("--show-cdup");
12511249
// Discard stderr because we expect this to fail when building from a tarball.
1252-
let output = cmd
1253-
.stderr(std::process::Stdio::null())
1254-
.output()
1255-
.ok()
1256-
.and_then(|output| if output.status.success() { Some(output) } else { None });
1250+
let output = cmd.stderr(std::process::Stdio::null()).output().ok().and_then(|output| {
1251+
if output.status.success() {
1252+
Some(output)
1253+
} else {
1254+
None
1255+
}
1256+
});
12571257
if let Some(output) = output {
12581258
let git_root_relative = String::from_utf8(output.stdout).unwrap();
12591259
// We need to canonicalize this path to make sure it uses backslashes instead of forward slashes,
@@ -2346,7 +2346,11 @@ impl Config {
23462346
.get(&target)
23472347
.and_then(|t| t.split_debuginfo)
23482348
.or_else(|| {
2349-
if self.build == target { self.rust_split_debuginfo_for_build_triple } else { None }
2349+
if self.build == target {
2350+
self.rust_split_debuginfo_for_build_triple
2351+
} else {
2352+
None
2353+
}
23502354
})
23512355
.unwrap_or_else(|| SplitDebuginfo::default_for_platform(target))
23522356
}
@@ -2373,8 +2377,14 @@ impl Config {
23732377
}
23742378
}
23752379

2376-
// check rustc/cargo version is same or lower with 1 apart from the building one
2380+
#[cfg(feature = "bootstrap-self-test")]
2381+
pub fn check_stage0_version(&self, _program_path: &Path, _component_name: &'static str) {}
2382+
2383+
/// check rustc/cargo version is same or lower with 1 apart from the building one
2384+
#[cfg(not(feature = "bootstrap-self-test"))]
23772385
pub fn check_stage0_version(&self, program_path: &Path, component_name: &'static str) {
2386+
use build_helper::util::fail;
2387+
23782388
if self.dry_run() {
23792389
return;
23802390
}
@@ -2391,10 +2401,10 @@ impl Config {
23912401
}
23922402

23932403
let stage0_version =
2394-
Version::parse(stage0_output.next().unwrap().split('-').next().unwrap().trim())
2404+
semver::Version::parse(stage0_output.next().unwrap().split('-').next().unwrap().trim())
23952405
.unwrap();
23962406
let source_version =
2397-
Version::parse(fs::read_to_string(self.src.join("src/version")).unwrap().trim())
2407+
semver::Version::parse(fs::read_to_string(self.src.join("src/version")).unwrap().trim())
23982408
.unwrap();
23992409
if !(source_version == stage0_version
24002410
|| (source_version.major == stage0_version.major

src/bootstrap/src/core/config/tests.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@ fn parse(config: &str) -> Config {
1515
Config::parse_inner(
1616
&[
1717
"check".to_string(),
18-
"--set=build.rustc=/does/not/exist".to_string(),
19-
"--set=build.cargo=/does/not/exist".to_string(),
2018
"--config=/does/not/exist".to_string(),
21-
"--skip-stage0-validation".to_string(),
2219
],
2320
|&_| toml::from_str(&config).unwrap(),
2421
)
@@ -171,10 +168,7 @@ fn override_toml_duplicate() {
171168
Config::parse_inner(
172169
&[
173170
"check".to_owned(),
174-
"--set=build.rustc=/does/not/exist".to_string(),
175-
"--set=build.cargo=/does/not/exist".to_string(),
176-
"--config=/does/not/exist".to_owned(),
177-
"--skip-stage0-validation".to_owned(),
171+
"--config=/does/not/exist".to_string(),
178172
"--set=change-id=1".to_owned(),
179173
"--set=change-id=2".to_owned(),
180174
],
@@ -200,9 +194,6 @@ fn profile_user_dist() {
200194
Config::parse_inner(
201195
&[
202196
"check".to_owned(),
203-
"--set=build.rustc=/does/not/exist".to_string(),
204-
"--set=build.cargo=/does/not/exist".to_string(),
205-
"--skip-stage0-validation".to_string(),
206197
],
207198
get_toml,
208199
);

src/bootstrap/src/core/download.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ use std::{
99
};
1010

1111
use build_helper::ci::CiEnv;
12-
use build_helper::stage0_parser::VersionMetadata;
1312
use xz2::bufread::XzDecoder;
1413

14+
use crate::utils::helpers::hex_encode;
1515
use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date};
16-
use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode};
1716
use crate::{t, Config};
1817

1918
static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock<bool> = OnceLock::new();
@@ -405,9 +404,17 @@ impl Config {
405404
cargo_clippy
406405
}
407406

407+
#[cfg(feature = "bootstrap-self-test")]
408+
pub(crate) fn maybe_download_rustfmt(&self) -> Option<PathBuf> {
409+
None
410+
}
411+
408412
/// NOTE: rustfmt is a completely different toolchain than the bootstrap compiler, so it can't
409413
/// reuse target directories or artifacts
414+
#[cfg(not(feature = "bootstrap-self-test"))]
410415
pub(crate) fn maybe_download_rustfmt(&self) -> Option<PathBuf> {
416+
use build_helper::stage0_parser::VersionMetadata;
417+
411418
let VersionMetadata { date, version } = self.stage0_metadata.rustfmt.as_ref()?;
412419
let channel = format!("{version}-{date}");
413420

@@ -487,6 +494,10 @@ impl Config {
487494
);
488495
}
489496

497+
#[cfg(feature = "bootstrap-self-test")]
498+
pub(crate) fn download_beta_toolchain(&self) {}
499+
500+
#[cfg(not(feature = "bootstrap-self-test"))]
490501
pub(crate) fn download_beta_toolchain(&self) {
491502
self.verbose(|| println!("downloading stage0 beta artifacts"));
492503

@@ -665,7 +676,13 @@ download-rustc = false
665676
self.unpack(&tarball, &bin_root, prefix);
666677
}
667678

679+
#[cfg(feature = "bootstrap-self-test")]
680+
pub(crate) fn maybe_download_ci_llvm(&self) {}
681+
682+
#[cfg(not(feature = "bootstrap-self-test"))]
668683
pub(crate) fn maybe_download_ci_llvm(&self) {
684+
use crate::core::build_steps::llvm::detect_llvm_sha;
685+
669686
if !self.llvm_from_ci {
670687
return;
671688
}
@@ -707,6 +724,7 @@ download-rustc = false
707724
}
708725
}
709726

727+
#[cfg(not(feature = "bootstrap-self-test"))]
710728
fn download_ci_llvm(&self, llvm_sha: &str) {
711729
let llvm_assertions = self.llvm_assertions;
712730

src/bootstrap/src/core/sanity.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88
//! In theory if we get past this phase it's a bug if a build fails, but in
99
//! practice that's likely not true!
1010
11-
use std::collections::{HashMap, HashSet};
11+
use std::collections::HashMap;
1212
use std::env;
1313
use std::ffi::{OsStr, OsString};
1414
use std::fs;
1515
use std::path::PathBuf;
1616
use std::process::Command;
17-
use walkdir::WalkDir;
17+
18+
#[cfg(not(feature = "bootstrap-self-test"))]
19+
use std::collections::HashSet;
1820

1921
use crate::builder::Kind;
2022
use crate::core::config::Target;
@@ -31,6 +33,7 @@ pub struct Finder {
3133
// it might not yet be included in stage0. In such cases, we handle the targets missing from stage0 in this list.
3234
//
3335
// Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
36+
#[cfg(not(feature = "bootstrap-self-test"))]
3437
const STAGE0_MISSING_TARGETS: &[&str] = &[
3538
// just a dummy comment so the list doesn't get onelined
3639
];
@@ -167,6 +170,7 @@ than building it.
167170
.map(|p| cmd_finder.must_have(p))
168171
.or_else(|| cmd_finder.maybe_have("reuse"));
169172

173+
#[cfg(not(feature = "bootstrap-self-test"))]
170174
let stage0_supported_target_list: HashSet<String> =
171175
output(Command::new(&build.config.initial_rustc).args(["--print", "target-list"]))
172176
.lines()
@@ -193,11 +197,11 @@ than building it.
193197
continue;
194198
}
195199

196-
let target_str = target.to_string();
197-
198200
// Ignore fake targets that are only used for unit tests in bootstrap.
199-
if !["A-A", "B-B", "C-C"].contains(&target_str.as_str()) {
201+
#[cfg(not(feature = "bootstrap-self-test"))]
202+
{
200203
let mut has_target = false;
204+
let target_str = target.to_string();
201205

202206
let missing_targets_hashset: HashSet<_> = STAGE0_MISSING_TARGETS.iter().map(|t| t.to_string()).collect();
203207
let duplicated_targets: Vec<_> = stage0_supported_target_list.intersection(&missing_targets_hashset).collect();
@@ -222,7 +226,7 @@ than building it.
222226
target_filename.push(".json");
223227

224228
// Recursively traverse through nested directories.
225-
let walker = WalkDir::new(custom_target_path).into_iter();
229+
let walker = walkdir::WalkDir::new(custom_target_path).into_iter();
226230
for entry in walker.filter_map(|e| e.ok()) {
227231
has_target |= entry.file_name() == target_filename;
228232
}

0 commit comments

Comments
 (0)