Skip to content

Commit 8fedea1

Browse files
committed
write x.py's help for saving output time
Currently x.py help (or x.py --help) builds bootstrap binary everytime, but it delays printing help. This change saves the current help text into a file. x.py help prints the file and doesn't touch bootstrap binary. x.py test bootstrap checks if the file is up to date.
1 parent f56eb06 commit 8fedea1

File tree

6 files changed

+176
-16
lines changed

6 files changed

+176
-16
lines changed

src/bootstrap/bootstrap.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,13 +1375,17 @@ def main():
13751375
args = parse_args(sys.argv)
13761376
help_triggered = args.help or len(sys.argv) == 1
13771377

1378-
# If the user is asking for help, let them know that the whole download-and-build
1379-
# process has to happen before anything is printed out.
1378+
# If the user is asking for help, it prints commands from the saved file.
13801379
if help_triggered:
1381-
eprint(
1382-
"INFO: Downloading and building bootstrap before processing --help command.\n"
1383-
" See src/bootstrap/README.md for help with common commands."
1384-
)
1380+
try:
1381+
with open(os.path.join(os.path.dirname(__file__), "../etc/xhelp"), "r") as f:
1382+
# The file from bootstrap func already has newline.
1383+
print(f.read(), end="")
1384+
sys.exit(0)
1385+
except Exception as error:
1386+
eprint(f"ERROR: unable to run help: {error}")
1387+
eprint("x.py run generate-help may solve the problem.")
1388+
sys.exit(1)
13851389

13861390
exit_code = 0
13871391
success_word = "successfully"
@@ -1395,13 +1399,13 @@ def main():
13951399
eprint(error)
13961400
success_word = "unsuccessfully"
13971401

1398-
if not help_triggered:
1399-
eprint(
1400-
"Build completed",
1401-
success_word,
1402-
"in",
1403-
format_build_time(time() - start_time),
1404-
)
1402+
eprint(
1403+
"Build completed",
1404+
success_word,
1405+
"in",
1406+
format_build_time(time() - start_time),
1407+
)
1408+
14051409
sys.exit(exit_code)
14061410

14071411

src/bootstrap/src/core/build_steps/run.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::core::build_steps::tool::{self, RustcPrivateCompilers, SourceType, To
1414
use crate::core::build_steps::vendor::{Vendor, default_paths_to_vendor};
1515
use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
1616
use crate::core::config::TargetSelection;
17-
use crate::core::config::flags::get_completion;
17+
use crate::core::config::flags::{get_completion, get_help};
1818
use crate::utils::exec::command;
1919
use crate::{Mode, t};
2020

@@ -501,3 +501,31 @@ impl Step for Rustfmt {
501501
rustfmt.into_cmd().run(builder);
502502
}
503503
}
504+
505+
/// Return the path of x.py's help.
506+
pub fn get_help_path(builder: &Builder<'_>) -> PathBuf {
507+
builder.src.join("src/etc/xhelp")
508+
}
509+
510+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
511+
pub struct GenerateHelp;
512+
513+
impl Step for GenerateHelp {
514+
type Output = ();
515+
516+
fn run(self, builder: &Builder<'_>) {
517+
let path = get_help_path(builder);
518+
if let Some(help) = get_help(&path) {
519+
std::fs::write(&path, help)
520+
.unwrap_or_else(|e| panic!("writing help into {} failed: {e:?}", path.display()));
521+
}
522+
}
523+
524+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
525+
run.alias("generate-help")
526+
}
527+
528+
fn make_run(run: RunConfig<'_>) {
529+
run.builder.ensure(GenerateHelp)
530+
}
531+
}

src/bootstrap/src/core/build_steps/test.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::core::build_steps::compile::{Std, run_cargo};
1515
use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler};
1616
use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
1717
use crate::core::build_steps::llvm::get_llvm_version;
18-
use crate::core::build_steps::run::get_completion_paths;
18+
use crate::core::build_steps::run::{get_completion_paths, get_help_path};
1919
use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
2020
use crate::core::build_steps::tool::{
2121
self, COMPILETEST_ALLOW_FEATURES, RustcPrivateCompilers, SourceType,
@@ -28,7 +28,7 @@ use crate::core::builder::{
2828
crate_description,
2929
};
3030
use crate::core::config::TargetSelection;
31-
use crate::core::config::flags::{Subcommand, get_completion};
31+
use crate::core::config::flags::{Subcommand, get_completion, get_help};
3232
use crate::utils::build_stamp::{self, BuildStamp};
3333
use crate::utils::exec::{BootstrapCommand, command};
3434
use crate::utils::helpers::{
@@ -1293,6 +1293,15 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to
12931293
);
12941294
crate::exit!(1);
12951295
}
1296+
1297+
builder.info("x.py help check");
1298+
let help_path = get_help_path(builder);
1299+
if builder.config.cmd.bless() {
1300+
builder.ensure(crate::core::build_steps::run::GenerateHelp);
1301+
} else if get_help(&help_path).is_some() {
1302+
eprintln!("x.py help was changed; run `x.py run generate-help` to update them");
1303+
crate::exit!(1);
1304+
}
12961305
}
12971306

