about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock49
-rw-r--r--src/bootstrap/bin/rustc.rs35
-rw-r--r--src/bootstrap/builder.rs52
-rw-r--r--src/bootstrap/check.rs4
-rw-r--r--src/bootstrap/test.rs4
-rw-r--r--src/bootstrap/tool.rs25
-rw-r--r--src/tools/rustbook/Cargo.toml4
-rw-r--r--src/tools/rustbook/src/main.rs22
8 files changed, 146 insertions, 49 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d7381b6c938..06ab91e06ca 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -329,7 +329,7 @@ dependencies = [
  "cargo-test-macro",
  "cargo-test-support",
  "cargo-util",
- "clap 4.0.15",
+ "clap 4.0.32",
  "crates-io",
  "curl",
  "curl-sys",
@@ -631,26 +631,27 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.0.15"
+version = "4.0.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f"
+checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
 dependencies = [
- "atty",
  "bitflags",
- "clap_derive 4.0.13",
+ "clap_derive 4.0.21",
  "clap_lex 0.3.0",
+ "is-terminal",
  "once_cell",
  "strsim",
  "termcolor",
+ "terminal_size",
 ]
 
 [[package]]
 name = "clap_complete"
-version = "3.1.1"
+version = "4.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25"
+checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
 dependencies = [
- "clap 3.2.20",
+ "clap 4.0.32",
 ]
 
 [[package]]
@@ -668,9 +669,9 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.0.13"
+version = "4.0.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad"
+checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
 dependencies = [
  "heck",
  "proc-macro-error",
@@ -2271,7 +2272,7 @@ name = "jsondoclint"
 version = "0.1.0"
 dependencies = [
  "anyhow",
- "clap 4.0.15",
+ "clap 4.0.32",
  "fs-err",
  "rustdoc-json-types",
  "serde",
@@ -2527,21 +2528,21 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.21"
+version = "0.4.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23f3e133c6d515528745ffd3b9f0c7d975ae039f0b6abb099f2168daa2afb4f9"
+checksum = "d1ed28d5903dde77bd5182645078a37ee57014cac6ccb2d54e1d6496386648e4"
 dependencies = [
  "ammonia",
  "anyhow",
  "chrono",
- "clap 3.2.20",
+ "clap 4.0.32",
  "clap_complete",
  "elasticlunr-rs",
- "env_logger 0.9.0",
+ "env_logger 0.10.0",
  "handlebars 4.3.3",
- "lazy_static",
  "log",
  "memchr",
+ "once_cell",
  "opener",
  "pulldown-cmark 0.9.2",
  "regex",
@@ -3537,7 +3538,7 @@ dependencies = [
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 3.2.20",
+ "clap 4.0.32",
  "env_logger 0.7.1",
  "mdbook",
 ]
@@ -5503,6 +5504,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "terminal_size"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907"
+dependencies = [
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
 name = "termize"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5718,9 +5729,9 @@ dependencies = [
 
 [[package]]
 name = "topological-sort"
-version = "0.1.0"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c"
+checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
 
 [[package]]
 name = "tracing"
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 1d526022812..9611c866df5 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -154,6 +154,41 @@ fn main() {
         cmd.arg("-Z").arg("force-unstable-if-unmarked");
     }
 
+    // allow-features is handled from within this rustc wrapper because of
+    // issues with build scripts. Some packages use build scripts to
+    // dynamically detect if certain nightly features are available.
+    // There are different ways this causes problems:
+    //
+    // * rustix runs `rustc` on a small test program to see if the feature is
+    //   available (and sets a `cfg` if it is). It does not honor
+    //   CARGO_ENCODED_RUSTFLAGS.
+    // * proc-macro2 detects if `rustc -vV` says "nighty" or "dev" and enables
+    //   nightly features. It will scan CARGO_ENCODED_RUSTFLAGS for
+    //   -Zallow-features. Unfortunately CARGO_ENCODED_RUSTFLAGS is not set
+    //   for build-dependencies when --target is used.
+    //
+    // The issues above means we can't just use RUSTFLAGS, and we can't use
+    // `cargo -Zallow-features=…`. Passing it through here ensures that it
+    // always gets set. Unfortunately that also means we need to enable more
+    // features than we really want (like those for proc-macro2), but there
+    // isn't much of a way around it.
+    //
+    // I think it is unfortunate that build scripts are doing this at all,
+    // since changes to nightly features can cause crates to break even if the
+    // user didn't want or care about the use of the nightly features. I think
+    // nightly features should be opt-in only. Unfortunately the dynamic
+    // checks are now too wide spread that we just need to deal with it.
+    //
+    // If you want to try to remove this, I suggest working with the crate
+    // authors to remove the dynamic checking. Another option is to pursue
+    // https://github.com/rust-lang/cargo/issues/11244 and
+    // https://github.com/rust-lang/cargo/issues/4423, which will likely be
+    // very difficult, but could help expose -Zallow-features into build
+    // scripts so they could try to honor them.
+    if let Ok(allow_features) = env::var("RUSTC_ALLOW_FEATURES") {
+        cmd.arg(format!("-Zallow-features={allow_features}"));
+    }
+
     if let Ok(flags) = env::var("MAGIC_EXTRA_RUSTFLAGS") {
         for flag in flags.split(' ') {
             cmd.arg(flag);
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index b54bf432621..1ae4ff52047 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1381,18 +1381,29 @@ impl<'a> Builder<'a> {
         // this), as well as #63012 which is the tracking issue for this
         // feature on the rustc side.
         cargo.arg("-Zbinary-dep-depinfo");
-        match mode {
-            Mode::ToolBootstrap => {
-                // Restrict the allowed features to those passed by rustbuild, so we don't depend on nightly accidentally.
-                rustflags.arg("-Zallow-features=binary-dep-depinfo");
-            }
-            Mode::ToolStd => {
-                // Right now this is just compiletest and a few other tools that build on stable.
-                // Allow them to use `feature(test)`, but nothing else.
-                rustflags.arg("-Zallow-features=binary-dep-depinfo,test,proc_macro_internals,proc_macro_diagnostic,proc_macro_span");
+        let allow_features = match mode {
+            Mode::ToolBootstrap | Mode::ToolStd => {
+                // Restrict the allowed features so we don't depend on nightly
+                // accidentally.
+                //
+                // binary-dep-depinfo is used by rustbuild itself for all
+                // compilations.
+                //
+                // Lots of tools depend on proc_macro2 and proc-macro-error.
+                // Those have build scripts which assume nightly features are
+                // available if the `rustc` version is "nighty" or "dev". See
+                // bin/rustc.rs for why that is a problem. Instead of labeling
+                // those features for each individual tool that needs them,
+                // just blanket allow them here.
+                //
+                // If this is ever removed, be sure to add something else in
+                // its place to keep the restrictions in place (or make a way
+                // to unset RUSTC_BOOTSTRAP).
+                "binary-dep-depinfo,proc_macro_span,proc_macro_span_shrink,proc_macro_diagnostic"
+                    .to_string()
             }
-            Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {}
-        }
+            Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => String::new(),
+        };
 
         cargo.arg("-j").arg(self.jobs().to_string());
 
@@ -1915,7 +1926,7 @@ impl<'a> Builder<'a> {
             }
         }
 
-        Cargo { command: cargo, rustflags, rustdocflags }
+        Cargo { command: cargo, rustflags, rustdocflags, allow_features }
     }
 
     /// Ensure that a given step is built, returning its output. This will
@@ -2094,6 +2105,7 @@ pub struct Cargo {
     command: Command,
     rustflags: Rustflags,
     rustdocflags: Rustflags,
+    allow_features: String,
 }
 
 impl Cargo {
@@ -2138,6 +2150,18 @@ impl Cargo {
         self.command.current_dir(dir);
         self
     }
+
+    /// Adds nightly-only features that this invocation is allowed to use.
+    ///
+    /// By default, all nightly features are allowed. Once this is called, it
+    /// will be restricted to the given set.
+    pub fn allow_features(&mut self, features: &str) -> &mut Cargo {
+        if !self.allow_features.is_empty() {
+            self.allow_features.push(',');
+        }
+        self.allow_features.push_str(features);
+        self
+    }
 }
 
 impl From<Cargo> for Command {
@@ -2152,6 +2176,10 @@ impl From<Cargo> for Command {
             cargo.command.env("RUSTDOCFLAGS", rustdocflags);
         }
 
+        if !cargo.allow_features.is_empty() {
+            cargo.command.env("RUSTC_ALLOW_FEATURES", cargo.allow_features);
+        }
+
         cargo.command
     }
 }
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index b203ecd3844..72e5dc6f4df 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -332,9 +332,7 @@ impl Step for RustAnalyzer {
             &["rust-analyzer/in-rust-tree".to_owned()],
         );
 
-        cargo.rustflag(
-            "-Zallow-features=proc_macro_internals,proc_macro_diagnostic,proc_macro_span",
-        );
+        cargo.allow_features(crate::tool::RustAnalyzer::ALLOW_FEATURES);
 
         // For ./x.py clippy, don't check those targets because
         // linting tests and benchmarks can produce very noisy results
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index ea906be7e3a..208321c7bfd 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -378,6 +378,7 @@ impl Step for RustAnalyzer {
             SourceType::InTree,
             &["sysroot-abi".to_owned()],
         );
+        cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
 
         let dir = builder.src.join(workspace_path);
         // needed by rust-analyzer to find its own text fixtures, cf.
@@ -690,7 +691,7 @@ impl Step for CompiletestTest {
         // We need `ToolStd` for the locally-built sysroot because
         // compiletest uses unstable features of the `test` crate.
         builder.ensure(compile::Std::new(compiler, host));
-        let cargo = tool::prepare_tool_cargo(
+        let mut cargo = tool::prepare_tool_cargo(
             builder,
             compiler,
             Mode::ToolStd,
@@ -700,6 +701,7 @@ impl Step for CompiletestTest {
             SourceType::InTree,
             &[],
         );
+        cargo.allow_features("test");
 
         try_run(builder, &mut cargo.into());
     }
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 63026bd44d4..08c74782455 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -29,6 +29,8 @@ struct ToolBuild {
     is_optional_tool: bool,
     source_type: SourceType,
     extra_features: Vec<String>,
+    /// Nightly-only features that are allowed (comma-separated list).
+    allow_features: &'static str,
 }
 
 impl Step for ToolBuild {
@@ -59,7 +61,7 @@ impl Step for ToolBuild {
             _ => panic!("unexpected Mode for tool build"),
         }
 
-        let cargo = prepare_tool_cargo(
+        let mut cargo = prepare_tool_cargo(
             builder,
             compiler,
             self.mode,
@@ -69,6 +71,9 @@ impl Step for ToolBuild {
             self.source_type,
             &self.extra_features,
         );
+        if !self.allow_features.is_empty() {
+            cargo.allow_features(self.allow_features);
+        }
 
         builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target));
         let mut duplicates = Vec::new();
@@ -292,6 +297,7 @@ macro_rules! bootstrap_tool {
         $name:ident, $path:expr, $tool_name:expr
         $(,is_external_tool = $external:expr)*
         $(,is_unstable_tool = $unstable:expr)*
+        $(,allow_features = $allow_features:expr)?
         ;
     )+) => {
         #[derive(Copy, PartialEq, Eq, Clone)]
@@ -355,6 +361,7 @@ macro_rules! bootstrap_tool {
                         SourceType::InTree
                     },
                     extra_features: vec![],
+                    allow_features: concat!($($allow_features)*),
                 }).expect("expected to build -- essential tool")
             }
         }
@@ -368,7 +375,7 @@ bootstrap_tool!(
     Tidy, "src/tools/tidy", "tidy";
     Linkchecker, "src/tools/linkchecker", "linkchecker";
     CargoTest, "src/tools/cargotest", "cargotest";
-    Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true;
+    Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = "test";
     BuildManifest, "src/tools/build-manifest", "build-manifest";
     RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
     RustInstaller, "src/tools/rust-installer", "rust-installer", is_external_tool = true;
@@ -435,6 +442,7 @@ impl Step for ErrorIndex {
                 is_optional_tool: false,
                 source_type: SourceType::InTree,
                 extra_features: Vec::new(),
+                allow_features: "",
             })
             .expect("expected to build -- essential tool")
     }
@@ -471,6 +479,7 @@ impl Step for RemoteTestServer {
                 is_optional_tool: false,
                 source_type: SourceType::InTree,
                 extra_features: Vec::new(),
+                allow_features: "",
             })
             .expect("expected to build -- essential tool")
     }
@@ -622,6 +631,7 @@ impl Step for Cargo {
                 is_optional_tool: false,
                 source_type: SourceType::Submodule,
                 extra_features: Vec::new(),
+                allow_features: "",
             })
             .expect("expected to build -- essential tool");
 
@@ -637,6 +647,7 @@ impl Step for Cargo {
                 is_optional_tool: true,
                 source_type: SourceType::Submodule,
                 extra_features: Vec::new(),
+                allow_features: "",
             });
         };
 
