Bazel は、プラットフォームとツールチェーンのモデリングを高度にサポートしています。これを実際のプロジェクトと統合するには、コード所有者、ルールメンテナンス担当者、コア Bazel 開発者が慎重に協力する必要があります。
このページでは、プラットフォームの目的の概要と、プラットフォームを使用して構築する方法について説明します。
tl;dr: Bazel のプラットフォーム API とツールチェーン API は利用可能ですが、すべての言語ルール、select()
、その他のレガシー リファレンスが更新されるまで、どこでも動作しません。これは継続的な取り組みです。最終的には、すべてのビルドがプラットフォームベースになります。ビルドの位置付けについては、以下をご覧ください。
より正式なドキュメントについては、以下をご覧ください。
背景情報
ソフトウェア プロジェクトがさまざまなマシンをターゲットにし、適切な言語ツールでビルドする方法を標準化するために、プラットフォームとツールチェーンが導入されました。
これは比較的最近追加された Bazel です。これは、言語のメンテナンス担当者が互換性のない方法でアドホックな方法でこれを行っているという観察からインスピレーションを得ています。たとえば、C++ ルールでは --cpu
と --crosstool_top
を使用して、ビルドのターゲット CPU と C++ ツールチェーンを設定します。どちらも「プラットフォーム」を正しくモデル化しません。歴史的にそのような試みは、見づらく不正確なビルドの原因となっていました。
これらのフラグは Java コンパイルも制御しません。Java コンパイルは、--java_toolchain
によって独自の独立したインターフェースを進化させています。
Bazel は、大規模な多言語、マルチプラットフォーム プロジェクトを対象としています。そのため、言語とプロジェクトの相互運用性を促進する明確な API など、これらのコンセプトに対する原則に基づくサポートが必要になります。これが新しい API の用途です
移行
プラットフォーム API とツールチェーン API は、プロジェクトで実際に使用する場合にのみ機能します。これは、プロジェクトのルールロジック、ツールチェーン、依存関係、select()
がサポートする必要があるため、簡単ではありません。すべてのプロジェクトとその依存関係を正常に動作させるには、移行を慎重に行う必要があります。
たとえば、Bazel の C++ ルールのサポート プラットフォームなどです。しかし、Apple のルールはそうではありません。C++ プロジェクトでは Apple を考慮していない場合があります。そのため、すべての C++ ビルドに対してプラットフォームをグローバルに有効にすることは、まだ安全ではありません。
このページの残りの部分では、この移行シーケンスと、プロジェクトが適合する仕組みとタイミングについて説明します。
目標
すべてのプロジェクトが次の形式でビルドされたら、Bazel のプラットフォームの移行は完了です。
bazel build //:myproject --platforms=//:myplatform
これは以下を意味します。
- プロジェクトで使用するルールは、
//:myplatform
から正しいツールチェーンを推測できます。 - プロジェクトの依存関係が使用するルールは、
//:myplatform
から正しいツールチェーンを推測できます。 - 使用するプロジェクトに依存するプロジェクトが
//:myplatform
をサポートしているか、またはプロジェクトで以前の API(--crosstool_top
など)をサポートしているかのどちらかです。 //:myplatform
は、CPU
、OS
、および自動プロジェクト間の互換性をサポートするその他の一般的なコンセプトの [共通宣言][共通プラットフォーム宣言]{: .external} を参照します。- 関連するすべてのプロジェクトの
select()
は、//:myplatform
によって暗黙的に示唆されるマシン プロパティを理解します。 //:myplatform
は、明確で再利用可能な場所で定義されます。プラットフォームがプロジェクトに固有の場合はプロジェクトのリポジトリ、それ以外の場合、このプラットフォームを使用するすべてのプロジェクトが検出できる場所です。
この目的が達成され次第、古い API は削除されます。これは、プロジェクトでプラットフォームとツールチェーンを選択する標準的な方法です。
プラットフォームを使用するべきですか?
プロジェクトの構築またはクロスコンパイルのみを行う場合は、プロジェクトの公式ドキュメントに従ってください。
プロジェクト、言語、ツールチェーンの管理者は、最終的に新しい API をサポートする必要があります。グローバル移行が完了するまで待つか、早期にオプトインするかは、価値と費用のニーズによって異なります。
価値
--cpu
などのハードコードされたフラグの代わりに、select()
を使用するか、または、目的のプロパティに対してツールチェーンを選択します。たとえば、複数の CPU が同じ命令セットをサポートできます。- ビルドの精度が向上。上記の例で
--cpu
を指定してselect()
を実行し、同じ命令セットをサポートする新しい CPU を追加すると、select()
は新しい CPU を認識できません。ただし、プラットフォームのselect()
は依然として正確です。 - シンプルなユーザー エクスペリエンス。すべてのプロジェクトが
--platforms=//:myplatform
を認識します。コマンドラインで複数の言語固有のフラグを使用する必要はありません。 - シンプルな言語デザイン。すべての言語で、ツールチェーンの定義、ツールチェーンの使用、プラットフォームに適したツールチェーンの選択のための共通の API が共有されています。
- ターゲットがターゲット プラットフォームと互換性がない場合は、ビルドとテストのフェーズでスキップできます。
料金
- プラットフォームをまだサポートしていない依存プロジェクトは、自動的には連携しない可能性があります。
- それらを機能させるには、追加の一時的なメンテナンスが必要になる場合があります。
- 新しい API と以前の API を共存させる場合、混乱を避けるために、より慎重なユーザー ガイダンスが必要になります。
OS
やCPU
などの共通プロパティの正規定義はまだ発展途上であり、追加の初期コントリビューションが必要になる場合があります。- 言語固有のツールチェーンの正規の定義はまだ発展途上であり、追加の初期コントリビューションが必要になる場合があります。
API の審査
platform
は、constraint_value
ターゲットのコレクションです。
platform(
name = "myplatform",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm",
],
)
constraint_value
はマシンのプロパティです。同じ「種類」の値は、共通の constraint_setting
でグループ化されます。
constraint_setting(name = "os")
constraint_value(
name = "linux",
constraint_setting = ":os",
)
constraint_value(
name = "mac",
constraint_setting = ":os",
)
toolchain
は Starlark ルールです。その属性で言語のツール(compiler =
"//mytoolchain:custom_gcc"
など)を宣言します。プロバイダは、これらのツールでビルドする必要があるルールにこの情報を渡します。
ツールチェーンでは、ターゲットにするマシン(target_compatible_with = ["@platforms//os:linux"]
)とツールを実行できるマシン(exec_compatible_with = ["@platforms//os:mac"]
)の constraint_value
を宣言します。
$ bazel build //:myproject --platforms=//:myplatform
をビルドする際、Bazel は、ビルドマシンで実行できるツールチェーンと //:myplatform
のビルドバイナリを自動的に選択します。これをツールチェーンの解決といいます。
使用可能なツールチェーンのセットは、register_toolchains
を使用して WORKSPACE
で登録するか、--extra_toolchains
を使用してコマンドラインで登録できます。
詳しくは、こちらをご覧ください。
ステータス
現在のプラットフォームのサポートは言語によって異なります。Bazel の主要なルールはすべてプラットフォームに移行しています。しかし、このプロセスには時間がかかります。これには、主に次の 3 つの理由があります。
新しいツールチェーン API(
ctx.toolchains
)からツール情報を取得し、--cpu
や--crosstool_top
などの以前の設定の読み取りを停止するには、ルールのロジックを更新する必要があります。これは比較的簡単です。ツールチェーンのメンテナンス担当者は、ツールチェーンを定義し、ユーザーが(GitHub リポジトリと
WORKSPACE
エントリで)アクセスできるようにする必要があります。これは技術的には単純ですが、簡単なユーザー エクスペリエンスを維持するには、インテリジェントに整理する必要があります。プラットフォームの定義も必要です(Bazel が実行されているマシンでビルドする場合を除く)。一般的に、プロジェクトでは独自のプラットフォームを定義する必要があります。
既存のプロジェクトは移行する必要があります。
select()
と移行も移行する必要があります。これが最大の課題です。これは多言語プロジェクトでは特に困難です(すべての言語で--platforms
を読み取れない場合に失敗する可能性があります)。
新しいルールセットを設計する場合は、最初からプラットフォームをサポートする必要があります。これにより、ルールと他のルールやプロジェクトとの互換性が自動的に確保され、プラットフォーム API がより広く普及するにつれて価値も大きくなります。
プラットフォームの一般的なプロパティ
プロジェクトに共通する OS
や CPU
などのプラットフォーム プロパティは、一元化された標準的な場所で宣言する必要があります。これにより、プロジェクト間および言語間の互換性が促進されます。
たとえば、MyApp の constraint_value
@myapp//cpus:arm
に select()
があり、@commonlib//constraints:arm
で SomeCommonLib に select()
がある場合、互換性のない基準で「arm」モードがトリガーされます。
グローバルに共通のプロパティは @platforms
リポジトリで宣言されています(そのため、上記の例の正規ラベルは @platforms//cpu:arm
です)。言語共通プロパティは、それぞれの言語のリポジトリで宣言する必要があります。
デフォルトのプラットフォーム
一般に、プロジェクト オーナーは、ビルド対象のマシンの種類を定義する明示的なプラットフォームを定義する必要があります。その後、これらは --platforms
でトリガーされます。
--platforms
が設定されていない場合、Bazel はデフォルトでローカル ビルドマシンを表す platform
になります。これは @local_config_platform//:host
に自動生成されるため、明示的に定義する必要はありません。ローカルマシンの OS
と CPU
を、@platforms
で宣言された constraint_value
にマッピングします。
C++
Bazel の C++ ルールでは、--incompatible_enable_cc_toolchain_resolution
を設定する際にプラットフォームを使用してツールチェーンを選択します(#7260)。
つまり、以下を使用して C++ プロジェクトを構成できます。
bazel build //:my_cpp_project --platforms=//:myplatform
できます。
bazel build //:my_cpp_project` --cpu=... --crosstool_top=... --compiler=...
プロジェクトが純粋な C++ であり、C++ 以外のプロジェクトに依存しない場合は、select
と遷移に互換性がある限り、プラットフォームを安全に使用できます。詳しくは、#7260 と C++ ツールチェーンの構成をご覧ください。
このモードはデフォルトでは有効になっていません。これは、Apple プロジェクトが --cpu
と --crosstool_top
を使用して C++ 依存関係をまだ構成しているためです(例)。これは、プラットフォームに移行する Apple のルールに依存します。
Java
Bazel の Java ルールではプラットフォームを使用します。
これは、以前のフラグ --java_toolchain
、--host_java_toolchain
、--javabase
、--host_javabase
に代わるものです。
構成フラグの使用方法については、Bazel と Java のマニュアルをご覧ください。 詳細については、設計ドキュメントをご覧ください。
まだ以前のフラグを使用している場合は、問題 #7849 の移行プロセスに沿って対応してください。
Android
Bazel の Android ルールでは、--incompatible_enable_android_toolchain_resolution
を設定する際にプラットフォームを使用してツールチェーンを選択します。
これはデフォルトでは有効になっていません。しかし、移行は順調に進んでいます。
Apple
Bazel の Apple ルールは、Apple ツールチェーンを選択するプラットフォームをまだサポートしていません。
また、プラットフォーム対応の C++ 依存関係もサポートしていません。これらは、以前の --crosstool_top
を使用して C++ ツールチェーンを設定するためです。移行が完了するまでは、Apple プロジェクトと、プラットフォームが有効な C++ をプラットフォーム マッピングで混在させることができます(例)。
その他の言語
新しい言語のルールを設計する場合は、プラットフォームを使用して言語のツールチェーンを選択します。適切なチュートリアルについては、ツールチェーンのドキュメントをご覧ください。
select()
プロジェクトは、constraint_value
ターゲットで select()
できますが、完全なプラットフォームでは行えません。これは、select()
ができるだけ多くの種類のマシンをサポートすることを意図したものです。ARM
固有のソースを含むライブラリは、より具体的にする理由がない限り、すべての ARM
搭載マシンをサポートする必要があります。
1 つ以上の constraint_value
を選択するには、次のコマンドを使用します。
config_setting(
name = "is_arm",
constraint_values = [
"@platforms//cpu:arm",
],
)
これは、従来の --cpu
の選択と同じです。
config_setting(
name = "is_arm",
values = {
"cpu": "arm",
},
)
詳しくはこちらをご覧ください。
--cpu
、--crosstool_top
などの select
が --platforms
を認識できません。プロジェクトをプラットフォームに移行する場合は、プロジェクトを constraint_values
に変換するか、プラットフォーム マッピングを使用して移行ウィンドウで両方のスタイルをサポートする必要があります。
切り替え効果
Starlark 遷移の変更フラグは、ビルドグラフの一部を下に向けます。プロジェクトで、--cpu
、--crossstool_top
などの以前のフラグを設定する遷移を使用している場合、--platforms
を読み取るルールではこれらの変更は発生しません。
プロジェクトをプラットフォームに移行する場合は、return { "//command_line_option:cpu": "arm" }
などの変更を return {
"//command_line_option:platforms": "//:my_arm_platform" }
に変換するか、プラットフォーム マッピングを使用して移行ウィンドウで両方のスタイルをサポートする必要があります。
プラットフォームの活用方法
プロジェクトをビルドするか、クロスコンパイルするだけの場合は、プロジェクトの公式ドキュメントに従ってください。プラットフォームと統合する方法とタイミング、提供する価値は、言語とプロジェクトの管理者が決定します。
プロジェクト、言語、ツールチェーンの管理者で、ビルドがデフォルトでプラットフォームを使用していない場合、(グローバル移行を待つ以外に)3 つのオプションがあります。
プロジェクトの言語(ある場合)の「プラットフォームの使用」フラグをオンにして、必要なプロジェクトをすべて試し、必要なプロジェクトが機能するかどうかを確認します。
対象のプロジェクトが
--cpu
や--crosstool_top
などの以前のフラグに依存している場合は、--platforms
とともに使用します。bazel build //:my_mixed_project --platforms==//:myplatform --cpu=... --crosstool_top=...
これにはメンテナンス費用がかかります(設定の一致を手動で確認する必要があります)。しかし、これは反反遷移がない場合でも機能します。
--cpu
スタイル設定を対応するプラットフォームにマッピング(またはその逆)することで、両方のスタイルをサポートするプラットフォーム マッピングを作成します。
プラットフォームのマッピング
プラットフォーム マッピングは一時的な API です。これにより、後者のサポート終了まで、同じビルドにプラットフォームが提供するロジックとレガシーを利用したロジックを共存させることができます。
プラットフォーム マッピングは、platform()
と対応する以前のフラグのセット、またはその逆のマップです。次に例を示します。
platforms:
# Maps "--platforms=//platforms:ios" to "--cpu=ios_x86_64 --apple_platform_type=ios".
//platforms:ios
--cpu=ios_x86_64
--apple_platform_type=ios
flags:
# Maps "--cpu=ios_x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
--cpu=ios_x86_64
--apple_platform_type=ios
//platforms:ios
# Maps "--cpu=darwin --apple_platform_type=macos" to "//platform:macos".
--cpu=darwin
--apple_platform_type=macos
//platforms:macos
Bazel はこれを使用して、移行を含め、すべての設定(プラットフォーム ベースと以前の設定の両方)がビルド全体に一貫して適用されることを保証します。
デフォルトでは、Bazel はワークスペースのルートにある platform_mappings
ファイルからマッピングを読み取ります。--platform_mappings=//:my_custom_mapping
を設定することもできます。
詳しくは、こちらをご覧ください。
質問
移行のタイムラインに関する一般的なサポートや質問については、bazel-discuss@googlegroups.com または適切なルールのオーナーにお問い合わせください。
プラットフォーム/ツールチェーン API の設計と進化については、bazel-dev@googlegroups.com までお問い合わせください。