Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 65833ed

Browse files
authoredMay 30, 2023
Rollup merge of #111955 - jyn514:step-refactors, r=clubby789
bootstrap: Various Step refactors This ended up being a bunch of only somewhat related changes, sorry 😓 on the bright side, they're all fairly small and well-commented in the commit messages. - Document `ShouldRun::crates` - Switch Steps from crates to crate_or_deps where possible and document why the single remaining place can't switch - Switch doc::{Std, Rustc} to `crate_or_deps` Previously they were using `all_krates` and various hacks to determine which crates to document. Switch them to `crate_or_deps` so `ShouldRun` tells them which crate to document instead of having to guess. This also makes a few other refactors: - Remove the now unused `all_krates`; new code should only use `crate_or_deps`. - Add tests for documenting Std - Remove the unnecessary `run_cargo_rustdoc_for` closure so that we only run cargo once - Give a more helpful error message when documenting a no_std target - Use `builder.msg` in the Steps instead of `builder.info` - Extend `msg` and `description` to work with any subcommand Previously `description` only supported `Testing` and `Benchmarking`, and `msg` gave weird results for `doc` (it would say `Docing`). - Add a `make_run_crates` function and use it Rustc and Std This fixes the panic from the previous commit. - Allow checking individual crates This is useful for profiling metadata generation. This comes very close to removing all_krates, but doesn't quite - there's one last usage left in `doc`. This is fixed in a later commit. - Give a more helpful error when calling `cargo_crates_in_set` for an alias Before: ``` thread 'main' panicked at 'no entry found for key', builder.rs:110:30 ``` After: ``` thread 'main' panicked at 'missing crate for path library', check.rs:89:26 ```
2 parents 0c9f87c + c28ee60 commit 65833ed

File tree

8 files changed

+225
-167
lines changed

8 files changed

+225
-167
lines changed
 

‎src/bootstrap/builder.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,14 @@ impl RunConfig<'_> {
103103
}
104104

105105
/// Return a list of crate names selected by `run.paths`.
106+
#[track_caller]
106107
pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> {
107108
let mut crates = Vec::new();
108109
for krate in &self.paths {
109110
let path = krate.assert_single_path();
110-
let crate_name = self.builder.crate_paths[&path.path];
111+
let Some(crate_name) = self.builder.crate_paths.get(&path.path) else {
112+
panic!("missing crate for path {}", path.path.display())
113+
};
111114
crates.push(crate_name.to_string());
112115
}
113116
INTERNER.intern_list(crates)
@@ -427,25 +430,6 @@ impl<'a> ShouldRun<'a> {
427430
}
428431
}
429432

