Rollup merge of #128215 - ehuss:update-reference, r=Kobzol

Update the reference

This updates the reference to use the new mdbook-spec preprocessor, which is a Cargo library inside the reference submodule.

Note that this PR contains a bunch of bootstrap cleanup commits to assist with making sure the submodules are working correctly. All of the cleanup PRs should have a description in their commit. I'd be happy to move those to a separate PR if that makes review easier.

The main changes for the reference are:
- Move the `doc::Reference` bootstrap step out of the generic macro into a custom step.
    - This step needs to build rustdoc because the new mdbook-spec plugin uses rustdoc for generating links.
    - PATH is updated so that the rustdoc binary can be found.
- rustbook now includes the mdbook-spec plugin as a dependency.
- rustbook enables the mdbook-spec preprocessor.

I did a bunch of testing with the various commands and setups, such as:
- `submodules=true` and `submodules=false`
- having all submodules deinitialized
- not in a git repository

However, there are probably thousands of different permutations of different commands, settings, and environments, so there is a chance I'm missing something.
This commit is contained in:
Matthias Krüger 2024-07-28 13:42:19 +02:00 committed by GitHub
commit 20cf5ade15
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 255 additions and 94 deletions

View File

@ -9,7 +9,7 @@
};
use crate::core::config::TargetSelection;
use crate::{Compiler, Mode, Subcommand};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
pub fn cargo_subcommand(kind: Kind) -> &'static str {
match kind {
@ -52,7 +52,7 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) {
builder.update_submodule(&Path::new("library").join("stdarch"));
builder.require_submodule("library/stdarch", None);
let target = self.target;
let compiler = builder.compiler(builder.top_stage, builder.config.build);

View File

@ -1,7 +1,5 @@
//! Implementation of running clippy on the compiler, standard library and various tools.
use std::path::Path;
use crate::builder::Builder;
use crate::builder::ShouldRun;
use crate::core::builder;
@ -127,7 +125,7 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) {
builder.update_submodule(&Path::new("library").join("stdarch"));
builder.require_submodule("library/stdarch", None);
let target = self.target;
let compiler = builder.compiler(builder.top_stage, builder.config.build);

View File

@ -182,11 +182,16 @@ fn run(self, builder: &Builder<'_>) {
return;
}
builder.update_submodule(&Path::new("library").join("stdarch"));
builder.require_submodule("library/stdarch", None);
// Profiler information requires LLVM's compiler-rt
if builder.config.profiler {
builder.update_submodule(Path::new("src/llvm-project"));
builder.require_submodule(
"src/llvm-project",
Some(
"The `build.profiler` config option requires `compiler-rt` sources from LLVM.",
),
);
}
let mut target_deps = builder.ensure(StartupObjects { compiler, target });
@ -456,13 +461,15 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
// That's probably ok? At least, the difference wasn't enforced before. There's a comment in
// the compiler_builtins build script that makes me nervous, though:
// https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
builder.update_submodule(&Path::new("src").join("llvm-project"));
builder.require_submodule(
"src/llvm-project",
Some(
"The `build.optimized-compiler-builtins` config option \
requires `compiler-rt` sources from LLVM.",
),
);
let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
if !compiler_builtins_root.exists() {
panic!(
"need LLVM sources available to build `compiler-rt`, but they weren't present; consider enabling `build.submodules = true` or disabling `optimized-compiler-builtins`"
);
}
assert!(compiler_builtins_root.exists());
// Note that `libprofiler_builtins/build.rs` also computes this so if
// you're changing something here please also change that.
cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);

View File

