Skip to content

Commit f104b12

Browse files
Change Step to be invoked with a path when in default mode.
Previously, a Step would be able to tell on its own when it was invoked "by-default" (that is, `./x.py test` was called instead of `./x.py test some/path`). This commit replaces that functionality, invoking each Step with each of the paths it has specified as "should be invoked by." For example, if a step calls `path("src/tools/cargo")` and `path("src/doc/cargo")` then it's make_run will be called twice, with "src/tools/cargo" and "src/doc/cargo." This makes it so that default handling logic is in builder, instead of spread across various Steps. However, this meant that some Step specifications needed to be updated, since for example `rustdoc` can be built by `./x.py build src/librustdoc` or `./x.py build src/tools/rustdoc`. A `PathSet` abstraction is added that handles this: now, each Step can not only list `path(...)` but also `paths(&[a, b, ...])` which will make it so that we don't invoke it with each of the individual paths, instead invoking it with the first path in the list (though this shouldn't be depended on). Future work likely consists of implementing a better/easier way for a given Step to work with "any" crate in-tree, especially those that want to run tests, build, or check crates in the std, test, or rustc crate trees. Currently this is rather painful to do as most of the logic is duplicated across should_run and make_run. It seems likely this can be abstracted away into builder somehow.
1 parent 55c36e3 commit f104b12

File tree

7 files changed

+415
-312
lines changed

7 files changed

+415
-312
lines changed

src/bootstrap/builder.rs

+85-40
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ pub struct RunConfig<'a> {
9595
pub builder: &'a Builder<'a>,
9696
pub host: Interned<String>,
9797
pub target: Interned<String>,
98-
pub path: Option<&'a Path>,
98+
pub path: &'a Path,
9999
}
100100

