Skip to content

Commit 58e18dd

Browse files
committed
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`
1 parent cb4b7f6 commit 58e18dd

File tree

5 files changed

+100
-124
lines changed

5 files changed

+100
-124
lines changed

src/bootstrap/builder.rs

-19
Original file line numberDiff line numberDiff line change
@@ -430,25 +430,6 @@ impl<'a> ShouldRun<'a> {
430430
}
431431
}
432432

433-
/// Indicates it should run if the command-line selects the given crate or
434-
/// any of its (local) dependencies.
435-
///
436-
/// Compared to `krate`, this treats the dependencies as aliases for the
437-
/// same job. Generally it is preferred to use `krate`, and treat each
438-
/// individual path separately. For example `./x.py test src/liballoc`
439-
/// (which uses `krate`) will test just `liballoc`. However, `./x.py check
440-
/// src/liballoc` (which uses `all_krates`) will check all of `libtest`.
441-
/// `all_krates` should probably be removed at some point.
442-
pub fn all_krates(mut self, name: &str) -> Self {
443-
let mut set = BTreeSet::new();
444-
for krate in self.builder.in_tree_crates(name, None) {
445-
let path = krate.local_path(self.builder);
446-
set.insert(TaskPath { path, kind: Some(self.kind) });
447-
}
448-
self.paths.insert(PathSet::Set(set));
449-
self
450-
}
451-
452433
/// Indicates it should run if the command-line selects the given crate or
453434
/// any of its (local) dependencies.
454435
///

src/bootstrap/builder/tests.rs

+14
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/dist.rs

+1-5
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

+79-94
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::builder::crate_description;
1616
use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
1717
use crate::cache::{Interned, INTERNER};
1818
use crate::compile;
19+
use crate::compile::make_run_crates;
1920
use crate::config::{Config, TargetSelection};
2021
use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
2122
use crate::util::{symlink_dir, t, up_to_date};
@@ -87,15 +88,6 @@ book!(
8788
StyleGuide, "src/doc/style-guide", "style-guide";
8889
);
8990

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-
9991
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
10092
pub struct UnstableBook {
10193
target: TargetSelection,
@@ -425,11 +417,18 @@ impl Step for SharedAssets {
425417
}
426418
}
427419

428-
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
420+
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
429421
pub struct Std {
430422
pub stage: u32,
431423
pub target: TargetSelection,
432424
pub format: DocumentationFormat,
425+
crates: Interned<Vec<String>>,
426+
}
427+
428+
impl Std {
429+
pub(crate) fn new(stage: u32, target: TargetSelection, format: DocumentationFormat) -> Self {
430+
Std { stage, target, format, crates: INTERNER.intern_list(vec![]) }
431+
}
433432
}
434433

435434
impl Step for Std {
@@ -438,7 +437,7 @@ impl Step for Std {
438437

439438
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
440439
let builder = run.builder;
441-
run.all_krates("sysroot").path("library").default_condition(builder.config.docs)
440+
run.crate_or_deps("sysroot").path("library").default_condition(builder.config.docs)
442441
}
443442

444443
fn make_run(run: RunConfig<'_>) {
@@ -450,14 +449,15 @@ impl Step for Std {
450449
} else {
451450
DocumentationFormat::HTML
452451
},
452+
crates: make_run_crates(&run, "library"),
453453
});
454454
}
455455

456456
/// Compile all standard library documentation.
457457
///
458458
/// This will generate all documentation for the standard library and its
459459
/// dependencies. This is largely just a wrapper around `cargo doc`.
460-
fn run(self, builder: &Builder<'_>) {
460+
fn run(mut self, builder: &Builder<'_>) {
461461
let stage = self.stage;
462462
let target = self.target;
463463
let out = match self.format {
@@ -487,25 +487,7 @@ impl Step for Std {
487487
extra_args.push(OsStr::new("--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,
@@ -566,21 +552,19 @@ fn doc_std(
566552
extra_args: &[&OsStr],
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,56 @@ 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());
612-
};
577+
let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc");
578+
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
579+
cargo.arg("--target-dir").arg(&*target_dir.to_string_lossy()).arg("-Zskip-rustdoc-fingerprint");
613580

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-
}
581+
for krate in requested_crates {
582+
cargo.arg("-p").arg(krate);
620583
}
621584

585+
cargo
586+
.arg("--")
587+
.arg("-Z")
588+
.arg("unstable-options")
589+
.arg("--resource-suffix")
590+
.arg(&builder.version)
591+
.args(extra_args);
592+
593+
if builder.config.library_docs_private_items {
594+
cargo.arg("--document-private-items").arg("--document-hidden-items");
595+
}
596+
597+
builder.run(&mut cargo.into());
622598
builder.cp_r(&out_dir, &out);
623599
}
624600

625601
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
626602
pub struct Rustc {
627603
pub stage: u32,
628604
pub target: TargetSelection,
605+
crates: Interned<Vec<String>>,
606+
}
607+
608+
impl Rustc {
609+
pub(crate) fn new(stage: u32, target: TargetSelection, builder: &Builder<'_>) -> Self {
610+
// Find dependencies for top level crates.
611+
let root_crates = vec![
612+
INTERNER.intern_str("rustc_driver"),
613+
INTERNER.intern_str("rustc_codegen_llvm"),
614+
INTERNER.intern_str("rustc_codegen_ssa"),
615+
];
616+
let crates: Vec<_> = root_crates
617+
.iter()
618+
.flat_map(|krate| {
619+
builder
620+
.in_tree_crates(krate, Some(target))
621+
.into_iter()
622+
.map(|krate| krate.name.to_string())
623+
})
624+
.collect();
625+
Self { stage, target, crates: INTERNER.intern_list(crates) }
626+
}
629627
}
630628

631629
impl Step for Rustc {
@@ -641,7 +639,11 @@ impl Step for Rustc {
641639
}
642640

643641
fn make_run(run: RunConfig<'_>) {
644-
run.builder.ensure(Rustc { stage: run.builder.top_stage, target: run.target });
642+
run.builder.ensure(Rustc {
643+
stage: run.builder.top_stage,
644+
target: run.target,
645+
crates: make_run_crates(&run, "compiler"),
646+
});
645647
}
646648

647649
/// Generates compiler documentation.
@@ -654,15 +656,6 @@ impl Step for Rustc {
654656
let stage = self.stage;
655657
let target = self.target;
656658

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-
666659
// This is the intended out directory for compiler documentation.
667660
let out = builder.compiler_doc_out(target);
668661
t!(fs::create_dir_all(&out));
@@ -672,7 +665,13 @@ impl Step for Rustc {
672665
let compiler = builder.compiler(stage, builder.config.build);
673666
builder.ensure(compile::Std::new(compiler, builder.config.build));
674667

675-
builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
668+
let _guard = builder.msg(
669+
Kind::Doc,
670+
stage,
671+
&format!("compiler{}", crate_description(&self.crates)),
672+
compiler.host,
673+
target,
674+
);
676675

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

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-
727712
let mut to_open = None;
728-
for krate in compiler_crates {
713+
for krate in &*self.crates {
729714
// Create all crate output directories first to make sure rustdoc uses
730715
// relative links.
731716
// FIXME: Cargo should probably do this itself.
@@ -785,7 +770,7 @@ macro_rules! tool_doc {
785770

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

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

0 commit comments

Comments
 (0)