@ -907,7 +907,7 @@ fn make_run(run: RunConfig<'_>) {
/// Creates the `rust-src` installer component
fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
if !builder.config.dry_run() {
builder.update_submodule(Path::new("src/llvm-project"));
builder.require_submodule("src/llvm-project", None);
}
let tarball = Tarball::new_targetless(builder, "rust-src");
@ -1022,10 +1022,7 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
// FIXME: This code looks _very_ similar to what we have in `src/core/build_steps/vendor.rs`
// perhaps it should be removed in favor of making `dist` perform the `vendor` step?
// Ensure we have all submodules from src and other directories checked out.
for submodule in build_helper::util::parse_gitmodules(&builder.src) {
builder.update_submodule(Path::new(submodule));
}
builder.require_and_update_all_submodules();
// Vendor all Cargo dependencies
let mut cmd = command(&builder.initial_cargo);

View File

@ -9,14 +9,14 @@
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::{fs, mem};
use std::{env, fs, mem};
use crate::core::build_steps::compile;
use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool};
use crate::core::builder::{self, crate_description};
use crate::core::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::core::config::{Config, TargetSelection};
use crate::utils::helpers::{dir_is_empty, symlink_dir, t, up_to_date};
use crate::utils::helpers::{symlink_dir, t, up_to_date};
use crate::Mode;
macro_rules! submodule_helper {
@ -53,8 +53,8 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) {
$(
let path = Path::new(submodule_helper!( $path, submodule $( = $submodule )? ));
builder.update_submodule(&path);
let path = submodule_helper!( $path, submodule $( = $submodule )? );
builder.require_submodule(path, None);
)?
builder.ensure(RustbookSrc {
target: self.target,
@ -62,6 +62,7 @@ fn run(self, builder: &Builder<'_>) {
src: builder.src.join($path),
parent: Some(self),
languages: $lang.into(),
rustdoc: None,
})
}
}
@ -80,7 +81,6 @@ fn run(self, builder: &Builder<'_>) {
EditionGuide, "src/doc/edition-guide", "edition-guide", &[], submodule;
EmbeddedBook, "src/doc/embedded-book", "embedded-book", &[], submodule;
Nomicon, "src/doc/nomicon", "nomicon", &[], submodule;
Reference, "src/doc/reference", "reference", &[], submodule;
RustByExample, "src/doc/rust-by-example", "rust-by-example", &["ja"], submodule;
RustdocBook, "src/doc/rustdoc", "rustdoc", &[];
StyleGuide, "src/doc/style-guide", "style-guide", &[];
@ -112,6 +112,7 @@ fn run(self, builder: &Builder<'_>) {
src: builder.md_doc_out(self.target).join("unstable-book"),
parent: Some(self),
languages: vec![],
rustdoc: None,
})
}
}
@ -123,6 +124,7 @@ struct RustbookSrc<P: Step> {
src: PathBuf,
parent: Option<P>,
languages: Vec<&'static str>,
rustdoc: Option<PathBuf>,
}
impl<P: Step> Step for RustbookSrc<P> {
@ -153,13 +155,18 @@ fn run(self, builder: &Builder<'_>) {
builder.info(&format!("Rustbook ({target}) - {name}"));
let _ = fs::remove_dir_all(&out);
builder
.tool_cmd(Tool::Rustbook)
.arg("build")
.arg(&src)
.arg("-d")
.arg(&out)
.run(builder);
let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
if let Some(mut rustdoc) = self.rustdoc {
rustdoc.pop();
let old_path = env::var_os("PATH").unwrap_or_default();
let new_path =
env::join_paths(std::iter::once(rustdoc).chain(env::split_paths(&old_path)))
.expect("could not add rustdoc to PATH");
rustbook_cmd.env("PATH", new_path);
}
rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out).run(builder);
for lang in &self.languages {
let out = out.join(lang);
@ -217,22 +224,14 @@ fn make_run(run: RunConfig<'_>) {
/// * Index page
/// * Redirect pages
fn run(self, builder: &Builder<'_>) {
let relative_path = Path::new("src").join("doc").join("book");
builder.update_submodule(&relative_path);
builder.require_submodule("src/doc/book", None);
let compiler = self.compiler;
let target = self.target;
let absolute_path = builder.src.join(&relative_path);
let absolute_path = builder.src.join("src/doc/book");
let redirect_path = absolute_path.join("redirects");
if !absolute_path.exists()
|| !redirect_path.exists()
|| dir_is_empty(&absolute_path)
|| dir_is_empty(&redirect_path)
{
eprintln!("Please checkout submodule: {}", relative_path.display());
crate::exit!(1);
}
// build book
builder.ensure(RustbookSrc {
target,
@ -240,6 +239,7 @@ fn run(self, builder: &Builder<'_>) {
src: absolute_path.clone(),
parent: Some(self),
languages: vec![],
rustdoc: None,
});
// building older edition redirects
@ -252,6 +252,7 @@ fn run(self, builder: &Builder<'_>) {
// treat the other editions as not having a parent.
parent: Option::<Self>::None,
languages: vec![],
rustdoc: None,
});
}
@ -932,8 +933,8 @@ fn run(self, builder: &Builder<'_>) {
let _ = source_type; // silence the "unused variable" warning
let source_type = SourceType::Submodule;
let path = Path::new(submodule_helper!( $path, submodule $( = $submodule )? ));
builder.update_submodule(&path);
let path = submodule_helper!( $path, submodule $( = $submodule )? );
builder.require_submodule(path, None);
)?
let stage = builder.top_stage;
@ -1172,12 +1173,6 @@ fn make_run(run: RunConfig<'_>) {
/// in the "md-doc" directory in the build output directory. Then
/// "rustbook" is used to convert it to HTML.
fn run(self, builder: &Builder<'_>) {
// These submodules are required to be checked out to build rustbook
// because they have Cargo dependencies that are needed.
#[allow(clippy::single_element_loop)] // This will change soon.
for path in ["src/doc/book"] {
builder.update_submodule(Path::new(path));
}
let out_base = builder.md_doc_out(self.target).join("rustc");
t!(fs::create_dir_all(&out_base));
let out_listing = out_base.join("src/lints");
@ -1228,6 +1223,50 @@ fn run(self, builder: &Builder<'_>) {
src: out_base,
parent: Some(self),
languages: vec![],
rustdoc: None,
});
}
}
#[derive(Ord, PartialOrd, Debug, Clone, Hash, PartialEq, Eq)]
pub struct Reference {
pub compiler: Compiler,
pub target: TargetSelection,
}
impl Step for Reference {
type Output = ();
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
run.path("src/doc/reference").default_condition(builder.config.docs)
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Reference {
compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
target: run.target,
});
}
/// Builds the reference book.
fn run(self, builder: &Builder<'_>) {
builder.require_submodule("src/doc/reference", None);
// This is needed for generating links to the standard library using
// the mdbook-spec plugin.
builder.ensure(compile::Std::new(self.compiler, builder.config.build));
let rustdoc = builder.rustdoc(self.compiler);
// Run rustbook/mdbook to generate the HTML pages.
builder.ensure(RustbookSrc {
target: self.target,
name: "reference".to_owned(),
src: builder.src.join("src/doc/reference"),
parent: Some(self),
languages: vec![],
rustdoc: Some(rustdoc),
});
}
}

