33//! This module implements the command-line parsing of the build system which
44//! has various flags to configure how it's run.
55
6- use std::path::PathBuf;
6+ use std::path::{Path, PathBuf} ;
77
8- use clap::{Parser, ValueEnum};
8+ use clap::{CommandFactory, Parser, ValueEnum};
99
1010use crate::builder::{Builder, Kind};
1111use crate::config::{target_selection_list, Config, TargetSelectionList};
@@ -54,15 +54,15 @@ pub struct Flags {
5454 /// Build directory, overrides `build.build-dir` in `config.toml`
5555 pub build_dir: Option<PathBuf>,
5656
57- #[arg(global(true), long, value_name = "BUILD")]
57+ #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "BUILD")]
5858 /// build target of the stage0 compiler
5959 pub build: Option<String>,
6060
61- #[arg(global(true), long, value_name = "HOST", value_parser = target_selection_list)]
61+ #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "HOST", value_parser = target_selection_list)]
6262 /// host targets to build
6363 pub host: Option<TargetSelectionList>,
6464
65- #[arg(global(true), long, value_name = "TARGET", value_parser = target_selection_list)]
65+ #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "TARGET", value_parser = target_selection_list)]
6666 /// target targets to build
6767 pub target: Option<TargetSelectionList>,
6868
@@ -73,7 +73,7 @@ pub struct Flags {
7373 /// include default paths in addition to the provided ones
7474 pub include_default_paths: bool,
7575
76- #[arg(global(true), long)]
76+ #[arg(global(true), value_hint = clap::ValueHint::Other, long)]
7777 pub rustc_error_format: Option<String>,
7878
7979 #[arg(global(true), long, value_hint = clap::ValueHint::CommandString, value_name = "CMD")]
@@ -82,16 +82,16 @@ pub struct Flags {
8282 #[arg(global(true), long)]
8383 /// dry run; don't build anything
8484 pub dry_run: bool,
85- #[arg(global(true), long, value_name = "N")]
85+ #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
8686 /// stage to build (indicates compiler to use/test, e.g., stage 0 uses the
8787 /// bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)
8888 pub stage: Option<u32>,
8989
90- #[arg(global(true), long, value_name = "N")]
90+ #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
9191 /// stage(s) to keep without recompiling
9292 /// (pass multiple times to keep e.g., both stages 0 and 1)
9393 pub keep_stage: Vec<u32>,
94- #[arg(global(true), long, value_name = "N")]
94+ #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
9595 /// stage(s) of the standard library to keep without recompiling
9696 /// (pass multiple times to keep e.g., both stages 0 and 1)
9797 pub keep_stage_std: Vec<u32>,
@@ -103,6 +103,7 @@ pub struct Flags {
103103 global(true),
104104 short,
105105 long,
106+ value_hint = clap::ValueHint::Other,
106107 default_value_t = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get),
107108 value_name = "JOBS"
108109 )]
@@ -117,7 +118,7 @@ pub struct Flags {
117118 /// otherwise, use the default configured behaviour
118119 pub warnings: Warnings,
119120
120- #[arg(global(true), long, value_name = "FORMAT")]
121+ #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "FORMAT")]
121122 /// rustc error format
122123 pub error_format: Option<String>,
123124 #[arg(global(true), long)]
@@ -133,13 +134,13 @@ pub struct Flags {
133134 #[arg(global(true), long, value_name = "VALUE")]
134135 pub llvm_skip_rebuild: Option<bool>,
135136 /// generate PGO profile with rustc build
136- #[arg(global(true), long, value_name = "PROFILE")]
137+ #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
137138 pub rust_profile_generate: Option<String>,
138139 /// use PGO profile for rustc build
139- #[arg(global(true), long, value_name = "PROFILE")]
140+ #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
140141 pub rust_profile_use: Option<String>,
141142 /// use PGO profile for LLVM build
142- #[arg(global(true), long, value_name = "PROFILE")]
143+ #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
143144 pub llvm_profile_use: Option<String>,
144145 // LLVM doesn't support a custom location for generating profile
145146 // information.
@@ -152,7 +153,7 @@ pub struct Flags {
152153 #[arg(global(true), long)]
153154 pub llvm_bolt_profile_generate: bool,
154155 /// use BOLT profile for LLVM build
155- #[arg(global(true), long, value_name = "PROFILE")]
156+ #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
156157 pub llvm_bolt_profile_use: Option<String>,
157158 #[arg(global(true))]
158159 /// paths for the subcommand
@@ -524,3 +525,23 @@ impl Subcommand {
524525 }
525526 }
526527}
528+
529+ /// Returns the shell completion for a given shell, if the result differs from the current
530+ /// content of `path`. If `path` does not exist, always returns `Some`.
531+ pub fn get_completion<G: clap_complete::Generator>(shell: G, path: &Path) -> Option<String> {
532+ let mut cmd = Flags::command();
533+ let current = if !path.exists() {
534+ String::new()
535+ } else {
536+ std::fs::read_to_string(path).unwrap_or_else(|_| {
537+ eprintln!("couldn't read {}", path.display());
538+ crate::detail_exit(1)
539+ })
540+ };
541+ let mut buf = Vec::new();
542+ clap_complete::generate(shell, &mut cmd, "x.py", &mut buf);
543+ if buf == current.as_bytes() {
544+ return None;
545+ }
546+ Some(String::from_utf8(buf).expect("completion script should be UTF-8"))
547+ }
0 commit comments