There are two main ways of debugging (and profiling bootstrap). The first is through println logging, and the second is through the tracing feature.
println loggingBootstrap has extensive unstructured logging. Most of it is gated behind the --verbose flag (pass -vv for even more detail).
If you want to see verbose output of executed Cargo commands and other kinds of detailed logs, pass -v or -vv when invoking bootstrap. Note that the logs are unstructured and may be overwhelming.
$ ./x dist rustc --dry-run -vv learning about cargo running: RUSTC_BOOTSTRAP="1" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "metadata" "--format-version" "1" "--no-deps" "--manifest-path" "/home/jyn/src/rust2/Cargo.toml" (failure_mode=Exit) (created at src/bootstrap/src/core/metadata.rs:81:25, executed at src/bootstrap/src/core/metadata.rs:92:50) running: RUSTC_BOOTSTRAP="1" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "metadata" "--format-version" "1" "--no-deps" "--manifest-path" "/home/jyn/src/rust2/library/Cargo.toml" (failure_mode=Exit) (created at src/bootstrap/src/core/metadata.rs:81:25, executed at src/bootstrap/src/core/metadata.rs:92:50) ...
tracing in bootstrapBootstrap has a conditional tracing feature, which provides the following features:
tracing events and spans.chrome-trace.json file using Chrome, on the chrome://tracing tab, or e.g. using Perfetto.step-graph-*.dot file using e.g. xdot to visualize the step graph, or use e.g. dot -Tsvg to convert the GraphViz file to an SVG file.command-stats.txt file is in a simple human-readable format.The structured logs will be written to standard error output (stderr), while the other outputs will be stored in files in the <build-dir>/bootstrap-trace/<pid> directory. For convenience, bootstrap will also create a symlink to the latest generated trace output directory at <build-dir>/bootstrap-trace/latest.
Note that if you execute bootstrap with
--dry-run, the tracing output directory might change. Bootstrap will always print a path where the tracing output files were stored at the end of its execution.
tracing outputTo enable the conditional tracing feature, run bootstrap with the BOOTSTRAP_TRACING environment variable.
$ BOOTSTRAP_TRACING=trace ./x build library --stage 1
Example output[^unstable]:
$ BOOTSTRAP_TRACING=trace ./x build library --stage 1 --dry-run
Building bootstrap
Finished `dev` profile [unoptimized] target(s) in 0.05s
15:56:52.477 INFO > tool::LibcxxVersionTool {target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715)
15:56:52.575 INFO > compile::Assemble {target_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }} (builder/mod.rs:1715)
15:56:52.575 INFO > tool::Compiletest {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715)
15:56:52.576 INFO > tool::ToolBuild {build_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, tool: "compiletest", path: "src/tools/compiletest", mode: ToolBootstrap, source_type: InTree, extra_features: [], allow_features: "internal_output_capture", cargo_args: [], artifact_kind: Binary} (builder/mod.rs:1715)
15:56:52.576 INFO > builder::Libdir {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715)
15:56:52.576 INFO > compile::Sysroot {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, force_recompile: false} (builder/mod.rs:1715)
15:56:52.578 INFO > compile::Assemble {target_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }} (builder/mod.rs:1715)
15:56:52.578 INFO > tool::Compiletest {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715)
15:56:52.578 INFO > tool::ToolBuild {build_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, tool: "compiletest", path: "src/tools/compiletest", mode: ToolBootstrap, source_type: InTree, extra_features: [], allow_features: "internal_output_capture", cargo_args: [], artifact_kind: Binary} (builder/mod.rs:1715)
15:56:52.578 INFO > builder::Libdir {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715)
15:56:52.578 INFO > compile::Sysroot {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, force_recompile: false} (builder/mod.rs:1715)
Finished `release` profile [optimized] target(s) in 0.11s
Tracing/profiling output has been written to <src-root>/build/bootstrap-trace/latest
Build completed successfully in 0:00:00
[^unstable]: This output is always subject to further changes.
The environment variable BOOTSTRAP_TRACING accepts a tracing_subscriber filter. If you set BOOTSTRAP_TRACING=trace, you will enable all logs, but that can be overwhelming. You can thus use the filter to reduce the amount of data logged.
There are two orthogonal ways to control which kind of tracing logs you want:
debug or trace.bootstrap or bootstrap::core::config or a custom target like CONFIG_HANDLING or STEP.BOOTSTRAP_TRACING=trace output can be quite verbose. Currently, you can use the following custom targets:CONFIG_HANDLING: show spans related to config handling.STEP: show all executed steps. Executed commands have info event level.COMMAND: show all executed commands. Executed commands have trace event level.IO: show performed I/O operations. Executed commands have trace event level.You can of course combine them (custom target logs are typically gated behind TRACE log level additionally):
$ BOOTSTRAP_TRACING=CONFIG_HANDLING=trace,STEP=info,COMMAND=trace ./x build library --stage 1
Note that the level that you specify using BOOTSTRAP_TRACING also has an effect on the spans that will be recorded in the Chrome trace file.
compiler() vs compiler_for()The additional targets COMPILER and COMPILER_FOR are used to help trace what builder.compiler() and builder.compiler_for() does. They should be removed if #96176 is resolved.
tracing in bootstrapBoth tracing::* macros and the tracing::instrument proc-macro attribute need to be gated behind tracing feature. Examples:
#[cfg(feature = "tracing")] use tracing::instrument; struct Foo; impl Step for Foo { type Output = (); #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Foo::should_run", skip_all))] fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { trace!(?run, "entered Foo::should_run"); todo!() } fn run(self, builder: &Builder<'_>) -> Self::Output { trace!(?run, "entered Foo::run"); todo!() } }
For #[instrument], it's recommended to:
trace level for fine-granularity, possibly debug level for core functions.name = ".." to distinguish between e.g. run of different steps.Unfortunately, because bootstrap is a rust-analyzer.linkedProjects, you can't ask r-a to check/build bootstrap itself with tracing feature enabled to get relevant completions, due to lack of support as described in https://github.com/rust-lang/rust-analyzer/issues/8521.