12981307
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {

src/bootstrap/src/core/builder/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,7 @@ impl<'a> Builder<'a> {
12241224
run::CyclicStep,
12251225
run::CoverageDump,
12261226
run::Rustfmt,
1227+
run::GenerateHelp,
12271228
),
12281229
Kind::Setup => {
12291230
describe!(setup::Profile, setup::Hook, setup::Link, setup::Editor)

src/bootstrap/src/core/config/flags.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,3 +701,25 @@ pub fn get_completion(shell: &dyn Generator, path: &Path) -> Option<String> {
701701
}
702702
Some(String::from_utf8(buf).expect("completion script should be UTF-8"))
703703
}
704+
705+
/// Return the help of the bootstrap if the result differs from the current
706+
/// help in `path`. It always returns the help if `path` does not exist.
707+
pub fn get_help(path: &Path) -> Option<String> {
708+
let mut cmd = Flags::command();
709+
let cur_help = if !path.exists() {
710+
String::new()
711+
} else {
712+
std::fs::read_to_string(path).unwrap_or_else(|_| {
713+
eprintln!("couldn't read {}", path.display());
714+
crate::exit!(1)
715+
})
716+
};
717+
718+
let new_help: clap::builder::StyledStr = cmd.render_help();
719+
720+
if new_help.to_string() == cur_help {
721+
return None;
722+
}
723+
724+
Some(new_help.to_string())
725+
}

src/etc/xhelp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
2+
Usage: x.py <subcommand> [options] [<paths>...]
3+
4+
Commands:
5+
build Compile either the compiler or libraries
6+
check Compile either the compiler or libraries, using cargo check
7+
clippy Run Clippy (uses rustup/cargo-installed clippy binary)
8+
fix Run cargo fix
9+
fmt Run rustfmt
10+
doc Build documentation
11+
test Build and run some test suites
12+
miri Build and run some test suites *in Miri*
13+
bench Build and run some benchmarks
14+
clean Clean out build directories
15+
dist Build distribution artifacts
16+
install Install distribution artifacts
17+
run Run tools contained in this repository
18+
setup Set up the environment for development
19+
vendor Vendor dependencies
20+
perf Perform profiling and benchmarking of the compiler using `rustc-perf`
21+
22+
Arguments:
23+
[PATHS]... paths for the subcommand
24+
[ARGS]... arguments passed to subcommands
25+
26+
Options:
27+
-v, --verbose...
28+
use verbose output (-vv for very verbose)
29+
-i, --incremental
30+
use incremental compilation
31+
--config <FILE>
32+
TOML configuration file for build
33+
--build-dir <DIR>
34+
Build directory, overrides `build.build-dir` in `bootstrap.toml`
35+
--build <BUILD>
36+
host target of the stage0 compiler
37+
--host <HOST>
38+
host targets to build
39+
--target <TARGET>
40+
target targets to build
41+
--exclude <PATH>
42+
build paths to exclude
43+
--skip <PATH>
44+
build paths to skip
45+
--include-default-paths
46+
include default paths in addition to the provided ones
47+
--rustc-error-format <RUSTC_ERROR_FORMAT>
48+
rustc error format
49+
--on-fail <CMD>
50+
command to run on failure
51+
--dry-run
52+
dry run; don't build anything
53+
--dump-bootstrap-shims
54+
Indicates whether to dump the work done from bootstrap shims
55+
--stage <N>
56+
stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)
57+
--keep-stage <N>
58+
stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)
59+
--keep-stage-std <N>
60+
stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)
61+
--src <DIR>
62+
path to the root of the rust checkout
63+
-j, --jobs <JOBS>
64+
number of jobs to run in parallel
65+
--warnings <deny|warn>
66+
if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour [default: default] [possible values: deny, warn, default]
67+
--json-output
68+
use message-format=json
69+
--compile-time-deps
70+
only build proc-macros and build scripts (for rust-analyzer)
71+
--color <STYLE>
72+
whether to use color in cargo and rustc output [default: auto] [possible values: always, never, auto]
73+
--bypass-bootstrap-lock
74+
Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)
75+
--rust-profile-generate <PROFILE>
76+
generate PGO profile with rustc build
77+
--rust-profile-use <PROFILE>
78+
use PGO profile for rustc build
79+
--llvm-profile-use <PROFILE>
80+
use PGO profile for LLVM build
81+
--llvm-profile-generate
82+
generate PGO profile with llvm built for rustc
83+
--enable-bolt-settings
84+
Enable BOLT link flags
85+
--skip-stage0-validation
86+
Skip stage0 compiler validation
87+
--reproducible-artifact <REPRODUCIBLE_ARTIFACT>
88+
Additional reproducible artifacts that should be added to the reproducible artifacts archive
89+
--set <section.option=value>
90+
override options in bootstrap.toml
91+
--ci <bool>
92+
Make bootstrap to behave as it's running on the CI environment or not [possible values: true, false]
93+
--skip-std-check-if-no-download-rustc
94+
Skip checking the standard library if `rust.download-rustc` isn't available. This is mostly for RA as building the stage1 compiler to check the library tree on each code change might be too much for some computers
95+
-h, --help
96+
Print help (see more with '--help')

0 commit comments

Comments
 (0)