@@ -684,6 +695,7 @@ impl Step for LldWrapper {
                 is_optional_tool: false,
                 source_type: SourceType::InTree,
                 extra_features: Vec::new(),
+                allow_features: "",
             })
             .expect("expected to build -- essential tool");
 
@@ -697,6 +709,11 @@ pub struct RustAnalyzer {
     pub target: TargetSelection,
 }
 
+impl RustAnalyzer {
+    pub const ALLOW_FEATURES: &str =
+        "proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink";
+}
+
 impl Step for RustAnalyzer {
     type Output = Option<PathBuf>;
     const DEFAULT: bool = true;
@@ -731,6 +748,7 @@ impl Step for RustAnalyzer {
             extra_features: vec!["rust-analyzer/in-rust-tree".to_owned()],
             is_optional_tool: false,
             source_type: SourceType::InTree,
+            allow_features: RustAnalyzer::ALLOW_FEATURES,
         })
     }
 }
@@ -769,6 +787,7 @@ impl Step for RustAnalyzerProcMacroSrv {
             extra_features: vec!["proc-macro-srv/sysroot-abi".to_owned()],
             is_optional_tool: false,
             source_type: SourceType::InTree,
+            allow_features: RustAnalyzer::ALLOW_FEATURES,
         })?;
 
         // Copy `rust-analyzer-proc-macro-srv` to `<sysroot>/libexec/`
