コンパイラの依存関係における 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)
これで更新されたクレートを使用できます。この例では、古い動作を削除できることを意味しました。