Skip to content

Commit 6aefd35

Browse files
authored
Unrolled build for #142416
Rollup merge of #142416 - Kobzol:bootstrap-cleanup-2, r=jieyouxu Assorted bootstrap cleanups (step 2) Very small improvements designed towards making bootstrap tests less hacky/special, and towards making it possible to run bootstrap tests in parallel. Best reviewed commit by commit. r? ``@jieyouxu``
2 parents d9ca9bd + a71b463 commit 6aefd35

File tree

13 files changed

+97
-106
lines changed

13 files changed

+97
-106
lines changed

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,7 +2009,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
20092009
// Note that if we encounter `PATH` we make sure to append to our own `PATH`
20102010
// rather than stomp over it.
20112011
if !builder.config.dry_run() && target.is_msvc() {
2012-
for (k, v) in builder.cc.borrow()[&target].env() {
2012+
for (k, v) in builder.cc[&target].env() {
20132013
if k != "PATH" {
20142014
cmd.env(k, v);
20152015
}
@@ -2026,8 +2026,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
20262026
// address sanitizer enabled (e.g., ntdll.dll).
20272027
cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
20282028
// Add the address sanitizer runtime to the PATH - it is located next to cl.exe.
2029-
let asan_runtime_path =
2030-
builder.cc.borrow()[&target].path().parent().unwrap().to_path_buf();
2029+
let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
20312030
let old_path = cmd
20322031
.get_envs()
20332032
.find_map(|(k, v)| (k == "PATH").then_some(v))

src/bootstrap/src/core/build_steps/tool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1334,7 +1334,7 @@ impl Builder<'_> {
13341334
if compiler.host.is_msvc() {
13351335
let curpaths = env::var_os("PATH").unwrap_or_default();
13361336
let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
1337-
for (k, v) in self.cc.borrow()[&compiler.host].env() {
1337+
for (k, v) in self.cc[&compiler.host].env() {
13381338
if k != "PATH" {
13391339
continue;
13401340
}

src/bootstrap/src/core/builder/cargo.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,7 @@ impl Cargo {
278278
self.rustdocflags.arg(&arg);
279279
}
280280

281-
if !builder.config.dry_run()
282-
&& builder.cc.borrow()[&target].args().iter().any(|arg| arg == "-gz")
283-
{
281+
if !builder.config.dry_run() && builder.cc[&target].args().iter().any(|arg| arg == "-gz") {
284282
self.rustflags.arg("-Clink-arg=-gz");
285283
}
286284

src/bootstrap/src/core/builder/mod.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::fmt::{self, Debug, Write};
55
use std::hash::Hash;
66
use std::ops::Deref;
77
use std::path::{Path, PathBuf};
8-
use std::sync::LazyLock;
8+
use std::sync::{LazyLock, OnceLock};
99
use std::time::{Duration, Instant};
1010
use std::{env, fs};
1111

@@ -60,6 +60,9 @@ pub struct Builder<'a> {
6060
/// to do. For example: with `./x check foo bar` we get `paths=["foo",
6161
/// "bar"]`.
6262
pub paths: Vec<PathBuf>,
63+
64+
/// Cached list of submodules from self.build.src.
65+
submodule_paths_cache: OnceLock<Vec<String>>,
6366
}
6467

6568
impl Deref for Builder<'_> {
@@ -687,7 +690,7 @@ impl<'a> ShouldRun<'a> {
687690
///
688691
/// [`path`]: ShouldRun::path
689692
pub fn paths(mut self, paths: &[&str]) -> Self {
690-
let submodules_paths = build_helper::util::parse_gitmodules(&self.builder.src);
693+
let submodules_paths = self.builder.submodule_paths();
691694

692695
self.paths.insert(PathSet::Set(
693696
paths
@@ -1180,6 +1183,7 @@ impl<'a> Builder<'a> {
11801183
stack: RefCell::new(Vec::new()),
11811184
time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
11821185
paths,
1186+
submodule_paths_cache: Default::default(),
11831187
}
11841188
}
11851189

@@ -1510,6 +1514,19 @@ impl<'a> Builder<'a> {
15101514
None
15111515
}
15121516

1517+
/// Updates all submodules, and exits with an error if submodule
1518+
/// management is disabled and the submodule does not exist.
1519+
pub fn require_and_update_all_submodules(&self) {
1520+
for submodule in self.submodule_paths() {
1521+
self.require_submodule(submodule, None);
1522+
}
1523+
}
1524+
1525+
/// Get all submodules from the src directory.
1526+
pub fn submodule_paths(&self) -> &[String] {
1527+
self.submodule_paths_cache.get_or_init(|| build_helper::util::parse_gitmodules(&self.src))
1528+
}
1529+
15131530
/// Ensure that a given step is built, returning its output. This will
15141531
/// cache the step, so it is safe (and good!) to call this as often as
15151532
/// needed to ensure that all dependencies are built.

src/bootstrap/src/lib.rs

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//! also check out the `src/bootstrap/README.md` file for more information.
1818
#![cfg_attr(test, allow(unused))]
1919

20-
use std::cell::{Cell, RefCell};
20+
use std::cell::Cell;
2121
use std::collections::{BTreeSet, HashMap, HashSet};
2222
use std::fmt::Display;
2323
use std::path::{Path, PathBuf};
@@ -189,10 +189,12 @@ pub struct Build {
189189

190190
// Runtime state filled in later on
191191
// C/C++ compilers and archiver for all targets
192-
cc: RefCell<HashMap<TargetSelection, cc::Tool>>,
193-
cxx: RefCell<HashMap<TargetSelection, cc::Tool>>,
194-
ar: RefCell<HashMap<TargetSelection, PathBuf>>,
195-
ranlib: RefCell<HashMap<TargetSelection, PathBuf>>,
192+
cc: HashMap<TargetSelection, cc::Tool>,
193+
cxx: HashMap<TargetSelection, cc::Tool>,
194+
ar: HashMap<TargetSelection, PathBuf>,
195+
ranlib: HashMap<TargetSelection, PathBuf>,
196+
wasi_sdk_path: Option<PathBuf>,
197+
196198
// Miscellaneous
197199
// allow bidirectional lookups: both name -> path and path -> name
198200
crates: HashMap<String, Crate>,
@@ -466,10 +468,11 @@ impl Build {
466468
enzyme_info,
467469
in_tree_llvm_info,
468470
in_tree_gcc_info,
469-
cc: RefCell::new(HashMap::new()),
470-
cxx: RefCell::new(HashMap::new()),
471-
ar: RefCell::new(HashMap::new()),
472-
ranlib: RefCell::new(HashMap::new()),
471+
cc: HashMap::new(),
472+
cxx: HashMap::new(),
473+
ar: HashMap::new(),
474+
ranlib: HashMap::new(),
475+
wasi_sdk_path: env::var_os("WASI_SDK_PATH").map(PathBuf::from),
473476
crates: HashMap::new(),
474477
crate_paths: HashMap::new(),
475478
is_sudo,
@@ -498,7 +501,7 @@ impl Build {
498501
}
499502

500503
build.verbose(|| println!("finding compilers"));
501-
utils::cc_detect::find(&build);
504+
utils::cc_detect::fill_compilers(&mut build);
502505
// When running `setup`, the profile is about to change, so any requirements we have now may
503506
// be different on the next invocation. Don't check for them until the next time x.py is
504507
// run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
@@ -593,14 +596,6 @@ impl Build {
593596
}
594597
}
595598

596-
/// Updates all submodules, and exits with an error if submodule
597-
/// management is disabled and the submodule does not exist.
598-
pub fn require_and_update_all_submodules(&self) {
599-
for submodule in build_helper::util::parse_gitmodules(&self.src) {
600-
self.require_submodule(submodule, None);
601-
}
602-
}
603-
604599
/// If any submodule has been initialized already, sync it unconditionally.
605600
/// This avoids contributors checking in a submodule change by accident.
606601
fn update_existing_submodules(&self) {
@@ -1143,17 +1138,17 @@ impl Build {
11431138
if self.config.dry_run() {
11441139
return PathBuf::new();
11451140
}
1146-
self.cc.borrow()[&target].path().into()
1141+
self.cc[&target].path().into()
11471142
}
11481143

11491144
/// Returns the internal `cc::Tool` for the C compiler.
11501145
fn cc_tool(&self, target: TargetSelection) -> Tool {
1151-
self.cc.borrow()[&target].clone()
1146+
self.cc[&target].clone()
11521147
}
11531148

11541149
/// Returns the internal `cc::Tool` for the C++ compiler.
11551150
fn cxx_tool(&self, target: TargetSelection) -> Tool {
1156-
self.cxx.borrow()[&target].clone()
1151+
self.cxx[&target].clone()
11571152
}
11581153

11591154
/// Returns C flags that `cc-rs` thinks should be enabled for the
@@ -1163,8 +1158,8 @@ impl Build {
11631158
return Vec::new();
11641159
}
11651160
let base = match c {
1166-
CLang::C => self.cc.borrow()[&target].clone(),
1167-
CLang::Cxx => self.cxx.borrow()[&target].clone(),
1161+
CLang::C => self.cc[&target].clone(),
1162+
CLang::Cxx => self.cxx[&target].clone(),
11681163
};
11691164

11701165
// Filter out -O and /O (the optimization flags) that we picked up
@@ -1217,23 +1212,23 @@ impl Build {
12171212
if self.config.dry_run() {
12181213
return None;
12191214
}
1220-
self.ar.borrow().get(&target).cloned()
1215+
self.ar.get(&target).cloned()
12211216
}
12221217

12231218
/// Returns the path to the `ranlib` utility for the target specified.
12241219
fn ranlib(&self, target: TargetSelection) -> Option<PathBuf> {
12251220
if self.config.dry_run() {
12261221
return None;
12271222
}
1228-
self.ranlib.borrow().get(&target).cloned()
1223+
self.ranlib.get(&target).cloned()
12291224
}
12301225

12311226
/// Returns the path to the C++ compiler for the target specified.
12321227
fn cxx(&self, target: TargetSelection) -> Result<PathBuf, String> {
12331228
if self.config.dry_run() {
12341229
return Ok(PathBuf::new());
12351230
}
1236-
match self.cxx.borrow().get(&target) {
1231+
match self.cxx.get(&target) {
12371232
Some(p) => Ok(p.path().into()),
12381233
None => Err(format!("target `{target}` is not configured as a host, only as a target")),
12391234
}
@@ -1250,7 +1245,7 @@ impl Build {
12501245
} else if target.contains("vxworks") {
12511246
// need to use CXX compiler as linker to resolve the exception functions
12521247
// that are only existed in CXX libraries
1253-
Some(self.cxx.borrow()[&target].path().into())
1248+
Some(self.cxx[&target].path().into())
12541249
} else if !self.config.is_host_target(target)
12551250
&& helpers::use_host_linker(target)
12561251
&& !target.is_msvc()

src/bootstrap/src/utils/build_stamp/tests.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,28 @@
11
use std::path::PathBuf;
22

3-
use crate::{BuildStamp, Config, Flags};
3+
use tempfile::TempDir;
44

5-
fn temp_dir() -> PathBuf {
6-
let config =
7-
Config::parse(Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]));
8-
config.tempdir()
9-
}
5+
use crate::{BuildStamp, Config, Flags};
106

117
#[test]
128
#[should_panic(expected = "prefix can not start or end with '.'")]
139
fn test_with_invalid_prefix() {
14-
let dir = temp_dir();
15-
BuildStamp::new(&dir).with_prefix(".invalid");
10+
let dir = TempDir::new().unwrap();
11+
BuildStamp::new(dir.path()).with_prefix(".invalid");
1612
}
1713

1814
#[test]
1915
#[should_panic(expected = "prefix can not start or end with '.'")]
2016
fn test_with_invalid_prefix2() {
21-
let dir = temp_dir();
22-
BuildStamp::new(&dir).with_prefix("invalid.");
17+
let dir = TempDir::new().unwrap();
18+
BuildStamp::new(dir.path()).with_prefix("invalid.");
2319
}
2420

2521
#[test]
2622
fn test_is_up_to_date() {
27-
let dir = temp_dir();
23+
let dir = TempDir::new().unwrap();
2824

29-
let mut build_stamp = BuildStamp::new(&dir).add_stamp("v1.0.0");
25+
let mut build_stamp = BuildStamp::new(dir.path()).add_stamp("v1.0.0");
3026
build_stamp.write().unwrap();
3127

3228
assert!(
@@ -45,9 +41,9 @@ fn test_is_up_to_date() {
4541

4642
#[test]
4743
fn test_with_prefix() {
48-
let dir = temp_dir();
44+
let dir = TempDir::new().unwrap();
4945

50-
let stamp = BuildStamp::new(&dir).add_stamp("v1.0.0");
46+
let stamp = BuildStamp::new(dir.path()).add_stamp("v1.0.0");
5147
assert_eq!(stamp.path.file_name().unwrap(), ".stamp");
5248

5349
let stamp = stamp.with_prefix("test");

src/bootstrap/src/utils/cc_detect.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build {
6161
///
6262
/// This function determines which targets need a C compiler (and, if needed, a C++ compiler)
6363
/// by combining the primary build target, host targets, and any additional targets. For
64-
/// each target, it calls [`find_target`] to configure the necessary compiler tools.
65-
pub fn find(build: &Build) {
64+
/// each target, it calls [`fill_target_compiler`] to configure the necessary compiler tools.
65+
pub fn fill_compilers(build: &mut Build) {
6666
let targets: HashSet<_> = match build.config.cmd {
6767
// We don't need to check cross targets for these commands.
6868
crate::Subcommand::Clean { .. }
@@ -87,7 +87,7 @@ pub fn find(build: &Build) {
8787
};
8888

8989
for target in targets.into_iter() {
90-
find_target(build, target);
90+
fill_target_compiler(build, target);
9191
}
9292
}
9393

@@ -96,7 +96,7 @@ pub fn find(build: &Build) {
9696
/// This function uses both user-specified configuration (from `bootstrap.toml`) and auto-detection
9797
/// logic to determine the correct C/C++ compilers for the target. It also determines the appropriate
9898
/// archiver (`ar`) and sets up additional compilation flags (both handled and unhandled).
99-
pub fn find_target(build: &Build, target: TargetSelection) {
99+
pub fn fill_target_compiler(build: &mut Build, target: TargetSelection) {
100100
let mut cfg = new_cc_build(build, target);
101101
let config = build.config.target_config.get(&target);
102102
if let Some(cc) = config
@@ -113,7 +113,7 @@ pub fn find_target(build: &Build, target: TargetSelection) {
113113
cfg.try_get_archiver().map(|c| PathBuf::from(c.get_program())).ok()
114114
};
115115

116-
build.cc.borrow_mut().insert(target, compiler.clone());
116+
build.cc.insert(target, compiler.clone());
117117
let mut cflags = build.cc_handled_clags(target, CLang::C);
118118
cflags.extend(build.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
119119

@@ -135,7 +135,7 @@ pub fn find_target(build: &Build, target: TargetSelection) {
135135
// for VxWorks, record CXX compiler which will be used in lib.rs:linker()
136136
if cxx_configured || target.contains("vxworks") {
137137
let compiler = cfg.get_compiler();
138-
build.cxx.borrow_mut().insert(target, compiler);
138+
build.cxx.insert(target, compiler);
139139
}
140140

141141
build.verbose(|| println!("CC_{} = {:?}", target.triple, build.cc(target)));
@@ -148,11 +148,11 @@ pub fn find_target(build: &Build, target: TargetSelection) {
148148
}
149149
if let Some(ar) = ar {
150150
build.verbose(|| println!("AR_{} = {ar:?}", target.triple));
151-
build.ar.borrow_mut().insert(target, ar);
151+
build.ar.insert(target, ar);
152152
}
153153

154154
if let Some(ranlib) = config.and_then(|c| c.ranlib.clone()) {
155-
build.ranlib.borrow_mut().insert(target, ranlib);
155+
build.ranlib.insert(target, ranlib);
156156
}
157157
}
158158

@@ -221,7 +221,10 @@ fn default_compiler(
221221
}
222222

223223
t if t.contains("-wasi") => {
224-
let root = PathBuf::from(std::env::var_os("WASI_SDK_PATH")?);
224+
let root = build
225+
.wasi_sdk_path
226+
.as_ref()
227+
.expect("WASI_SDK_PATH mut be configured for a -wasi target");
225228
let compiler = match compiler {
226229
Language::C => format!("{t}-clang"),
227230
Language::CPlusPlus => format!("{t}-clang++"),

0 commit comments

Comments
 (0)