@@ -788,6 +807,7 @@ macro_rules! tool_extended {
        $tool_name:expr,
        stable = $stable:expr
        $(,tool_std = $tool_std:literal)?
+       $(,allow_features = $allow_features:expr)?
        ;)+) => {
         $(
             #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -839,6 +859,7 @@ macro_rules! tool_extended {
                     extra_features: $sel.extra_features,
                     is_optional_tool: true,
                     source_type: SourceType::InTree,
+                    allow_features: concat!($($allow_features)*),
                 })
             }
         }
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 33c05180408..b296aa2f4e6 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -5,10 +5,10 @@ license = "MIT OR Apache-2.0"
 edition = "2021"
 
 [dependencies]
-clap = "3.1.1"
+clap = "4.0.32"
 env_logger = "0.7.1"
 
 [dependencies.mdbook]
-version = "0.4.21"
+version = "0.4.25"
 default-features = false
 features = ["search"]
diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs
index 3c7dc0183d7..1368ec653de 100644
--- a/src/tools/rustbook/src/main.rs
+++ b/src/tools/rustbook/src/main.rs
@@ -9,18 +9,21 @@ use mdbook::errors::Result as Result3;
 use mdbook::MDBook;
 
 fn main() {
-    let crate_version = format!("v{}", crate_version!());
+    let crate_version = concat!("v", crate_version!());
     env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init();
     let d_arg = arg!(-d --"dest-dir" <DEST_DIR>
 "The output directory for your book\n(Defaults to ./book when omitted)")
-    .required(false);
-    let dir_arg = arg!([dir]
-"A directory for your book\n(Defaults to Current Directory when omitted)");
+    .required(false)
+    .value_parser(clap::value_parser!(PathBuf));
+
+    let dir_arg = arg!([dir] "Root directory for the book\n\
+                              (Defaults to the current directory when omitted)")
+    .value_parser(clap::value_parser!(PathBuf));
 
     let matches = Command::new("rustbook")
         .about("Build a book with mdBook")
         .author("Steve Klabnik <steve@steveklabnik.com>")
-        .version(&*crate_version)
+        .version(crate_version)
         .subcommand_required(true)
         .arg_required_else_help(true)
         .subcommand(
@@ -60,8 +63,8 @@ pub fn build(args: &ArgMatches) -> Result3<()> {
     // Set this to allow us to catch bugs in advance.
     book.config.build.create_missing = false;
 
-    if let Some(dest_dir) = args.value_of("dest-dir") {
-        book.config.build.build_dir = PathBuf::from(dest_dir);
+    if let Some(dest_dir) = args.get_one::<PathBuf>("dest-dir") {
+        book.config.build.build_dir = dest_dir.into();
     }
 
     book.build()?;
@@ -76,10 +79,9 @@ fn test(args: &ArgMatches) -> Result3<()> {
 }
 
 fn get_book_dir(args: &ArgMatches) -> PathBuf {
-    if let Some(dir) = args.value_of("dir") {
+    if let Some(p) = args.get_one::<PathBuf>("dir") {
         // Check if path is relative from current dir, or absolute...
-        let p = Path::new(dir);
-        if p.is_relative() { env::current_dir().unwrap().join(dir) } else { p.to_path_buf() }
+        if p.is_relative() { env::current_dir().unwrap().join(p) } else { p.to_path_buf() }
     } else {
         env::current_dir().unwrap()
     }