430-
/// Indicates it should run if the command-line selects the given crate or
431-
/// any of its (local) dependencies.
432-
///
433-
/// Compared to `krate`, this treats the dependencies as aliases for the
434-
/// same job. Generally it is preferred to use `krate`, and treat each
435-
/// individual path separately. For example `./x.py test src/liballoc`
436-
/// (which uses `krate`) will test just `liballoc`. However, `./x.py check
437-
/// src/liballoc` (which uses `all_krates`) will check all of `libtest`.
438-
/// `all_krates` should probably be removed at some point.
439-
pub fn all_krates(mut self, name: &str) -> Self {
440-
let mut set = BTreeSet::new();
441-
for krate in self.builder.in_tree_crates(name, None) {
442-
let path = krate.local_path(self.builder);
443-
set.insert(TaskPath { path, kind: Some(self.kind) });
444-
}
445-
self.paths.insert(PathSet::Set(set));
446-
self
447-
}
448-
449433
/// Indicates it should run if the command-line selects the given crate or
450434
/// any of its (local) dependencies.
451435
///
@@ -458,6 +442,8 @@ impl<'a> ShouldRun<'a> {
458442
/// Indicates it should run if the command-line selects any of the given crates.
459443
///
460444
/// `make_run` will be called a single time with all matching command-line paths.
445+
///
446+
/// Prefer [`ShouldRun::crate_or_deps`] to this function where possible.
461447
pub(crate) fn crates(mut self, crates: Vec<&Crate>) -> Self {
462448
for krate in crates {
463449
let path = krate.local_path(self.builder);
@@ -487,7 +473,15 @@ impl<'a> ShouldRun<'a> {
487473
self.paths(&[path])
488474
}
489475

490-
// multiple aliases for the same job
476+
/// Multiple aliases for the same job.
477+
///
478+
/// This differs from [`path`] in that multiple calls to path will end up calling `make_run`
479+
/// multiple times, whereas a single call to `paths` will only ever generate a single call to
480+
/// `paths`.
481+
///
482+
/// This is analogous to `all_krates`, although `all_krates` is gone now. Prefer [`path`] where possible.
483+
///
484+
/// [`path`]: ShouldRun::path
491485
pub fn paths(mut self, paths: &[&str]) -> Self {
492486
static SUBMODULES_PATHS: OnceCell<Vec<String>> = OnceCell::new();
493487

@@ -641,12 +635,16 @@ impl Kind {
641635
}
642636
}
643637

644-
pub fn test_description(&self) -> &'static str {
638+
pub fn description(&self) -> String {
645639
match self {
646640
Kind::Test => "Testing",
647641
Kind::Bench => "Benchmarking",
648-
_ => panic!("not a test command: {}!", self.as_str()),
642+
Kind::Doc => "Documenting",
643+
Kind::Run => "Running",
644+
Kind::Suggest => "Suggesting",
645+
_ => return format!("{self:?}"),
649646
}
647+
.to_owned()
650648
}
651649
}
652650

‎src/bootstrap/builder/tests.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::*;
22
use crate::config::{Config, DryRun, TargetSelection};
3+
use crate::doc::DocumentationFormat;
34
use std::thread;
45

56
fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
@@ -66,6 +67,16 @@ macro_rules! std {
6667
};
6768
}
6869

70+
macro_rules! doc_std {
71+
($host:ident => $target:ident, stage = $stage:literal) => {
72+
doc::Std::new(
73+
$stage,
74+
TargetSelection::from_user(stringify!($target)),
75+
DocumentationFormat::HTML,
76+
)
77+
};
78+
}
79+
6980
macro_rules! rustc {
7081
($host:ident => $target:ident, stage = $stage:literal) => {
7182
compile::Rustc::new(
@@ -144,6 +155,9 @@ fn alias_and_path_for_library() {
144155
first(cache.all::<compile::Std>()),
145156
&[std!(A => A, stage = 0), std!(A => A, stage = 1)]
146157
);
158+
159+
let mut cache = run_build(&["library".into(), "core".into()], configure("doc", &["A"], &["A"]));
160+
assert_eq!(first(cache.all::<doc::Std>()), &[doc_std!(A => A, stage = 0)]);
147161
}
148162

149163
#[test]

‎src/bootstrap/check.rs

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
//! Implementation of compiling the compiler and standard library, in "check"-based modes.
22
3-
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
3+
use crate::builder::{crate_description, Builder, Kind, RunConfig, ShouldRun, Step};
44
use crate::cache::Interned;
5-
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
5+
use crate::compile::{
6+
add_to_sysroot, make_run_crates, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo,
7+
};
68
use crate::config::TargetSelection;
79
use crate::tool::{prepare_tool_cargo, SourceType};
810
use crate::INTERNER;
@@ -12,6 +14,12 @@ use std::path::{Path, PathBuf};
1214
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1315
pub struct Std {
1416
pub target: TargetSelection,
17+
/// Whether to build only a subset of crates.
18+
///
19+
/// This shouldn't be used from other steps; see the comment on [`compile::Rustc`].
20+
///
21+
/// [`compile::Rustc`]: crate::compile::Rustc
22+
crates: Interned<Vec<String>>,
1523
}
1624

1725
/// Returns args for the subcommand itself (not for cargo)
@@ -66,16 +74,23 @@ fn cargo_subcommand(kind: Kind) -> &'static str {
6674
}
6775
}
6876

77+
impl Std {
78+
pub fn new(target: TargetSelection) -> Self {
79+
Self { target, crates: INTERNER.intern_list(vec![]) }
80+
}
81+
}
82+
6983
impl Step for Std {
7084
type Output = ();
7185
const DEFAULT: bool = true;
7286

7387
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
74-
run.all_krates("sysroot").path("library")
88+
run.crate_or_deps("sysroot").path("library")
7589
}
7690

7791
fn make_run(run: RunConfig<'_>) {
78-
run.builder.ensure(Std { target: run.target });
92+
let crates = make_run_crates(&run, "library");
93+
run.builder.ensure(Std { target: run.target, crates });
7994
}
8095

8196
fn run(self, builder: &Builder<'_>) {
@@ -97,7 +112,14 @@ impl Step for Std {
97112
cargo.arg("--lib");
98113
}
99114

100-
let _guard = builder.msg_check("library artifacts", target);
115+
for krate in &*self.crates {
116+
cargo.arg("-p").arg(krate);
117+
}
118+
119+
let _guard = builder.msg_check(
120+
format_args!("library artifacts{}", crate_description(&self.crates)),
121+
target,
122+
);
101123
run_cargo(
102124
builder,
103125
cargo,
@@ -117,7 +139,8 @@ impl Step for Std {
117139
}
118140

119141
// don't run on std twice with x.py clippy
120-
if builder.kind == Kind::Clippy {
142+
// don't check test dependencies if we haven't built libtest
143+
if builder.kind == Kind::Clippy || !self.crates.is_empty() {
121144
return;
122145
}
123146

@@ -147,8 +170,8 @@ impl Step for Std {
147170
// Explicitly pass -p for all dependencies krates -- this will force cargo
148171
// to also check the tests/benches/examples for these crates, rather
149172
// than just the leaf crate.
150-
for krate in builder.in_tree_crates("test", Some(target)) {
151-
cargo.arg("-p").arg(krate.name);
173+
for krate in &*self.crates {
174+
cargo.arg("-p").arg(krate);
152175
}
153176

154177
let _guard = builder.msg_check("library test/bench/example targets", target);
@@ -167,6 +190,22 @@ impl Step for Std {
167190
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
168191
pub struct Rustc {
169192
pub target: TargetSelection,
193+
/// Whether to build only a subset of crates.
194+
///
195+
/// This shouldn't be used from other steps; see the comment on [`compile::Rustc`].
196+
///
197+
/// [`compile::Rustc`]: crate::compile::Rustc
198+
crates: Interned<Vec<String>>,
199+
}
200+
201+
impl Rustc {
202+
pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
203+
let mut crates = vec![];
204+
for krate in builder.in_tree_crates("rustc-main", None) {
205+
crates.push(krate.name.to_string());
206+
}
207+
Self { target, crates: INTERNER.intern_list(crates) }
208+
}
170209
}
171210

172211
impl Step for Rustc {
@@ -175,11 +214,12 @@ impl Step for Rustc {
175214
const DEFAULT: bool = true;
176215

177216
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
178-
run.all_krates("rustc-main").path("compiler")
217+
run.crate_or_deps("rustc-main").path("compiler")
179218
}
180219

181220
fn make_run(run: RunConfig<'_>) {
182-
run.builder.ensure(Rustc { target: run.target });
221+
let crates = make_run_crates(&run, "compiler");
222+
run.builder.ensure(Rustc { target: run.target, crates });
183223
}
184224

185225
/// Builds the compiler.
@@ -200,7 +240,7 @@ impl Step for Rustc {
200240
builder.ensure(crate::compile::Std::new(compiler, compiler.host));
201241
builder.ensure(crate::compile::Std::new(compiler, target));
202242
} else {
203-
builder.ensure(Std { target });
243+
builder.ensure(Std::new(target));
204244
}
205245

206246
let mut cargo = builder.cargo(
@@ -218,14 +258,17 @@ impl Step for Rustc {
218258
cargo.arg("--all-targets");
219259
}
220260

221-
// Explicitly pass -p for all compiler krates -- this will force cargo
261+
// Explicitly pass -p for all compiler crates -- this will force cargo
222262
// to also check the tests/benches/examples for these crates, rather
223263
// than just the leaf crate.
224-
for krate in builder.in_tree_crates("rustc-main", Some(target)) {
225-
cargo.arg("-p").arg(krate.name);
264+
for krate in &*self.crates {
265+
cargo.arg("-p").arg(krate);
226266
}
227267

228-
let _guard = builder.msg_check("compiler artifacts", target);
268+
let _guard = builder.msg_check(
269+
format_args!("compiler artifacts{}", crate_description(&self.crates)),
270+
target,
271+
);
229272
run_cargo(
230273
builder,
231274
cargo,
@@ -268,7 +311,7 @@ impl Step for CodegenBackend {
268311
let target = self.target;
269312
let backend = self.backend;
270313

271-
builder.ensure(Rustc { target });
314+
builder.ensure(Rustc::new(target, builder));
272315

273316
let mut cargo = builder.cargo(
274317
compiler,
@@ -318,7 +361,7 @@ impl Step for RustAnalyzer {
318361
let compiler = builder.compiler(builder.top_stage, builder.config.build);
319362
let target = self.target;
320363

321-
builder.ensure(Std { target });
364+
builder.ensure(Std::new(target));
322365

323366
let mut cargo = prepare_tool_cargo(
324367
builder,
@@ -386,7 +429,7 @@ macro_rules! tool_check_step {
386429
let compiler = builder.compiler(builder.top_stage, builder.config.build);
387430
let target = self.target;
388431

389-
builder.ensure(Rustc { target });
432+
builder.ensure(Rustc::new(target, builder));
390433

391434
let mut cargo = prepare_tool_cargo(
392435
builder,

‎src/bootstrap/compile.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,17 @@ impl Std {
4848
}
4949
}
5050

51+
/// Given an `alias` selected by the `Step` and the paths passed on the command line,
52+
/// return a list of the crates that should be built.
53+
///
54+
/// Normally, people will pass *just* `library` if they pass it.
55+
/// But it's possible (although strange) to pass something like `library std core`.
56+
/// Build all crates anyway, as if they hadn't passed the other args.
57+
pub(crate) fn make_run_crates(run: &RunConfig<'_>, alias: &str) -> Interned<Vec<String>> {
58+
let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias));
59+
if has_alias { Default::default() } else { run.cargo_crates_in_set() }
60+
}
61+
5162
impl Step for Std {
5263
type Output = ();
5364
const DEFAULT: bool = true;
@@ -62,16 +73,10 @@ impl Step for Std {
6273
}
6374

6475
fn make_run(run: RunConfig<'_>) {
65-
// Normally, people will pass *just* library if they pass it.
66-
// But it's possible (although strange) to pass something like `library std core`.
67-
// Build all crates anyway, as if they hadn't passed the other args.
68-
let has_library =
69-
run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
70-
let crates = if has_library { Default::default() } else { run.cargo_crates_in_set() };
7176
run.builder.ensure(Std {
7277
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
7378
target: run.target,
74-
crates,
79+
crates: make_run_crates(&run, "library"),
7580
});
7681
}
7782

@@ -615,6 +620,8 @@ impl Step for Rustc {
615620
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
616621
let mut crates = run.builder.in_tree_crates("rustc-main", None);
617622
for (i, krate) in crates.iter().enumerate() {
623+
// We can't allow `build rustc` as an alias for this Step, because that's reserved by `Assemble`.
624+
// Ideally Assemble would use `build compiler` instead, but that seems too confusing to be worth the breaking change.
618625
if krate.name == "rustc-main" {
619626
crates.swap_remove(i);
620627
break;

‎src/bootstrap/dist.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,7 @@ impl Step for JsonDocs {
106106
/// Builds the `rust-docs-json` installer component.
107107
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
108108
let host = self.host;
109-
builder.ensure(crate::doc::Std {
110-
stage: builder.top_stage,
111-
target: host,
112-
format: DocumentationFormat::JSON,
113-
});
109+
builder.ensure(crate::doc::Std::new(builder.top_stage, host, DocumentationFormat::JSON));
114110

115111
let dest = "share/doc/rust/json";
116112

‎src/bootstrap/doc.rs

Lines changed: 105 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
//! Everything here is basically just a shim around calling either `rustbook` or
88
//! `rustdoc`.
99
10-
use std::ffi::OsStr;
1110
use std::fs;
1211
use std::io;
1312
use std::path::{Path, PathBuf};
@@ -16,6 +15,7 @@ use crate::builder::crate_description;
1615
use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
1716
use crate::cache::{Interned, INTERNER};
1817
use crate::compile;
18+
use crate::compile::make_run_crates;
1919
use crate::config::{Config, TargetSelection};
2020
use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
2121
use crate::util::{symlink_dir, t, up_to_date};
@@ -87,15 +87,6 @@ book!(
8787
StyleGuide, "src/doc/style-guide", "style-guide";
8888
);
8989

90-
// "library/std" -> ["library", "std"]
91-
//
92-
// Used for deciding whether a particular step is one requested by the user on
93-
// the `x.py doc` command line, which determines whether `--open` will open that
94-
// page.
95-
pub(crate) fn components_simplified(path: &PathBuf) -> Vec<&str> {
96-
path.iter().map(|component| component.to_str().unwrap_or("???")).collect()
97-
}
98-
9990
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
10091
pub struct UnstableBook {
10192
target: TargetSelection,
@@ -425,11 +416,18 @@ impl Step for SharedAssets {
425416
}
426417
}
427418

428-
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
419+
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
429420
pub struct Std {
430421
pub stage: u32,
431422
pub target: TargetSelection,
432423
pub format: DocumentationFormat,
424+
crates: Interned<Vec<String>>,
425+
}
426+
427+
impl Std {
428+
pub(crate) fn new(stage: u32, target: TargetSelection, format: DocumentationFormat) -> Self {
429+
Std { stage, target, format, crates: INTERNER.intern_list(vec![]) }
430+
}
433431
}
434432

435433
impl Step for Std {
@@ -438,7 +436,7 @@ impl Step for Std {
438436

439437
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
440438
let builder = run.builder;
441-
run.all_krates("sysroot").path("library").default_condition(builder.config.docs)
439+
run.crate_or_deps("sysroot").path("library").default_condition(builder.config.docs)
442440
}
443441

444442
fn make_run(run: RunConfig<'_>) {
@@ -450,14 +448,15 @@ impl Step for Std {
450448
} else {
451449
DocumentationFormat::HTML
452450
},
451+
crates: make_run_crates(&run, "library"),
453452
});
454453
}
455454

456455
/// Compile all standard library documentation.
457456
///
458457
/// This will generate all documentation for the standard library and its
459458
/// dependencies. This is largely just a wrapper around `cargo doc`.
460-
fn run(self, builder: &Builder<'_>) {
459+
fn run(mut self, builder: &Builder<'_>) {
461460
let stage = self.stage;
462461
let target = self.target;
463462
let out = match self.format {
@@ -471,41 +470,24 @@ impl Step for Std {
471470
builder.ensure(SharedAssets { target: self.target });
472471
}
473472

474-
let index_page = builder.src.join("src/doc/index.md").into_os_string();
473+
let index_page = builder
474+
.src
475+
.join("src/doc/index.md")
476+
.into_os_string()
477+
.into_string()
478+
.expect("non-utf8 paths are unsupported");
475479
let mut extra_args = match self.format {
476-
DocumentationFormat::HTML => vec![
477-
OsStr::new("--markdown-css"),
478-
OsStr::new("rust.css"),
479-
OsStr::new("--markdown-no-toc"),
480-
OsStr::new("--index-page"),
481-
&index_page,
482-
],
483-
DocumentationFormat::JSON => vec![OsStr::new("--output-format"), OsStr::new("json")],
480+
DocumentationFormat::HTML => {
481+
vec!["--markdown-css", "rust.css", "--markdown-no-toc", "--index-page", &index_page]
482+
}
483+
DocumentationFormat::JSON => vec!["--output-format", "json"],
484484
};
485485

486486
if !builder.config.docs_minification {
487-
extra_args.push(OsStr::new("--disable-minification"));
487+
extra_args.push("--disable-minification");
488488
}
489489

490-
let requested_crates = builder
491-
.paths
492-
.iter()
493-
.map(components_simplified)
494-
.filter_map(|path| {
495-
if path.len() >= 2 && path.get(0) == Some(&"library") {
496-
// single crate
497-
Some(path[1].to_owned())
498-
} else if !path.is_empty() {
499-
// ??
500-
Some(path[0].to_owned())
501-
} else {
502-
// all library crates
503-
None
504-
}
505-
})
506-
.collect::<Vec<_>>();
507-
508-
doc_std(builder, self.format, stage, target, &out, &extra_args, &requested_crates);
490+
doc_std(builder, self.format, stage, target, &out, &extra_args, &self.crates);
509491

510492
// Don't open if the format is json
511493
if let DocumentationFormat::JSON = self.format {
@@ -514,7 +496,11 @@ impl Step for Std {
514496

515497
// Look for library/std, library/core etc in the `x.py doc` arguments and
516498
// open the corresponding rendered docs.
517-
for requested_crate in requested_crates {
499+
if self.crates.is_empty() {
500+
self.crates = INTERNER.intern_list(vec!["library".to_owned()]);
501+
};
502+
503+
for requested_crate in &*self.crates {
518504
if requested_crate == "library" {
519505
// For `x.py doc library --open`, open `std` by default.
520506
let index = out.join("std").join("index.html");
@@ -538,7 +524,7 @@ impl Step for Std {
538524
/// or remote link.
539525
const STD_PUBLIC_CRATES: [&str; 5] = ["core", "alloc", "std", "proc_macro", "test"];
540526

541-
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
527+
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
542528
pub enum DocumentationFormat {
543529
HTML,
544530
JSON,
@@ -563,24 +549,22 @@ fn doc_std(
563549
stage: u32,
564550
target: TargetSelection,
565551
out: &Path,
566-
extra_args: &[&OsStr],
552+
extra_args: &[&str],
567553
requested_crates: &[String],
568554
) {
569-
builder.info(&format!(
570-
"Documenting{} stage{} library ({}) in {} format",
571-
crate_description(requested_crates),
572-
stage,
573-
target,
574-
format.as_str()
575-
));
576555
if builder.no_std(target) == Some(true) {
577556
panic!(
578557
"building std documentation for no_std target {target} is not supported\n\
579-
Set `docs = false` in the config to disable documentation."
558+
Set `docs = false` in the config to disable documentation, or pass `--exclude doc::library`."
580559
);
581560
}
561+
582562
let compiler = builder.compiler(stage, builder.config.build);
583563

564+
let description =
565+
format!("library{} in {} format", crate_description(&requested_crates), format.as_str());
566+
let _guard = builder.msg(Kind::Doc, stage, &description, compiler.host, target);
567+
584568
let target_doc_dir_name = if format == DocumentationFormat::JSON { "json-doc" } else { "doc" };
585569
let target_dir =
586570
builder.stage_out(compiler, Mode::Std).join(target.triple).join(target_doc_dir_name);
@@ -590,42 +574,71 @@ fn doc_std(
590574
// as a function parameter.
591575
let out_dir = target_dir.join(target.triple).join("doc");
592576

593-
let run_cargo_rustdoc_for = |package: &str| {
594-
let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc");
595-
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
596-
cargo
597-
.arg("--target-dir")
598-
.arg(&*target_dir.to_string_lossy())
599-
.arg("-p")
600-
.arg(package)
601-
.arg("-Zskip-rustdoc-fingerprint")
602-
.arg("--")
603-
.arg("-Z")
604-
.arg("unstable-options")
605-
.arg("--resource-suffix")
606-
.arg(&builder.version)
607-
.args(extra_args);
608-
if builder.config.library_docs_private_items {
609-
cargo.arg("--document-private-items").arg("--document-hidden-items");
610-
}
611-
builder.run(&mut cargo.into());
577+
let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "doc");
578+
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
579+
cargo
580+
.arg("--no-deps")
581+
.arg("--target-dir")
582+
.arg(&*target_dir.to_string_lossy())
583+
.arg("-Zskip-rustdoc-fingerprint")
584+
.rustdocflag("-Z")
585+
.rustdocflag("unstable-options")
586+
.rustdocflag("--resource-suffix")
587+
.rustdocflag(&builder.version);
588+
for arg in extra_args {
589+
cargo.rustdocflag(arg);
590+
}
591+
592+
if builder.config.library_docs_private_items {
593+
cargo.rustdocflag("--document-private-items").rustdocflag("--document-hidden-items");
594+
}
595+
596+
// HACK: because we use `--manifest-path library/sysroot/Cargo.toml`, cargo thinks we only want to document that specific crate, not its dependencies.
597+
// Override its default.
598+
let built_crates = if requested_crates.is_empty() {
599+
builder
600+
.in_tree_crates("sysroot", None)
601+
.into_iter()
602+
.map(|krate| krate.name.to_string())
603+
.collect()
604+
} else {
605+
requested_crates.to_vec()
612606
};
613607

614-
for krate in STD_PUBLIC_CRATES {
615-
run_cargo_rustdoc_for(krate);
616-
if requested_crates.iter().any(|p| p == krate) {
617-
// No need to document more of the libraries if we have the one we want.
618-
break;
619-
}
608+
for krate in built_crates {
609+
cargo.arg("-p").arg(krate);
620610
}
621611

612+
builder.run(&mut cargo.into());
622613
builder.cp_r(&out_dir, &out);
623614
}
624615

625616
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
626617
pub struct Rustc {
627618
pub stage: u32,
628619
pub target: TargetSelection,
620+
crates: Interned<Vec<String>>,
621+
}
622+
623+
impl Rustc {
624+
pub(crate) fn new(stage: u32, target: TargetSelection, builder: &Builder<'_>) -> Self {
625+
// Find dependencies for top level crates.
626+
let root_crates = vec![
627+
INTERNER.intern_str("rustc_driver"),
628+
INTERNER.intern_str("rustc_codegen_llvm"),
629+
INTERNER.intern_str("rustc_codegen_ssa"),
630+
];
631+
let crates: Vec<_> = root_crates
632+
.iter()
633+
.flat_map(|krate| {
634+
builder
635+
.in_tree_crates(krate, Some(target))
636+
.into_iter()
637+
.map(|krate| krate.name.to_string())
638+
})
639+
.collect();
640+
Self { stage, target, crates: INTERNER.intern_list(crates) }
641+
}
629642
}
630643

631644
impl Step for Rustc {
@@ -641,7 +654,11 @@ impl Step for Rustc {
641654
}
642655

643656
fn make_run(run: RunConfig<'_>) {
644-
run.builder.ensure(Rustc { stage: run.builder.top_stage, target: run.target });
657+
run.builder.ensure(Rustc {
658+
stage: run.builder.top_stage,
659+
target: run.target,
660+
crates: make_run_crates(&run, "compiler"),
661+
});
645662
}
646663

647664
/// Generates compiler documentation.
@@ -654,15 +671,6 @@ impl Step for Rustc {
654671
let stage = self.stage;
655672
let target = self.target;
656673

657-
let paths = builder
658-
.paths
659-
.iter()
660-
.filter(|path| {
661-
let components = components_simplified(path);
662-
components.len() >= 2 && components[0] == "compiler"
663-
})
664-
.collect::<Vec<_>>();
665-
666674
// This is the intended out directory for compiler documentation.
667675
let out = builder.compiler_doc_out(target);
668676
t!(fs::create_dir_all(&out));
@@ -672,7 +680,13 @@ impl Step for Rustc {
672680
let compiler = builder.compiler(stage, builder.config.build);
673681
builder.ensure(compile::Std::new(compiler, builder.config.build));
674682

675-
builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
683+
let _guard = builder.msg(
684+
Kind::Doc,
685+
stage,
686+
&format!("compiler{}", crate_description(&self.crates)),
687+
compiler.host,
688+
target,
689+
);
676690

677691
// This uses a shared directory so that librustdoc documentation gets
678692
// correctly built and merged with the rustc documentation. This is
@@ -710,22 +724,8 @@ impl Step for Rustc {
710724
cargo.rustdocflag("--extern-html-root-url");
711725
cargo.rustdocflag("ena=https://docs.rs/ena/latest/");
712726

713-
let root_crates = if paths.is_empty() {
714-
vec![
715-
INTERNER.intern_str("rustc_driver"),
716-
INTERNER.intern_str("rustc_codegen_llvm"),
717-
INTERNER.intern_str("rustc_codegen_ssa"),
718-
]
719-
} else {
720-
paths.into_iter().map(|p| builder.crate_paths[p]).collect()
721-
};
722-
// Find dependencies for top level crates.
723-
let compiler_crates = root_crates.iter().flat_map(|krate| {
724-
builder.in_tree_crates(krate, Some(target)).into_iter().map(|krate| krate.name)
725-
});
726-
727727
let mut to_open = None;
728-
for krate in compiler_crates {
728+
for krate in &*self.crates {
729729
// Create all crate output directories first to make sure rustdoc uses
730730
// relative links.
731731
// FIXME: Cargo should probably do this itself.
@@ -785,7 +785,7 @@ macro_rules! tool_doc {
785785

786786
if true $(&& $rustc_tool)? {
787787
// Build rustc docs so that we generate relative links.
788-
builder.ensure(Rustc { stage, target });
788+
builder.ensure(Rustc::new(stage, target, builder));
789789

790790
// Rustdoc needs the rustc sysroot available to build.
791791
// FIXME: is there a way to only ensure `check::Rustc` here? Last time I tried it failed

‎src/bootstrap/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,8 +1020,8 @@ impl Build {
10201020
host: impl Into<Option<TargetSelection>>,
10211021
target: impl Into<Option<TargetSelection>>,
10221022
) -> Option<gha::Group> {
1023-
let action = action.into();
1024-
let msg = |fmt| format!("{action:?}ing stage{stage} {what}{fmt}");
1023+
let action = action.into().description();
1024+
let msg = |fmt| format!("{action} stage{stage} {what}{fmt}");
10251025
let msg = if let Some(target) = target.into() {
10261026
let host = host.into().unwrap();
10271027
if host == target {

‎src/bootstrap/test.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ impl Step for CrateBootstrap {
101101
);
102102
builder.info(&format!(
103103
"{} {} stage0 ({})",
104-
builder.kind.test_description(),
104+
builder.kind.description(),
105105
path,
106106
bootstrap_host,
107107
));
@@ -220,7 +220,7 @@ impl Step for HtmlCheck {
220220
}
221221
// Ensure that a few different kinds of documentation are available.
222222
builder.default_doc(&[]);
223-
builder.ensure(crate::doc::Rustc { target: self.target, stage: builder.top_stage });
223+
builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder));
224224

225225
try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)));
226226
}
@@ -886,11 +886,11 @@ impl Step for RustdocJSStd {
886886
command.arg("--test-file").arg(path);
887887
}
888888
}
889-
builder.ensure(crate::doc::Std {
890-
target: self.target,
891-
stage: builder.top_stage,
892-
format: DocumentationFormat::HTML,
893-
});
889+
builder.ensure(crate::doc::Std::new(
890+
builder.top_stage,
891+
self.target,
892+
DocumentationFormat::HTML,
893+
));
894894
builder.run(&mut command);
895895
} else {
896896
builder.info("No nodejs found, skipping \"tests/rustdoc-js-std\" tests");

0 commit comments

Comments
 (0)
Please sign in to comment.