bootstrap: update defaults for compiler and library aliases

This commit is contained in:
Lukas Markeffsky 2023-06-23 16:28:08 +00:00
parent fe03b46ee4
commit b1a5423ff8
8 changed files with 114 additions and 86 deletions

View File

@ -115,6 +115,43 @@ pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> {
}
INTERNER.intern_list(crates)
}
/// Given an `alias` selected by the `Step` and the paths passed on the command line,
/// return a list of the crates that should be built.
///
/// Normally, people will pass *just* `library` if they pass it.
/// But it's possible (although strange) to pass something like `library std core`.
/// Build all crates anyway, as if they hadn't passed the other args.
pub fn make_run_crates(&self, alias: Alias) -> Interned<Vec<String>> {
let has_alias =
self.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias.as_str()));
if !has_alias {
return self.cargo_crates_in_set();
}
let crates = match alias {
Alias::Library => self.builder.in_tree_crates("sysroot", Some(self.target)),
Alias::Compiler => self.builder.in_tree_crates("rustc-main", Some(self.target)),
};
let crate_names = crates.into_iter().map(|krate| krate.name.to_string()).collect();
INTERNER.intern_list(crate_names)
}
}
#[derive(Debug, Copy, Clone)]
pub enum Alias {
Library,
Compiler,
}
impl Alias {
fn as_str(self) -> &'static str {
match self {
Alias::Library => "library",
Alias::Compiler => "compiler",
}
}
}
/// A description of the crates in this set, suitable for passing to `builder.info`.

View File

@ -68,13 +68,17 @@ macro_rules! std {
}
macro_rules! doc_std {
($host:ident => $target:ident, stage = $stage:literal) => {
($host:ident => $target:ident, stage = $stage:literal) => {{
let config = configure("doc", &["A"], &["A"]);
let build = Build::new(config);
let builder = Builder::new(&build);
doc::Std::new(
$stage,
TargetSelection::from_user(stringify!($target)),
&builder,
DocumentationFormat::HTML,
)
};
}};
}
macro_rules! rustc {

View File

@ -1,10 +1,8 @@
//! Implementation of compiling the compiler and standard library, in "check"-based modes.
use crate::builder::{crate_description, Builder, Kind, RunConfig, ShouldRun, Step};
use crate::builder::{crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
use crate::compile::{
add_to_sysroot, make_run_crates, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo,
};
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
use crate::config::TargetSelection;
use crate::tool::{prepare_tool_cargo, SourceType};
use crate::INTERNER;
@ -89,7 +87,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
let crates = make_run_crates(&run, "library");
let crates = run.make_run_crates(Alias::Library);
run.builder.ensure(Std { target: run.target, crates });
}
@ -140,7 +138,7 @@ fn run(self, builder: &Builder<'_>) {
// don't run on std twice with x.py clippy
// don't check test dependencies if we haven't built libtest
if builder.kind == Kind::Clippy || !self.crates.is_empty() {
if builder.kind == Kind::Clippy || !self.crates.iter().any(|krate| krate == "test") {
return;
}
@ -200,10 +198,11 @@ pub struct Rustc {
impl Rustc {
pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
let mut crates = vec![];
for krate in builder.in_tree_crates("rustc-main", None) {
crates.push(krate.name.to_string());
}
let crates = builder
.in_tree_crates("rustc-main", Some(target))
.into_iter()
.map(|krate| krate.name.to_string())
.collect();
Self { target, crates: INTERNER.intern_list(crates) }
}
}
@ -218,7 +217,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
let crates = make_run_crates(&run, "compiler");
let crates = run.make_run_crates(Alias::Compiler);
run.builder.ensure(Rustc { target: run.target, crates });
}

View File

@ -55,17 +55,6 @@ pub fn force_recompile(compiler: Compiler, target: TargetSelection) -> Self {
}
}
/// Given an `alias` selected by the `Step` and the paths passed on the command line,
/// return a list of the crates that should be built.
///
/// Normally, people will pass *just* `library` if they pass it.
/// But it's possible (although strange) to pass something like `library std core`.
/// Build all crates anyway, as if they hadn't passed the other args.
pub(crate) fn make_run_crates(run: &RunConfig<'_>, alias: &str) -> Interned<Vec<String>> {
let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias));
if has_alias { Default::default() } else { run.cargo_crates_in_set() }
}
impl Step for Std {
type Output = ();
const DEFAULT: bool = true;
@ -80,10 +69,15 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
// If the paths include "library", build the entire standard library.
let has_alias =
run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
let crates = if has_alias { Default::default() } else { run.cargo_crates_in_set() };
run.builder.ensure(Std {
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
target: run.target,
crates: make_run_crates(&run, "library"),
crates,
force_recompile: false,
});
}