View File

@ -89,7 +89,7 @@ fn push_all(&mut self, s: impl AsRef<OsStr>) {
/// if not).
pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> LlvmBuildStatus {
// If we have llvm submodule initialized already, sync it.
builder.update_existing_submodule(&Path::new("src").join("llvm-project"));
builder.update_existing_submodule("src/llvm-project");
builder.config.maybe_download_ci_llvm();
@ -110,7 +110,8 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L
}
// Initialize the llvm submodule if not initialized already.
builder.update_submodule(&Path::new("src").join("llvm-project"));
// If submodules are disabled, this does nothing.
builder.update_submodule("src/llvm-project");
let root = "src/llvm-project/llvm";
let out_dir = builder.llvm_out(target);
@ -1197,7 +1198,10 @@ fn make_run(run: RunConfig<'_>) {
/// Build crtbegin.o/crtend.o for musl target.
fn run(self, builder: &Builder<'_>) -> Self::Output {
builder.update_submodule(Path::new("src/llvm-project"));
builder.require_submodule(
"src/llvm-project",
Some("The LLVM sources are required for the CRT from `compiler-rt`."),
);
let out_dir = builder.native_dir(self.target).join("crt");
@ -1270,7 +1274,10 @@ fn make_run(run: RunConfig<'_>) {
/// Build libunwind.a
fn run(self, builder: &Builder<'_>) -> Self::Output {
builder.update_submodule(Path::new("src/llvm-project"));
builder.require_submodule(
"src/llvm-project",
Some("The LLVM sources are required for libunwind."),
);
if builder.config.dry_run() {
return PathBuf::new();

View File

@ -2257,7 +2257,12 @@ fn run_local_doc(self, builder: &Builder<'_>) {
}
macro_rules! test_book {
($($name:ident, $path:expr, $book_name:expr, default=$default:expr;)+) => {
($(
$name:ident, $path:expr, $book_name:expr,
default=$default:expr
$(,submodules = $submodules:expr)?
;
)+) => {
$(
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct $name {
@ -2280,6 +2285,11 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) {
$(
for submodule in $submodules {
builder.require_submodule(submodule, None);
}
)*
builder.ensure(BookTest {
compiler: self.compiler,
path: PathBuf::from($path),
@ -2293,15 +2303,15 @@ fn run(self, builder: &Builder<'_>) {
}
test_book!(
Nomicon, "src/doc/nomicon", "nomicon", default=false;
Reference, "src/doc/reference", "reference", default=false;
Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
RustcBook, "src/doc/rustc", "rustc", default=true;
RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false;
EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false;
TheBook, "src/doc/book", "book", default=false;
RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"];
UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
EditionGuide, "src/doc/edition-guide", "edition-guide", default=false;
EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -2398,8 +2408,8 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) {
let relative_path = Path::new("src").join("doc").join("rustc-dev-guide");
builder.update_submodule(&relative_path);
let relative_path = "src/doc/rustc-dev-guide";
builder.require_submodule(relative_path, None);
let src = builder.src.join(relative_path);
let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook).delay_failure();
@ -3009,7 +3019,7 @@ fn run(self, builder: &Builder<'_>) {
let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host);
// Some tests require cargo submodule to be present.
builder.build.update_submodule(Path::new("src/tools/cargo"));
builder.build.require_submodule("src/tools/cargo", None);
let mut check_bootstrap = command(builder.python());
check_bootstrap

View File

@ -1,6 +1,6 @@
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use crate::core::build_steps::compile;
use crate::core::build_steps::toolstate::ToolState;
@ -241,6 +241,7 @@ macro_rules! bootstrap_tool {
$(,is_external_tool = $external:expr)*
$(,is_unstable_tool = $unstable:expr)*
$(,allow_features = $allow_features:expr)?
$(,submodules = $submodules:expr)?
;
)+) => {
#[derive(PartialEq, Eq, Clone)]
@ -287,6 +288,11 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) -> PathBuf {
$(
for submodule in $submodules {
builder.require_submodule(submodule, None);
}
)*
builder.ensure(ToolBuild {
compiler: self.compiler,
target: self.target,
@ -314,7 +320,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
}
bootstrap_tool!(
Rustbook, "src/tools/rustbook", "rustbook";
Rustbook, "src/tools/rustbook", "rustbook", submodules = SUBMODULES_FOR_RUSTBOOK;
UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen";
Tidy, "src/tools/tidy", "tidy";
Linkchecker, "src/tools/linkchecker", "linkchecker";
@ -340,6 +346,10 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
);
/// These are the submodules that are required for rustbook to work due to
/// depending on mdbook plugins.
pub static SUBMODULES_FOR_RUSTBOOK: &[&str] = &["src/doc/book", "src/doc/reference"];
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct OptimizedDist {
pub compiler: Compiler,
@ -363,7 +373,7 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) -> PathBuf {
// We need to ensure the rustc-perf submodule is initialized when building opt-dist since
// the tool requires it to be in place to run.
builder.update_submodule(Path::new("src/tools/rustc-perf"));
builder.require_submodule("src/tools/rustc-perf", None);
builder.ensure(ToolBuild {
compiler: self.compiler,
@ -404,7 +414,7 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) -> PathBuf {
// We need to ensure the rustc-perf submodule is initialized.
builder.update_submodule(Path::new("src/tools/rustc-perf"));
builder.require_submodule("src/tools/rustc-perf", None);
let tool = ToolBuild {
compiler: self.compiler,
@ -705,7 +715,7 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) -> PathBuf {
builder.build.update_submodule(Path::new("src/tools/cargo"));
builder.build.require_submodule("src/tools/cargo", None);
builder.ensure(ToolBuild {
compiler: self.compiler,
@ -1087,8 +1097,6 @@ fn run(mut $sel, $builder: &Builder<'_>) -> PathBuf {
// NOTE: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs`
// to make `./x.py build <tool>` work.
// NOTE: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to
// invoke Cargo to build bootstrap. See the comment there for more details.
tool_extended!((self, builder),
Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true;
CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true;

View File

@ -1,6 +1,7 @@
use crate::core::build_steps::tool::SUBMODULES_FOR_RUSTBOOK;
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::utils::exec::command;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub(crate) struct Vendor {
@ -35,8 +36,8 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
}
// These submodules must be present for `x vendor` to work.
for path in ["src/tools/cargo", "src/doc/book"] {
builder.build.update_submodule(Path::new(path));
for submodule in SUBMODULES_FOR_RUSTBOOK.iter().chain(["src/tools/cargo"].iter()) {
builder.build.require_submodule(submodule, None);
}
// Sync these paths by default.

View File

@ -13,15 +13,18 @@ fn configure_with_args(cmd: &[String], host: &[&str], target: &[&str]) -> Config
config.save_toolstates = None;
config.dry_run = DryRun::SelfCheck;
// Ignore most submodules, since we don't need them for a dry run.
// But make sure to check out the `doc` and `rust-analyzer` submodules, since some steps need them
// just to know which commands to run.
// Ignore most submodules, since we don't need them for a dry run, and the
// tests run much faster without them.
//
// The src/doc/book submodule is needed because TheBook step tries to
// access files even during a dry-run (may want to consider just skipping
// that in a dry run).
let submodule_build = Build::new(Config {
// don't include LLVM, so CI doesn't require ninja/cmake to be installed
rust_codegen_backends: vec![],
..Config::parse(&["check".to_owned()])
});
submodule_build.update_submodule(Path::new("src/doc/book"));
submodule_build.require_submodule("src/doc/book", None);
config.submodules = Some(false);
config.ninja_in_file = false;

View File

@ -2404,8 +2404,11 @@ pub fn split_debuginfo(&self, target: TargetSelection) -> SplitDebuginfo {
.unwrap_or_else(|| SplitDebuginfo::default_for_platform(target))
}
pub fn submodules(&self, rust_info: &GitInfo) -> bool {
self.submodules.unwrap_or(rust_info.is_managed_git_subrepository())
/// Returns whether or not submodules should be managed by bootstrap.
pub fn submodules(&self) -> bool {
// If not specified in config, the default is to only manage
// submodules if we're currently inside a git repository.
self.submodules.unwrap_or(self.rust_info.is_managed_git_subrepository())
}
pub fn codegen_backends(&self, target: TargetSelection) -> &[String] {

View File

@ -441,7 +441,13 @@ pub fn new(mut config: Config) -> Build {
// Cargo.toml files.
let rust_submodules = ["library/backtrace", "library/stdarch"];
for s in rust_submodules {
build.update_submodule(Path::new(s));
build.require_submodule(
s,
Some(
"The submodule is required for the standard library \
and the main Cargo workspace.",
),
);
}
// Now, update all existing submodules.
build.update_existing_submodules();
@ -470,12 +476,17 @@ pub fn new(mut config: Config) -> Build {
build
}
// modified from `check_submodule` and `update_submodule` in bootstrap.py
/// Given a path to the directory of a submodule, update it.
///
/// `relative_path` should be relative to the root of the git repository, not an absolute path.
pub(crate) fn update_submodule(&self, relative_path: &Path) {
if !self.config.submodules(self.rust_info()) {
///
/// This *does not* update the submodule if `config.toml` explicitly says
/// not to, or if we're not in a git repository (like a plain source
/// tarball). Typically [`Build::require_submodule`] should be
/// used instead to provide a nice error to the user if the submodule is
/// missing.
fn update_submodule(&self, relative_path: &str) {
if !self.config.submodules() {
return;
}
@ -522,7 +533,7 @@ pub(crate) fn update_submodule(&self, relative_path: &Path) {
return;
}
println!("Updating submodule {}", relative_path.display());
println!("Updating submodule {relative_path}");
helpers::git(Some(&self.src))
.run_always()
.args(["submodule", "-q", "sync"])
@ -580,11 +591,53 @@ pub(crate) fn update_submodule(&self, relative_path: &Path) {
}
}
/// Updates a submodule, and exits with a failure if submodule management
/// is disabled and the submodule does not exist.
///
/// The given submodule name should be its path relative to the root of
/// the main repository.
///
/// The given `err_hint` will be shown to the user if the submodule is not
/// checked out and submodule management is disabled.
pub fn require_submodule(&self, submodule: &str, err_hint: Option<&str>) {
// When testing bootstrap itself, it is much faster to ignore
// submodules. Almost all Steps work fine without their submodules.
if cfg!(test) && !self.config.submodules() {
return;
}
self.update_submodule(submodule);
let absolute_path = self.config.src.join(submodule);
if dir_is_empty(&absolute_path) {
let maybe_enable = if !self.config.submodules()
&& self.config.rust_info.is_managed_git_subrepository()
{
"\nConsider setting `build.submodules = true` or manually initializing the submodules."
} else {
""
};
let err_hint = err_hint.map_or_else(String::new, |e| format!("\n{e}"));
eprintln!(
"submodule {submodule} does not appear to be checked out, \
but it is required for this step{maybe_enable}{err_hint}"
);
exit!(1);
}
}
/// Updates all submodules, and exits with an error if submodule
/// management is disabled and the submodule does not exist.
pub fn require_and_update_all_submodules(&self) {
for submodule in build_helper::util::parse_gitmodules(&self.src) {
self.require_submodule(submodule, None);
}
}
/// If any submodule has been initialized already, sync it unconditionally.
/// This avoids contributors checking in a submodule change by accident.
pub fn update_existing_submodules(&self) {
// Avoid running git when there isn't a git checkout.
if !self.config.submodules(self.rust_info()) {
fn update_existing_submodules(&self) {
// Avoid running git when there isn't a git checkout, or the user has
// explicitly disabled submodules in `config.toml`.
if !self.config.submodules() {
return;
}
let output = helpers::git(Some(&self.src))
@ -597,22 +650,23 @@ pub fn update_existing_submodules(&self) {
for line in output.lines() {
// Look for `submodule.$name.path = $path`
// Sample output: `submodule.src/rust-installer.path src/tools/rust-installer`
let submodule = Path::new(line.split_once(' ').unwrap().1);
let submodule = line.split_once(' ').unwrap().1;
let path = Path::new(submodule);
// Don't update the submodule unless it's already been cloned.
if GitInfo::new(false, submodule).is_managed_git_subrepository() {
if GitInfo::new(false, path).is_managed_git_subrepository() {
self.update_submodule(submodule);
}
}
}
/// Updates the given submodule only if it's initialized already; nothing happens otherwise.
pub fn update_existing_submodule(&self, submodule: &Path) {
pub fn update_existing_submodule(&self, submodule: &str) {
// Avoid running git when there isn't a git checkout.
if !self.config.submodules(self.rust_info()) {
if !self.config.submodules() {
return;
}
if GitInfo::new(false, submodule).is_managed_git_subrepository() {
if GitInfo::new(false, Path::new(submodule)).is_managed_git_subrepository() {
self.update_submodule(submodule);
}
}

@ -1 +1 @@
Subproject commit e2f0bdc4031866734661dcdb548184bde1450baf
Subproject commit 2e191814f163ee1e77e2d6094eee4dd78a289c5b

View File

@ -661,6 +661,20 @@ dependencies = [
"textwrap",
]
[[package]]
name = "mdbook-spec"
version = "0.1.2"
dependencies = [
"anyhow",
"mdbook",
"once_cell",
"pathdiff",
"regex",
"semver",
"serde_json",
"tempfile",
]
[[package]]
name = "mdbook-trpl-listing"
version = "0.1.0"
@ -794,6 +808,12 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "pathdiff"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
[[package]]
name = "percent-encoding"
version = "2.3.1"
@ -1079,6 +1099,7 @@ dependencies = [
"env_logger",
"mdbook",
"mdbook-i18n-helpers",
"mdbook-spec",
"mdbook-trpl-listing",
"mdbook-trpl-note",
]

View File

@ -12,6 +12,7 @@ env_logger = "0.11"
mdbook-trpl-listing = { path = "../../doc/book/packages/mdbook-trpl-listing" }
mdbook-trpl-note = { path = "../../doc/book/packages/mdbook-trpl-note" }
mdbook-i18n-helpers = "0.3.3"
mdbook-spec = { path = "../../doc/reference/mdbook-spec"}
[dependencies.mdbook]
version = "0.4.37"

View File

@ -9,6 +9,7 @@
use mdbook::MDBook;
use mdbook_i18n_helpers::preprocessors::Gettext;
use mdbook_spec::Spec;
use mdbook_trpl_listing::TrplListing;
use mdbook_trpl_note::TrplNote;
@ -83,6 +84,13 @@ pub fn build(args: &ArgMatches) -> Result3<()> {
book.config.build.build_dir = dest_dir.into();
}
// NOTE: Replacing preprocessors using this technique causes error
// messages to be displayed when the original preprocessor doesn't work
// (but it otherwise succeeds).
//
// This should probably be fixed in mdbook to remove the existing
// preprocessor, or this should modify the config and use
// MDBook::load_with_config.
if book.config.get_preprocessor("trpl-note").is_some() {
book.with_preprocessor(TrplNote);
}
@ -91,6 +99,10 @@ pub fn build(args: &ArgMatches) -> Result3<()> {
book.with_preprocessor(TrplListing);
}
if book.config.get_preprocessor("spec").is_some() {
book.with_preprocessor(Spec::new());
}
book.build()?;
Ok(())

View File

@ -72,7 +72,7 @@
//("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
//("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None, &[]),
("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book"]),
("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book", "src/doc/reference"]),
("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None, &["src/tools/rustc-perf"]),
("src/tools/x", &[], None, &[]),
// tidy-alphabetical-end