From 05d37ae2c0f7119c3034ebcc0023d9bbbfdbac35 Mon Sep 17 00:00:00 2001 From: bors Date: Tue, 20 Apr 2021 21:58:22 +0000 Subject: [PATCH] Fix #9350 (cargo build -Z help is missing options) > Do not merge yet, some options are still undocumented. Fix #9350 (cargo build -Z help is missing options) Add a procedural macro to declare `CliUnstable` struct and provide help messages instead of hard-coding help in `src/bin/cargo/cli.rs` > Flags documentation: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html Feedback welcome --- src/bin/cargo/cli.rs | 42 ++++++---- src/cargo/core/compiler/job_queue.rs | 2 +- src/cargo/core/compiler/mod.rs | 2 +- src/cargo/core/features.rs | 112 ++++++++++++++++----------- src/cargo/util/command_prelude.rs | 2 +- tests/testsuite/help.rs | 4 +- 6 files changed, 101 insertions(+), 63 deletions(-) diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index 55d7bd9bfdc..b891836cb90 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -1,10 +1,11 @@ -use cargo::core::features; +use cargo::core::{features, CliUnstable}; use cargo::{self, drop_print, drop_println, CliResult, Config}; use clap::{AppSettings, Arg, ArgMatches}; use super::commands; use super::list_commands; use crate::command_prelude::*; +use cargo::core::features::HIDDEN; pub fn main(config: &mut Config) -> CliResult { // CAUTION: Be careful with using `config` until it is configured below. @@ -30,25 +31,38 @@ pub fn main(config: &mut Config) -> CliResult { }; if args.value_of("unstable-features") == Some("help") { + let options = CliUnstable::help(); + let non_hidden_options: Vec<(String, String)> = options + .iter() + .filter(|(_, help_message)| *help_message != HIDDEN) + .map(|(name, help)| (name.to_string(), help.to_string())) + .collect(); + let longest_option = non_hidden_options + .iter() + .map(|(option_name, _)| option_name.len()) + .max() + .unwrap_or(0); + let help_lines: Vec = non_hidden_options + .iter() + .map(|(option_name, option_help_message)| { + let option_name_kebab_case = option_name.replace("_", "-"); + let padding = " ".repeat(longest_option - option_name.len()); // safe to substract + format!( + " -Z {}{} -- {}", + option_name_kebab_case, padding, option_help_message + ) + }) + .collect(); + let joined = help_lines.join("\n"); drop_println!( config, " Available unstable (nightly-only) flags: - -Z allow-features -- Allow *only* the listed unstable features - -Z avoid-dev-deps -- Avoid installing dev-dependencies if possible - -Z extra-link-arg -- Allow `cargo:rustc-link-arg` in build scripts - -Z minimal-versions -- Install minimal dependency versions instead of maximum - -Z no-index-update -- Do not update the registry, avoids a network request for benchmarking - -Z unstable-options -- Allow the usage of unstable options - -Z timings -- Display concurrency information - -Z doctest-xcompile -- Compile and run doctests for non-host target using runner config - -Z terminal-width -- Provide a terminal width to rustc for error truncation - -Z namespaced-features -- Allow features with `dep:` prefix - -Z weak-dep-features -- Allow `dep_name?/feature` feature syntax - -Z patch-in-config -- Allow `[patch]` sections in .cargo/config.toml files +{} -Run with 'cargo -Z [FLAG] [SUBCOMMAND]'" +Run with 'cargo -Z [FLAG] [SUBCOMMAND]'", + joined ); if !config.nightly_features_allowed { drop_println!( diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index 4491b1fd649..96c26fdab67 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -808,7 +808,7 @@ impl<'cfg> DrainState<'cfg> { } fn emit_future_incompat(&mut self, cx: &mut Context<'_, '_>) { - if cx.bcx.config.cli_unstable().enable_future_incompat_feature { + if cx.bcx.config.cli_unstable().future_incompat_report { if self.per_crate_future_incompat_reports.is_empty() { drop( cx.bcx diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index a1dddf1ad82..b994a6ce4dd 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -936,7 +936,7 @@ fn build_base_args( .env("RUSTC_BOOTSTRAP", "1"); } - if bcx.config.cli_unstable().enable_future_incompat_feature { + if bcx.config.cli_unstable().future_incompat_report { cmd.arg("-Z").arg("emit-future-incompat-report"); } diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 88b4e47e787..62520b8c953 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -68,7 +68,6 @@ //! get an instance of `CliUnstable` and check if the option has been //! enabled on the `CliUnstable` instance. Nightly gating is already //! handled, so no need to worry about that. -//! 4. Update the `-Z help` documentation in the `main` function. //! //! ## Stabilization //! @@ -83,9 +82,9 @@ //! 2. `-Z unstable-options`: Find the call to `fail_if_stable_opt` and //! remove it. Be sure to update the man pages if necessary. //! 3. `-Z` flag: Change the parsing code in [`CliUnstable::add`] to call -//! `stabilized_warn` or `stabilized_err`. Remove it from the `-Z help` -//! docs in the `main` function. Remove the `(unstable)` note in the -//! clap help text if necessary. +//! `stabilized_warn` or `stabilized_err` and remove the field from +//! `CliUnstable. Remove the `(unstable)` note in the clap help text if +//! necessary. //! 2. Remove `masquerade_as_nightly_cargo` from any tests, and remove //! `cargo-features` from `Cargo.toml` test files if any. //! 3. Remove the docs from unstable.md and update the redirect at the bottom @@ -105,6 +104,7 @@ use crate::util::errors::CargoResult; use crate::util::{indented_lines, iter_join}; use crate::Config; +pub const HIDDEN: &str = ""; pub const SEE_CHANNELS: &str = "See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information \ about Rust release channels."; @@ -538,51 +538,73 @@ impl Features { } } -/// A parsed representation of all unstable flags that Cargo accepts. -/// -/// Cargo, like `rustc`, accepts a suite of `-Z` flags which are intended for -/// gating unstable functionality to Cargo. These flags are only available on -/// the nightly channel of Cargo. -#[derive(Default, Debug, Deserialize)] -#[serde(default, rename_all = "kebab-case")] -pub struct CliUnstable { +macro_rules! unstable_cli_options { + ( + $( + $(#[$meta:meta])? + $element: ident: $ty: ty = ($help: expr ) + ),* + ) => { + /// A parsed representation of all unstable flags that Cargo accepts. + /// + /// Cargo, like `rustc`, accepts a suite of `-Z` flags which are intended for + /// gating unstable functionality to Cargo. These flags are only available on + /// the nightly channel of Cargo. + #[derive(Default, Debug, Deserialize)] + #[serde(default, rename_all = "kebab-case")] + pub struct CliUnstable { + $( + $(#[$meta])? + pub $element: $ty + ),* + } + impl CliUnstable { + pub fn help() -> Vec<(&'static str, &'static str)> { + let fields = vec![$((stringify!($element), $help)),*]; + fields + } + } + } +} + +unstable_cli_options!( // Permanently unstable features: - pub allow_features: Option>, - pub print_im_a_teapot: bool, + allow_features: Option> = ("Allow *only* the listed unstable features"), + print_im_a_teapot: bool= (HIDDEN), // All other unstable features. // Please keep this list lexiographically ordered. - pub advanced_env: bool, - pub avoid_dev_deps: bool, - pub binary_dep_depinfo: bool, + advanced_env: bool = (HIDDEN), + avoid_dev_deps: bool = ("Avoid installing dev-dependencies if possible"), + binary_dep_depinfo: bool = ("Track changes to dependency artifacts"), #[serde(deserialize_with = "deserialize_build_std")] - pub build_std: Option>, - pub build_std_features: Option>, - pub config_include: bool, - pub configurable_env: bool, - pub credential_process: bool, - pub doctest_in_workspace: bool, - pub doctest_xcompile: bool, - pub dual_proc_macros: bool, - pub enable_future_incompat_feature: bool, - pub extra_link_arg: bool, - pub features: Option>, - pub jobserver_per_rustc: bool, - pub minimal_versions: bool, - pub mtime_on_use: bool, - pub multitarget: bool, - pub named_profiles: bool, - pub namespaced_features: bool, - pub no_index_update: bool, - pub panic_abort_tests: bool, - pub patch_in_config: bool, - pub rustdoc_map: bool, - pub separate_nightlies: bool, - pub terminal_width: Option>, - pub timings: Option>, - pub unstable_options: bool, - pub weak_dep_features: bool, -} + build_std: Option> = ("Enable Cargo to compile the standard library itself as part of a crate graph compilation"), + build_std_features: Option> = ("Configure features enabled for the standard library itself when building the standard library"), + config_include: bool = ("Enable the `include` key in config files"), + configurable_env: bool = ("Enable the [env] section in the .cargo/config.toml file"), + credential_process: bool = ("Add a config setting to fetch registry authentication tokens by calling an external process"), + doctest_in_workspace: bool = ("Compile doctests with paths relative to the workspace root"), + doctest_xcompile: bool = ("Compile and run doctests for non-host target using runner config"), + dual_proc_macros: bool = ("Build proc-macros for both the host and the target"), + future_incompat_report: bool = ("Enable creation of a future-incompat report for all dependencies"), + extra_link_arg: bool = ("Allow `cargo:rustc-link-arg` in build scripts"), + features: Option> = (HIDDEN), + jobserver_per_rustc: bool = (HIDDEN), + minimal_versions: bool = ("Resolve minimal dependency versions instead of maximum"), + mtime_on_use: bool = ("Configure Cargo to update the mtime of used files"), + multitarget: bool = ("Allow passing multiple `--target` flags to the cargo subcommand selected"), + named_profiles: bool = ("Allow defining custom profiles"), + namespaced_features: bool = ("Allow features with `dep:` prefix"), + no_index_update: bool = ("Do not update the registry index even if the cache is outdated"), + panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"), + patch_in_config: bool = ("Allow `[patch]` sections in .cargo/config.toml files"), + rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"), + separate_nightlies: bool = (HIDDEN), + terminal_width: Option> = ("Provide a terminal width to rustc for error truncation"), + timings: Option> = ("Display concurrency information"), + unstable_options: bool = ("Allow the usage of unstable options"), + weak_dep_features: bool = ("Allow `dep_name?/feature` feature syntax") +); const STABILIZED_COMPILE_PROGRESS: &str = "The progress bar is now always \ enabled when used on an interactive console.\n\ @@ -798,7 +820,7 @@ impl CliUnstable { "config-profile" => stabilized_warn(k, "1.43", STABILIZED_CONFIG_PROFILE), "crate-versions" => stabilized_warn(k, "1.47", STABILIZED_CRATE_VERSIONS), "package-features" => stabilized_warn(k, "1.51", STABILIZED_PACKAGE_FEATURES), - "future-incompat-report" => self.enable_future_incompat_feature = parse_empty(k, v)?, + "future-incompat-report" => self.future_incompat_report = parse_empty(k, v)?, _ => bail!("unknown `-Z` flag specified: {}", k), } diff --git a/src/cargo/util/command_prelude.rs b/src/cargo/util/command_prelude.rs index 3b5d9a7e23a..4515b11d81d 100644 --- a/src/cargo/util/command_prelude.rs +++ b/src/cargo/util/command_prelude.rs @@ -488,7 +488,7 @@ pub trait ArgMatchesExt { // TODO: Tracking issue .fail_if_stable_opt("--future-incompat-report", 9241)?; - if !config.cli_unstable().enable_future_incompat_feature { + if !config.cli_unstable().future_incompat_report { anyhow::bail!( "Usage of `--future-incompat-report` requires `-Z future-incompat-report`" ) diff --git a/tests/testsuite/help.rs b/tests/testsuite/help.rs index 5b2a87d0461..0f094e44a8c 100644 --- a/tests/testsuite/help.rs +++ b/tests/testsuite/help.rs @@ -48,7 +48,9 @@ fn z_flags_help() { // Test that the output of `cargo -Z help` shows a different help screen with // all the `-Z` flags. cargo_process("-Z help") - .with_stdout_contains(" -Z unstable-options -- Allow the usage of unstable options") + .with_stdout_contains( + " -Z allow-features[..]-- Allow *only* the listed unstable features", + ) .run(); }