View File

@ -106,7 +106,12 @@ fn make_run(run: RunConfig<'_>) {
/// Builds the `rust-docs-json` installer component.
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let host = self.host;
builder.ensure(crate::doc::Std::new(builder.top_stage, host, DocumentationFormat::JSON));
builder.ensure(crate::doc::Std::new(
builder.top_stage,
host,
builder,
DocumentationFormat::JSON,
));
let dest = "share/doc/rust/json";

View File

@ -11,10 +11,9 @@
use std::path::{Path, PathBuf};
use crate::builder::crate_description;
use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::cache::{Interned, INTERNER};
use crate::compile;
use crate::compile::make_run_crates;
use crate::config::{Config, TargetSelection};
use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
use crate::util::{symlink_dir, t, up_to_date};
@ -424,8 +423,18 @@ pub struct Std {
}
impl Std {
pub(crate) fn new(stage: u32, target: TargetSelection, format: DocumentationFormat) -> Self {
Std { stage, target, format, crates: INTERNER.intern_list(vec![]) }
pub(crate) fn new(
stage: u32,
target: TargetSelection,
builder: &Builder<'_>,
format: DocumentationFormat,
) -> Self {
let crates = builder
.in_tree_crates("sysroot", Some(target))
.into_iter()
.map(|krate| krate.name.to_string())
.collect();
Std { stage, target, format, crates: INTERNER.intern_list(crates) }
}
}
@ -447,7 +456,7 @@ fn make_run(run: RunConfig<'_>) {
} else {
DocumentationFormat::HTML
},
crates: make_run_crates(&run, "library"),
crates: run.make_run_crates(Alias::Library),
});
}
@ -455,7 +464,7 @@ fn make_run(run: RunConfig<'_>) {
///
/// This will generate all documentation for the standard library and its
/// dependencies. This is largely just a wrapper around `cargo doc`.
fn run(mut self, builder: &Builder<'_>) {
fn run(self, builder: &Builder<'_>) {
let stage = self.stage;
let target = self.target;
let out = match self.format {
@ -493,20 +502,17 @@ fn run(mut self, builder: &Builder<'_>) {
return;
}
// Look for library/std, library/core etc in the `x.py doc` arguments and
// open the corresponding rendered docs.
if self.crates.is_empty() {
self.crates = INTERNER.intern_list(vec!["library".to_owned()]);
};
for requested_crate in &*self.crates {
if requested_crate == "library" {
// For `x.py doc library --open`, open `std` by default.
let index = out.join("std").join("index.html");
builder.open_in_browser(index);
} else if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) {
let index = out.join(requested_crate).join("index.html");
builder.open_in_browser(index);
if builder.paths.iter().any(|path| path.ends_with("library")) {
// For `x.py doc library --open`, open `std` by default.
let index = out.join("std").join("index.html");
builder.open_in_browser(index);
} else {
for requested_crate in &*self.crates {
if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) {
let index = out.join(requested_crate).join("index.html");
builder.open_in_browser(index);
break;
}
}
}
}
@ -539,9 +545,6 @@ fn as_str(&self) -> &str {
}
/// Build the documentation for public standard library crates.
///
/// `requested_crates` can be used to build only a subset of the crates. If empty, all crates will
/// be built.
fn doc_std(
builder: &Builder<'_>,
format: DocumentationFormat,
@ -592,19 +595,11 @@ fn doc_std(
cargo.rustdocflag("--document-private-items").rustdocflag("--document-hidden-items");
}
// HACK: because we use `--manifest-path library/sysroot/Cargo.toml`, cargo thinks we only want to document that specific crate, not its dependencies.
// Override its default.
let built_crates = if requested_crates.is_empty() {
builder
.in_tree_crates("sysroot", None)
.into_iter()
.map(|krate| krate.name.to_string())
.collect()
} else {
requested_crates.to_vec()
};
for krate in built_crates {
for krate in requested_crates {
if krate == "sysroot" {
// The sysroot crate is an implementation detail, don't include it in public docs.
continue;
}
cargo.arg("-p").arg(krate);
}
@ -621,20 +616,10 @@ pub struct Rustc {
impl Rustc {
pub(crate) fn new(stage: u32, target: TargetSelection, builder: &Builder<'_>) -> Self {
// Find dependencies for top level crates.
let root_crates = vec![
INTERNER.intern_str("rustc_driver"),
INTERNER.intern_str("rustc_codegen_llvm"),
INTERNER.intern_str("rustc_codegen_ssa"),
];
let crates: Vec<_> = root_crates
.iter()
.flat_map(|krate| {
builder
.in_tree_crates(krate, Some(target))
.into_iter()
.map(|krate| krate.name.to_string())
})
let crates = builder
.in_tree_crates("rustc-main", Some(target))
.into_iter()
.map(|krate| krate.name.to_string())
.collect();
Self { stage, target, crates: INTERNER.intern_list(crates) }
}
@ -656,7 +641,7 @@ fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Rustc {
stage: run.builder.top_stage,
target: run.target,
crates: make_run_crates(&run, "compiler"),
crates: run.make_run_crates(Alias::Compiler),
});
}
@ -666,7 +651,7 @@ fn make_run(run: RunConfig<'_>) {
/// Compiler documentation is distributed separately, so we make sure
/// we do not merge it with the other documentation from std, test and
/// proc_macros. This is largely just a wrapper around `cargo doc`.
fn run(mut self, builder: &Builder<'_>) {
fn run(self, builder: &Builder<'_>) {
let stage = self.stage;
let target = self.target;
@ -726,24 +711,26 @@ fn run(mut self, builder: &Builder<'_>) {
let mut to_open = None;
if self.crates.is_empty() {
self.crates = INTERNER.intern_list(vec!["rustc_driver".to_owned()]);
};
for krate in &*self.crates {
// Create all crate output directories first to make sure rustdoc uses
// relative links.
// FIXME: Cargo should probably do this itself.
t!(fs::create_dir_all(out_dir.join(krate)));
let dir_name = krate.replace("-", "_");
t!(fs::create_dir_all(out_dir.join(&*dir_name)));
cargo.arg("-p").arg(krate);
if to_open.is_none() {
to_open = Some(krate);
to_open = Some(dir_name);
}
}
builder.run(&mut cargo.into());
// Let's open the first crate documentation page:
if let Some(krate) = to_open {
if builder.paths.iter().any(|path| path.ends_with("compiler")) {
// For `x.py doc compiler --open`, open `rustc_middle` by default.
let index = out.join("rustc_middle").join("index.html");
builder.open_in_browser(index);
} else if let Some(krate) = to_open {
// Let's open the first crate documentation page:
let index = out.join(krate).join("index.html");
builder.open_in_browser(index);
}

View File

@ -1502,6 +1502,7 @@ fn in_tree_crates(&self, root: &str, target: Option<TargetSelection>) -> Vec<&Cr
}
}
}
ret.sort_unstable_by_key(|krate| krate.name); // reproducible order needed for tests
ret
}

View File

@ -901,6 +901,7 @@ fn run(self, builder: &Builder<'_>) {
builder.ensure(crate::doc::Std::new(
builder.top_stage,
self.target,
builder,
DocumentationFormat::HTML,
));
builder.run(&mut command);