Simplify command-line-option declarations in the compiler

This commit is contained in:
Zalathar 2024-11-07 22:47:15 +11:00
parent 584c8200de
commit 001013c63c

View File

@ -12,7 +12,7 @@
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::{self, FromStr}; use std::str::{self, FromStr};
use std::sync::LazyLock; use std::sync::LazyLock;
use std::{fmt, fs, iter}; use std::{cmp, fmt, fs, iter};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
@ -1367,11 +1367,36 @@ pub fn build_target_config(early_dcx: &EarlyDiagCtxt, opts: &Options, sysroot: &
} }
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum OptionStability { pub enum OptionStability {
Stable, Stable,
Unstable, Unstable,
} }
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum OptionKind {
/// An option that takes a value, and cannot appear more than once (e.g. `--out-dir`).
///
/// Corresponds to [`getopts::Options::optopt`].
Opt,
/// An option that takes a value, and can appear multiple times (e.g. `--emit`).
///
/// Corresponds to [`getopts::Options::optmulti`].
Multi,
/// An option that does not take a value, and cannot appear more than once (e.g. `--help`).
///
/// Corresponds to [`getopts::Options::optflag`].
/// The `hint` string must be empty.
Flag,
/// An option that does not take a value, and can appear multiple times (e.g. `-O`).
///
/// Corresponds to [`getopts::Options::optflagmulti`].
/// The `hint` string must be empty.
FlagMulti,
}
pub struct RustcOptGroup { pub struct RustcOptGroup {
apply: Box<dyn Fn(&mut getopts::Options) -> &mut getopts::Options>, apply: Box<dyn Fn(&mut getopts::Options) -> &mut getopts::Options>,
pub name: &'static str, pub name: &'static str,
@ -1402,58 +1427,37 @@ pub fn unstable<F>(name: &'static str, f: F) -> RustcOptGroup
} }
} }
// The `opt` local module holds wrappers around the `getopts` API that pub fn make_opt(
// adds extra rustc-specific metadata to each option; such metadata stability: OptionStability,
// is exposed by . The public kind: OptionKind,
// functions below ending with `_u` are the functions that return short_name: &'static str,
// *unstable* options, i.e., options that are only enabled when the long_name: &'static str,
// user also passes the `-Z unstable-options` debugging flag. desc: &'static str,
mod opt { hint: &'static str,
// The `fn flag*` etc below are written so that we can use them ) -> RustcOptGroup {
// in the future; do not warn about them not being used right now. RustcOptGroup {
#![allow(dead_code)] name: cmp::max_by_key(short_name, long_name, |s| s.len()),
stability,
use super::RustcOptGroup; apply: match kind {
OptionKind::Opt => Box::new(move |opts: &mut getopts::Options| {
type R = RustcOptGroup; opts.optopt(short_name, long_name, desc, hint)
type S = &'static str; }),
OptionKind::Multi => Box::new(move |opts: &mut getopts::Options| {
fn stable<F>(name: S, f: F) -> R opts.optmulti(short_name, long_name, desc, hint)
where }),
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, OptionKind::Flag => {
{ assert_eq!(hint, "");
RustcOptGroup::stable(name, f) Box::new(move |opts: &mut getopts::Options| {
} opts.optflag(short_name, long_name, desc)
})
fn unstable<F>(name: S, f: F) -> R }
where OptionKind::FlagMulti => {
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, assert_eq!(hint, "");
{ Box::new(move |opts: &mut getopts::Options| {
RustcOptGroup::unstable(name, f) opts.optflagmulti(short_name, long_name, desc)
} })
}
fn longer(a: S, b: S) -> S { },
if a.len() > b.len() { a } else { b }
}
pub(crate) fn opt_s(a: S, b: S, c: S, d: S) -> R {
stable(longer(a, b), move |opts| opts.optopt(a, b, c, d))
}
pub(crate) fn multi_s(a: S, b: S, c: S, d: S) -> R {
stable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
}
pub(crate) fn flag_s(a: S, b: S, c: S) -> R {
stable(longer(a, b), move |opts| opts.optflag(a, b, c))
}
pub(crate) fn flagmulti_s(a: S, b: S, c: S) -> R {
stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
}
fn opt(a: S, b: S, c: S, d: S) -> R {
unstable(longer(a, b), move |opts| opts.optopt(a, b, c, d))
}
pub(crate) fn multi(a: S, b: S, c: S, d: S) -> R {
unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
} }
} }
@ -1468,46 +1472,60 @@ pub(crate) fn multi(a: S, b: S, c: S, d: S) -> R {
/// including metadata for each option, such as whether the option is /// including metadata for each option, such as whether the option is
/// part of the stable long-term interface for rustc. /// part of the stable long-term interface for rustc.
pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> { pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
use OptionKind::{Flag, FlagMulti, Multi, Opt};
use OptionStability::Stable;
use self::make_opt as opt;
vec![ vec![
opt::flag_s("h", "help", "Display this message"), opt(Stable, Flag, "h", "help", "Display this message", ""),
opt::multi_s("", "cfg", "Configure the compilation environment. opt(
SPEC supports the syntax `NAME[=\"VALUE\"]`.", "SPEC"), Stable,
opt::multi_s("", "check-cfg", "Provide list of expected cfgs for checking", "SPEC"), Multi,
opt::multi_s( "",
"cfg",
"Configure the compilation environment.\n\
SPEC supports the syntax `NAME[=\"VALUE\"]`.",
"SPEC",
),
opt(Stable, Multi, "", "check-cfg", "Provide list of expected cfgs for checking", "SPEC"),
opt(
Stable,
Multi,
"L", "L",
"", "",
"Add a directory to the library search path. The "Add a directory to the library search path. \
optional KIND can be one of dependency, crate, native, The optional KIND can be one of dependency, crate, native, framework, or all (the default).",
framework, or all (the default).",
"[KIND=]PATH", "[KIND=]PATH",
), ),
opt::multi_s( opt(
Stable,
Multi,
"l", "l",
"", "",
"Link the generated crate(s) to the specified native "Link the generated crate(s) to the specified native\n\
library NAME. The optional KIND can be one of library NAME. The optional KIND can be one of\n\
static, framework, or dylib (the default). static, framework, or dylib (the default).\n\
Optional comma separated MODIFIERS (bundle|verbatim|whole-archive|as-needed) Optional comma separated MODIFIERS\n\
may be specified each with a prefix of either '+' to (bundle|verbatim|whole-archive|as-needed)\n\
enable or '-' to disable.", may be specified each with a prefix of either '+' to\n\
enable or '-' to disable.",
"[KIND[:MODIFIERS]=]NAME[:RENAME]", "[KIND[:MODIFIERS]=]NAME[:RENAME]",
), ),
make_crate_type_option(), make_crate_type_option(),
opt::opt_s("", "crate-name", "Specify the name of the crate being built", "NAME"), opt(Stable, Opt, "", "crate-name", "Specify the name of the crate being built", "NAME"),
opt::opt_s( opt(Stable, Opt, "", "edition", &EDITION_STRING, EDITION_NAME_LIST),
"", opt(
"edition", Stable,
&EDITION_STRING, Multi,
EDITION_NAME_LIST,
),
opt::multi_s(
"", "",
"emit", "emit",
"Comma separated list of types of output for \ "Comma separated list of types of output for the compiler to emit",
the compiler to emit",
"[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]", "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]",
), ),
opt::multi_s( opt(
Stable,
Multi,
"", "",
"print", "print",
"Compiler information to print on stdout", "Compiler information to print on stdout",
@ -1516,41 +1534,36 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
tls-models|target-spec-json|all-target-specs-json|native-static-libs|\ tls-models|target-spec-json|all-target-specs-json|native-static-libs|\
stack-protector-strategies|link-args|deployment-target]", stack-protector-strategies|link-args|deployment-target]",
), ),
opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""),
opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=2", ""),
opt::opt_s("o", "", "Write output to <filename>", "FILENAME"), opt(Stable, Opt, "o", "", "Write output to <filename>", "FILENAME"),
opt::opt_s( opt(Stable, Opt, "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
"", opt(
"out-dir", Stable,
"Write output to compiler-chosen filename \ Opt,
in <dir>",
"DIR",
),
opt::opt_s(
"", "",
"explain", "explain",
"Provide a detailed explanation of an error \ "Provide a detailed explanation of an error message",
message",
"OPT", "OPT",
), ),
opt::flag_s("", "test", "Build a test harness"), opt(Stable, Flag, "", "test", "Build a test harness", ""),
opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"), opt(Stable, Opt, "", "target", "Target triple for which the code is compiled", "TARGET"),
opt::multi_s("A", "allow", "Set lint allowed", "LINT"), opt(Stable, Multi, "A", "allow", "Set lint allowed", "LINT"),
opt::multi_s("W", "warn", "Set lint warnings", "LINT"), opt(Stable, Multi, "W", "warn", "Set lint warnings", "LINT"),
opt::multi_s("", "force-warn", "Set lint force-warn", "LINT"), opt(Stable, Multi, "", "force-warn", "Set lint force-warn", "LINT"),
opt::multi_s("D", "deny", "Set lint denied", "LINT"), opt(Stable, Multi, "D", "deny", "Set lint denied", "LINT"),
opt::multi_s("F", "forbid", "Set lint forbidden", "LINT"), opt(Stable, Multi, "F", "forbid", "Set lint forbidden", "LINT"),
opt::multi_s( opt(
Stable,
Multi,
"", "",
"cap-lints", "cap-lints",
"Set the most restrictive lint level. \ "Set the most restrictive lint level. More restrictive lints are capped at this level",
More restrictive lints are capped at this \
level",
"LEVEL", "LEVEL",
), ),
opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"), opt(Stable, Multi, "C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
opt::flag_s("V", "version", "Print version info and exit"), opt(Stable, Flag, "V", "version", "Print version info and exit", ""),
opt::flag_s("v", "verbose", "Use verbose output"), opt(Stable, Flag, "v", "verbose", "Use verbose output", ""),
] ]
} }
@ -1558,25 +1571,36 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
/// each option, such as whether the option is part of the stable /// each option, such as whether the option is part of the stable
/// long-term interface for rustc. /// long-term interface for rustc.
pub fn rustc_optgroups() -> Vec<RustcOptGroup> { pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
use OptionKind::{Multi, Opt};
use OptionStability::{Stable, Unstable};
use self::make_opt as opt;
let mut opts = rustc_short_optgroups(); let mut opts = rustc_short_optgroups();
// FIXME: none of these descriptions are actually used // FIXME: none of these descriptions are actually used
opts.extend(vec![ opts.extend(vec![
opt::multi_s( opt(
Stable,
Multi,
"", "",
"extern", "extern",
"Specify where an external rust library is located", "Specify where an external rust library is located",
"NAME[=PATH]", "NAME[=PATH]",
), ),
opt::opt_s("", "sysroot", "Override the system root", "PATH"), opt(Stable, Opt, "", "sysroot", "Override the system root", "PATH"),
opt::multi("Z", "", "Set unstable / perma-unstable options", "FLAG"), opt(Unstable, Multi, "Z", "", "Set unstable / perma-unstable options", "FLAG"),
opt::opt_s( opt(
Stable,
Opt,
"", "",
"error-format", "error-format",
"How errors and other messages are produced", "How errors and other messages are produced",
"human|json|short", "human|json|short",
), ),
opt::multi_s("", "json", "Configure the JSON output of the compiler", "CONFIG"), opt(Stable, Multi, "", "json", "Configure the JSON output of the compiler", "CONFIG"),
opt::opt_s( opt(
Stable,
Opt,
"", "",
"color", "color",
"Configure coloring of output: "Configure coloring of output:
@ -1585,19 +1609,23 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
never = never colorize output", never = never colorize output",
"auto|always|never", "auto|always|never",
), ),
opt::opt_s( opt(
Stable,
Opt,
"", "",
"diagnostic-width", "diagnostic-width",
"Inform rustc of the width of the output so that diagnostics can be truncated to fit", "Inform rustc of the width of the output so that diagnostics can be truncated to fit",
"WIDTH", "WIDTH",
), ),
opt::multi_s( opt(
Stable,
Multi,
"", "",
"remap-path-prefix", "remap-path-prefix",
"Remap source names in all output (compiler messages and output files)", "Remap source names in all output (compiler messages and output files)",
"FROM=TO", "FROM=TO",
), ),
opt::multi("", "env-set", "Inject an environment variable", "VAR=VALUE"), opt(Unstable, Multi, "", "env-set", "Inject an environment variable", "VAR=VALUE"),
]); ]);
opts opts
} }
@ -2760,7 +2788,9 @@ fn parse_pretty(early_dcx: &EarlyDiagCtxt, unstable_opts: &UnstableOptions) -> O
} }
pub fn make_crate_type_option() -> RustcOptGroup { pub fn make_crate_type_option() -> RustcOptGroup {
opt::multi_s( make_opt(
OptionStability::Stable,
OptionKind::Multi,
"", "",
"crate-type", "crate-type",
"Comma separated list of types of crates "Comma separated list of types of crates