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

コンパイラの依存関係における cfg(bootstrap)

Rustコンパイラは、コンパイラ自身との間で巡回依存に陥る可能性がある外部クレートをいくつか使用しています。つまり、コンパイラはビルドするために更新されたクレートを必要としますが、そのクレートは更新されたコンパイラを必要とします。このページでは、この循環を断ち切るために #[cfg(bootstrap)] をどのように使用できるかを説明します。

#[cfg(bootstrap)] の有効化

通常、外部クレートで #[cfg(bootstrap)] を使用すると警告が発生します。

warning: unexpected `cfg` condition name: `bootstrap`
 --> src/main.rs:1:7
  |
1 | #[cfg(bootstrap)]
  |       ^^^^^^^^^
  |
  = help: expected names are: `docsrs`, `feature`, and `test` and 31 more
  = help: consider using a Cargo feature instead
  = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
           [lints.rust]
           unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bootstrap)'] }
  = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(bootstrap)");` to the top of the `build.rs`
  = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
  = note: `#[warn(unexpected_cfgs)]` on by default

この警告は、プロジェクトの Cargo.toml に次の行を追加することで抑制できます。

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bootstrap)'] }

これで、コンパイラ内で使用できるのと同じように、クレート内で #[cfg(bootstrap)] を使用できます。ブートストラップコンパイラが使用されている場合は #[cfg(bootstrap)] が付与されたコードがコンパイルされ、それ以外の場合は #[cfg(not(bootstrap))] が付与されたコードがコンパイルされます。

更新の一連の手順

具体例として、#[naked] 属性を unsafe 属性に変更したことで、compiler-builtins クレートとの巡回依存が発生した変更を取り上げます。

ステップ 1: コンパイラで新しい動作を受け入れる(#139797

この例では、エラーを無効にすることで、古い動作と新しい動作の両方を同時に受け入れることができます。

ステップ 2: クレートを更新する(#821

次にクレート内で、古い動作を使用するために #[cfg(bootstrap)] を使用するか、新しい動作を使用するために #[cfg(not(bootstrap))] を使用します。

ステップ 3: コンパイラで使用するクレートのバージョンを更新する(#139934

compiler-builtins の場合、これはバージョンの引き上げを意味しました。他の場合では、gitサブモジュールの更新になることもあります。

ステップ 4: コンパイラから古い動作を削除する(#139753

これで更新されたクレートを使用できます。この例では、古い動作を削除できることを意味しました。