Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

bootstrap のデバッグ

デバッグ(および bootstrap のプロファイリング)には、主に 2 つの方法があります。1 つ目は println ロギングによる方法で、2 つ目は tracing 機能による方法です。

println ロギング

Bootstrap には、構造化されていない広範なロギングがあります。その大半は --verbose フラグの背後にゲートされています(さらに詳細を得るには -vv を渡します)。

実行された Cargo コマンドの詳細な出力や、その他の種類の詳細ログを確認したい場合は、bootstrap を呼び出すときに -v または -vv を渡してください。ログは構造化されておらず、圧倒される量になる可能性があることに注意してください。

$ ./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)
...

bootstrap における tracing

Bootstrap には条件付きの tracing 機能があり、次の機能を提供します。

  • tracing のイベントと span を使用した構造化ロギングを有効にします。
  • 実行されたステップとコマンドの階層と所要時間を可視化するために使用できる Chrome trace file を生成します。
    • 生成された chrome-trace.json ファイルは、Chrome の chrome://tracing タブで開けます。または、たとえば Perfetto を使用して開けます。
  • 実行されたステップ間の依存関係を可視化する GraphViz グラフを生成します。
    • 生成された step-graph-*.dot ファイルは、たとえば xdot を使用して開いてステップグラフを可視化できます。または、たとえば dot -Tsvg を使用して GraphViz ファイルを SVG ファイルに変換できます。
  • コマンド実行サマリーを生成します。これには、どのコマンドが実行されたか、それらの実行のうちいくつがキャッシュされたか、実行に最も時間がかかったコマンドはどれかが示されます。
    • 生成された command-stats.txt ファイルは、シンプルで人間が読みやすい形式です。

構造化ログは標準エラー出力(stderr)に書き込まれます。一方、その他の出力は <build-dir>/bootstrap-trace/<pid> ディレクトリ内のファイルに保存されます。利便性のため、bootstrap は最後に生成されたトレース出力ディレクトリへのシンボリックリンクも <build-dir>/bootstrap-trace/latest に作成します。

--dry-run で bootstrap を実行すると、tracing 出力ディレクトリが変わる可能性があることに注意してください。Bootstrap は、実行の最後に tracing 出力ファイルが保存されたパスを常に表示します。

tracing 出力の有効化

条件付きの tracing 機能を有効にするには、BOOTSTRAP_TRACING 環境変数を指定して bootstrap を実行します。

$ BOOTSTRAP_TRACING=trace ./x build library --stage 1

出力例1:

$ 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

tracing 出力の制御

環境変数 BOOTSTRAP_TRACING は、tracing_subscriber フィルター を受け付けます。BOOTSTRAP_TRACING=trace を設定すると、すべてのログが有効になりますが、圧倒される量になる可能性があります。そのため、フィルターを使用してログに記録されるデータ量を減らすことができます。

どの種類の tracing ログを必要とするかを制御するには、互いに直交する 2 つの方法があります。

  1. ログのレベルを指定できます。例: debug または trace
    • レベルを選択すると、同等またはより高い優先度レベルを持つすべてのイベント/スパンが表示されます。
  2. ログのターゲットも制御できます。例: bootstrapbootstrap::core::config、または CONFIG_HANDLINGSTEP のようなカスタムターゲット。
    • カスタムターゲットは、関心のあるスパンの種類を限定するために使用されます。BOOTSTRAP_TRACING=trace の出力は非常に冗長になる可能性があるためです。現在、以下のカスタムターゲットを使用できます。
      • CONFIG_HANDLING: config 処理に関連するスパンを表示します。
      • STEP: 実行されたすべてのステップを表示します。実行されたコマンドは info イベントレベルを持ちます。
      • COMMAND: 実行されたすべてのコマンドを表示します。実行されたコマンドは trace イベントレベルを持ちます。
      • IO: 実行された I/O 操作を表示します。実行されたコマンドは trace イベントレベルを持ちます。
        • 現在、多くの I/O はトレースされていないことに注意してください。

もちろん、これらを組み合わせることもできます(カスタムターゲットログは通常、追加で TRACE ログレベルの背後で制御されます)。

$ BOOTSTRAP_TRACING=CONFIG_HANDLING=trace,STEP=info,COMMAND=trace ./x build library --stage 1

BOOTSTRAP_TRACING を使用して指定するレベルは、Chrome トレースファイルに記録されるスパンにも影響することに注意してください。

FIXME(#96176): compiler()compiler_for() の個別の tracing

追加のターゲット COMPILERCOMPILER_FOR は、 builder.compiler()builder.compiler_for() が何を行うかをトレースするのに役立ちます。 #96176 が解決された場合、これらは削除されるべきです。

bootstrap で tracing を使用する

tracing::* マクロと tracing::instrument proc-macro 属性の両方を、tracing feature の背後で制御する必要があります。例:

#[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!()
    }    
}

#[instrument] については、以下が推奨されます。

  • 細かい粒度では trace レベルの背後で制御し、コア関数では場合によって debug レベルの背後で制御します。
  • name = ".." を通じて instrumentation 名を明示的に選択し、たとえば異なるステップの run を区別します。
  • tracing によって挙動の分岐を引き起こさないよう注意してください。たとえば、tracing 基盤が有効な場合にのみ追加のものをビルドする、といったことです。

rust-analyzer 統合?

残念ながら、bootstrap は rust-analyzer.linkedProjects であるため、https://github.com/rust-lang/rust-analyzer/issues/8521 で説明されているようにサポートが不足しており、関連する補完を得るために tracing feature を有効にして bootstrap 自体をチェック/ビルドするよう r-a に依頼することはできません。


  1. この出力は常に今後変更される可能性があります。