101101
struct StepDescription {
@@ -105,6 +105,28 @@ struct StepDescription {
105105
only_build: bool,
106106
should_run: fn(ShouldRun) -> ShouldRun,
107107
make_run: fn(RunConfig),
108+
name: &'static str,
109+
}
110+
111+
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
112+
struct PathSet {
113+
set: BTreeSet<PathBuf>,
114+
}
115+
116+
impl PathSet {
117+
fn one<P: Into<PathBuf>>(path: P) -> PathSet {
118+
let mut set = BTreeSet::new();
119+
set.insert(path.into());
120+
PathSet { set }
121+
}
122+
123+
fn has(&self, needle: &Path) -> bool {
124+
self.set.iter().any(|p| p.ends_with(needle))
125+
}
126+
127+
fn path(&self) -> &Path {
128+
self.set.iter().next().unwrap()
129+
}
108130
}
109131

110132
impl StepDescription {
@@ -116,30 +138,17 @@ impl StepDescription {
116138
only_build: S::ONLY_BUILD,
117139
should_run: S::should_run,
118140
make_run: S::make_run,
141+
name: unsafe { ::std::intrinsics::type_name::<S>() },
119142
}
120143
}
121144

122-
fn maybe_run(&self, builder: &Builder, should_run: &ShouldRun, path: Option<&Path>) {
123-
if let Some(path) = path {
124-
if builder.config.exclude.iter().any(|e| e == path) {
125-
eprintln!("Skipping {:?} because this path is excluded", path);
126-
return;
127-
} else if !builder.config.exclude.is_empty() {
128-
eprintln!("{:?} not skipped -- not in {:?}", path, builder.config.exclude);
129-
}
130-
} else {
131-
if !should_run.paths.is_empty() {
132-
if should_run.paths.iter().all(|p| builder.config.exclude.contains(&p)) {
133-
eprintln!("Skipping because all of its paths ({:?}) are excluded",
134-
should_run.paths);
135-
return;
136-
} else if should_run.paths.len() > 1 {
137-
for path in &should_run.paths {
138-
self.maybe_run(builder, should_run, Some(path));
139-
}
140-
return;
141-
}
142-
}
145+
fn maybe_run(&self, builder: &Builder, pathset: &PathSet) {
146+
if builder.config.exclude.iter().any(|e| pathset.has(e)) {
147+
eprintln!("Skipping {:?} because it is excluded", pathset);
148+
return;
149+
} else if !builder.config.exclude.is_empty() {
150+
eprintln!("{:?} not skipped for {:?} -- not in {:?}", pathset,
151+
self.name, builder.config.exclude);
143152
}
144153
let build = builder.build;
145154
let hosts = if self.only_build_targets || self.only_build {
@@ -165,7 +174,7 @@ impl StepDescription {
165174
for target in targets {
166175
let run = RunConfig {
167176
builder,
168-
path,
177+
path: pathset.path(),
169178
host: *host,
170179
target: *target,
171180
};
@@ -178,19 +187,28 @@ impl StepDescription {
178187
let should_runs = v.iter().map(|desc| {
179188
(desc.should_run)(ShouldRun::new(builder))
180189
}).collect::<Vec<_>>();
190+
191+
// sanity checks on rules
192+
for (desc, should_run) in v.iter().zip(&should_runs) {
193+
assert!(!should_run.paths.is_empty(),
194+
"{:?} should have at least one pathset", desc.name);
195+
}
196+
181197
if paths.is_empty() {
182198
for (desc, should_run) in v.iter().zip(should_runs) {
183199
if desc.default && should_run.is_really_default {
184-
desc.maybe_run(builder, &should_run, None);
200+
for pathset in &should_run.paths {
201+
desc.maybe_run(builder, pathset);
202+
}
185203
}
186204
}
187205
} else {
188206
for path in paths {
189207
let mut attempted_run = false;
190208
for (desc, should_run) in v.iter().zip(&should_runs) {
191-
if should_run.run(path) {
209+
if let Some(pathset) = should_run.pathset_for_path(path) {
192210
attempted_run = true;
193-
desc.maybe_run(builder, &should_run, Some(path));
211+
desc.maybe_run(builder, pathset);
194212
}
195213
}
196214

@@ -206,7 +224,7 @@ impl StepDescription {
206224
pub struct ShouldRun<'a> {
207225
pub builder: &'a Builder<'a>,
208226
// use a BTreeSet to maintain sort order
209-
paths: BTreeSet<PathBuf>,
227+
paths: BTreeSet<PathSet>,
210228

211229
// If this is a default rule, this is an additional constraint placed on
212230
// it's run. Generally something like compiler docs being enabled.
@@ -227,15 +245,35 @@ impl<'a> ShouldRun<'a> {
227245
self
228246
}
229247

248+
// Unlike `krate` this will create just one pathset. As such, it probably shouldn't actually
249+
// ever be used, but as we transition to having all rules properly handle passing krate(...) by
250+
// actually doing something different for every crate passed.
251+
pub fn all_krates(mut self, name: &str) -> Self {
252+
let mut set = BTreeSet::new();
253+
for krate in self.builder.in_tree_crates(name) {
254+
set.insert(PathBuf::from(&krate.path));
255+
}
256+
self.paths.insert(PathSet { set });
257+
self
258+
}
259+
230260
pub fn krate(mut self, name: &str) -> Self {
231-
for (_, krate_path) in self.builder.crates(name) {
232-
self.paths.insert(t!(env::current_dir()).join(krate_path));
261+
for krate in self.builder.in_tree_crates(name) {
262+
self.paths.insert(PathSet::one(&krate.path));
233263
}
234264
self
235265
}
236266

237-
pub fn path(mut self, path: &str) -> Self {
238-
self.paths.insert(t!(env::current_dir()).join(path));
267+
// single, non-aliased path
268+
pub fn path(self, path: &str) -> Self {
269+
self.paths(&[path])
270+
}
271+
272+
// multiple aliases for the same job
273+
pub fn paths(mut self, paths: &[&str]) -> Self {
274+
self.paths.insert(PathSet {
275+
set: paths.iter().map(PathBuf::from).collect(),
276+
});
239277
self
240278
}
241279

@@ -244,8 +282,8 @@ impl<'a> ShouldRun<'a> {
244282
self
245283
}
246284

247-
fn run(&self, path: &Path) -> bool {
248-
self.paths.iter().any(|p| path.ends_with(p))
285+
fn pathset_for_path(&self, path: &Path) -> Option<&PathSet> {
286+
self.paths.iter().find(|pathset| pathset.has(path))
249287
}
250288
}
251289

@@ -275,11 +313,16 @@ impl<'a> Builder<'a> {
275313
tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy,
276314
native::Llvm, tool::Rustfmt, tool::Miri),
277315
Kind::Check => describe!(check::Std, check::Test, check::Rustc),
278-
Kind::Test => describe!(test::Tidy, test::Bootstrap, test::DefaultCompiletest,
279-
test::HostCompiletest, test::Crate, test::CrateLibrustc, test::Rustdoc,
280-
test::Linkcheck, test::Cargotest, test::Cargo, test::Rls, test::Docs,
281-
test::ErrorIndex, test::Distcheck, test::Rustfmt, test::Miri, test::Clippy,
282-
test::RustdocJS, test::RustdocTheme),
316+
Kind::Test => describe!(test::Tidy, test::Bootstrap, test::Ui, test::RunPass,
317+
test::CompileFail, test::ParseFail, test::RunFail, test::RunPassValgrind,
318+
test::MirOpt, test::Codegen, test::CodegenUnits, test::Incremental, test::Debuginfo,
319+
test::UiFullDeps, test::RunPassFullDeps, test::RunFailFullDeps,
320+
test::CompileFailFullDeps, test::IncrementalFullDeps, test::Rustdoc, test::Pretty,
321+
test::RunPassPretty, test::RunFailPretty, test::RunPassValgrindPretty,
322+
test::RunPassFullDepsPretty, test::RunFailFullDepsPretty, test::RunMake,
323+
test::Crate, test::CrateLibrustc, test::Rustdoc, test::Linkcheck, test::Cargotest,
324+
test::Cargo, test::Rls, test::Docs, test::ErrorIndex, test::Distcheck,
325+
test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme),
283326
Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
284327
Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
285328
doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
@@ -317,8 +360,10 @@ impl<'a> Builder<'a> {
317360
should_run = (desc.should_run)(should_run);
318361
}
319362
let mut help = String::from("Available paths:\n");
320-
for path in should_run.paths {
321-
help.push_str(format!(" ./x.py {} {}\n", subcommand, path.display()).as_str());
363+
for pathset in should_run.paths {
364+
for path in pathset.set {
365+
help.push_str(format!(" ./x.py {} {}\n", subcommand, path.display()).as_str());
366+
}
322367
}
323368
Some(help)
324369
}

src/bootstrap/check.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl Step for Std {
2626
const DEFAULT: bool = true;
2727

2828
fn should_run(run: ShouldRun) -> ShouldRun {
29-
run.path("src/libstd").krate("std")
29+
run.all_krates("std")
3030
}
3131

3232
fn make_run(run: RunConfig) {
@@ -67,7 +67,7 @@ impl Step for Rustc {
6767
const DEFAULT: bool = true;
6868

6969
fn should_run(run: ShouldRun) -> ShouldRun {
70-
run.path("src/librustc").krate("rustc-main")
70+
run.all_krates("rustc-main")
7171
}
7272

7373
fn make_run(run: RunConfig) {
@@ -114,7 +114,7 @@ impl Step for Test {
114114
const DEFAULT: bool = true;
115115

116116
fn should_run(run: ShouldRun) -> ShouldRun {
117-
run.path("src/libtest").krate("test")
117+
run.all_krates("test")
118118
}
119119

120120
fn make_run(run: RunConfig) {

src/bootstrap/compile.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl Step for Std {
4848
const DEFAULT: bool = true;
4949

5050
fn should_run(run: ShouldRun) -> ShouldRun {
51-
run.path("src/libstd").krate("std")
51+
run.all_krates("std")
5252
}
5353

5454
fn make_run(run: RunConfig) {
@@ -320,7 +320,7 @@ impl Step for Test {
320320
const DEFAULT: bool = true;
321321

322322
fn should_run(run: ShouldRun) -> ShouldRun {
323-
run.path("src/libtest").krate("test")
323+
run.all_krates("test")
324324
}
325325

326326
fn make_run(run: RunConfig) {
@@ -436,7 +436,7 @@ impl Step for Rustc {
436436
const DEFAULT: bool = true;
437437

438438
fn should_run(run: ShouldRun) -> ShouldRun {
439-
run.path("src/librustc").krate("rustc-main")
439+
run.all_krates("rustc-main")
440440
}
441441

442442
fn make_run(run: RunConfig) {
@@ -593,7 +593,7 @@ impl Step for CodegenBackend {
593593
const DEFAULT: bool = true;
594594

595595
fn should_run(run: ShouldRun) -> ShouldRun {
596-
run.path("src/librustc_trans")
596+
run.all_krates("rustc_trans")
597597
}
598598

599599
fn make_run(run: RunConfig) {
@@ -828,7 +828,7 @@ impl Step for Assemble {
828828
type Output = Compiler;
829829

830830
fn should_run(run: ShouldRun) -> ShouldRun {
831-
run.path("src/rustc")
831+
run.all_krates("rustc-main")
832832
}
833833

834834
/// Prepare a new compiler from the artifacts in `stage`

src/bootstrap/doc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ impl Step for Std {
429429

430430
fn should_run(run: ShouldRun) -> ShouldRun {
431431
let builder = run.builder;
432-
run.krate("std").default_condition(builder.build.config.docs)
432+
run.all_krates("std").default_condition(builder.build.config.docs)
433433
}
434434

435435
fn make_run(run: RunConfig) {

src/bootstrap/lib.rs

+22-15
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,8 @@
113113
//! More documentation can be found in each respective module below, and you can
114114
//! also check out the `src/bootstrap/README.md` file for more information.
115115
116-
#![deny(warnings)]
117-
#![allow(stable_features)]
118-
#![feature(associated_consts)]
116+
//#![deny(warnings)]
117+
#![feature(core_intrinsics)]
119118

120119
#[macro_use]
121120
extern crate build_helper;
@@ -267,6 +266,18 @@ struct Crate {
267266
bench_step: String,
268267
}
269268

269+
impl Crate {
270+
fn is_local(&self, build: &Build) -> bool {
271+
self.path.starts_with(&build.config.src) &&
272+
!self.path.to_string_lossy().ends_with("_shim")
273+
}
274+
275+
fn local_path(&self, build: &Build) -> PathBuf {
276+
assert!(self.is_local(build));
277+
self.path.strip_prefix(&build.config.src).unwrap().into()
278+
}
279+
}
280+
270281
/// The various "modes" of invoking Cargo.
271282
///
272283
/// These entries currently correspond to the various output directories of the
@@ -949,22 +960,18 @@ impl Build {
949960
}
950961
}
951962

952-
/// Get a list of crates from a root crate.
953-
///
954-
/// Returns Vec<(crate, path to crate, is_root_crate)>
955-
fn crates(&self, root: &str) -> Vec<(Interned<String>, &Path)> {
956-
let interned = INTERNER.intern_string(root.to_owned());
963+
fn in_tree_crates(&self, root: &str) -> Vec<&Crate> {
957964
let mut ret = Vec::new();
958-
let mut list = vec![interned];
965+
let mut list = vec![INTERNER.intern_str(root)];
959966
let mut visited = HashSet::new();
960967
while let Some(krate) = list.pop() {
961968
let krate = &self.crates[&krate];
962-
// If we can't strip prefix, then out-of-tree path
963-
let path = krate.path.strip_prefix(&self.src).unwrap_or(&krate.path);
964-
ret.push((krate.name, path));
965-
for dep in &krate.deps {
966-
if visited.insert(dep) && dep != "build_helper" {
967-
list.push(*dep);
969+
if krate.is_local(self) {
970+
ret.push(krate);
971+
for dep in &krate.deps {
972+
if visited.insert(dep) && dep != "build_helper" {
973+
list.push(*dep);
974+
}
968975
}
969976
}
970977
}

src/bootstrap/native.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,7 @@ impl Step for Llvm {
5151
}
5252

5353
fn make_run(run: RunConfig) {
54-
let emscripten = run.path.map(|p| {
55-
p.ends_with("llvm-emscripten")
56-
}).unwrap_or(false);
54+
let emscripten = run.path.ends_with("llvm-emscripten");
5755
run.builder.ensure(Llvm {
5856
target: run.target,
5957
emscripten,

0 commit comments

Comments
 (0)