Bazel には、マルチアーキテクチャとクロス コンパイル ビルド用のプラットフォームとツールチェーンをモデル化するための高度なサポートが用意されています。
このページでは、このサポートの状況をまとめています。
関連項目:
ステータス
C++
C++ ルールでは、--incompatible_enable_cc_toolchain_resolution が設定されている場合にプラットフォームを使用してツールチェーンを選択します。
つまり、次のように C++ プロジェクトを構成できます。
bazel build //:my_cpp_project --platforms=//:myplatformではなく、
bazel build //:my_cpp_project` --cpu=... --crosstool_top=... --compiler=...これは Bazel 7.0 でデフォルトで有効になります(#7260)。
プラットフォームで C++ プロジェクトをテストするには、プロジェクトの移行と C++ ツールチェーンの構成をご覧ください。
Java
Java ルールは、プラットフォームを使用してツールチェーンを選択します。
これは、以前のフラグ --java_toolchain、--host_java_toolchain、--javabase、--host_javabase に代わるものです。
詳しくは、Java と Bazel をご覧ください。
Android
Android ルールは、--incompatible_enable_android_toolchain_resolution が設定されている場合にプラットフォームを使用してツールチェーンを選択します。
つまり、Android プロジェクトを次のように構成できます。
bazel build //:my_android_project --android_platforms=//:my_android_platform--android_crosstool_top、--android_cpu、--fat_apk_cpu などの以前のフラグを使用する代わりに、
これは Bazel 7.0 でデフォルトで有効になります(#16285)。
プラットフォームで Android プロジェクトをテストするには、プロジェクトの移行をご覧ください。
Apple
Apple ルールはプラットフォームをサポートしておらず、サポートの予定もありません。
プラットフォーム マッピングを使用すると、Apple ビルド(Apple ルールと純粋な C++ の混合でビルドする場合など)でプラットフォーム API を引き続き使用できます。
その他の言語
言語ルールセットを所有している場合は、ルールセットの移行でサポートを追加する方法をご覧ください。
背景
プラットフォームとツールチェーンが導入され、ソフトウェア プロジェクトがさまざまなアーキテクチャをターゲットにしてクロス コンパイルする方法が標準化されました。
これは、言語のメンテナーがすでにアドホックで互換性のない方法でこれを行っているという観察に触発されたものです。たとえば、C++ ルールでは --cpu と --crosstool_top を使用して、ターゲット CPU とツールチェーンを宣言していました。どちらも「プラットフォーム」を正しくモデル化していません。これにより、不自然で不正確なビルドが生成されていました。
Java、Android、その他の言語では、同様の目的で独自のフラグが進化しましたが、相互運用性はありませんでした。これにより、言語間のビルドが混乱し、複雑になっていました。
Bazel は、大規模なマルチ言語、マルチプラットフォーム プロジェクトを対象としています。これには、明確な標準 API を含む、これらのコンセプトに対するより原則的なサポートが必要です。
移行の必要性
新しい API にアップグレードするには、API のリリースと、それを使用するためのルールロジックのアップグレードという 2 つの作業が必要です。
1 つ目は完了しましたが、2 つ目は進行中です。これには、言語固有のプラットフォームとツールチェーンが定義されていること、言語ロジックが --crosstool_top などの古いフラグではなく新しい API を介してツールチェーンを読み取ること、config_setting が古いフラグではなく新しい API で選択されることを確認することが含まれます。
この作業は簡単ですが、言語ごとに個別の作業が必要になります。また、プロジェクト オーナーに対して、今後の変更に対するテストを行うよう事前に警告する必要があります。
そのため、この移行は継続的に行われています。
目標
この移行は、すべてのプロジェクトがフォームでビルドされると完了します。
bazel build //:myproject --platforms=//:myplatformこれは以下を意味します。
- プロジェクトのルールによって、
//:myplatformに適したツールチェーンが選択されます。 - プロジェクトの依存関係によって、
//:myplatformに適したツールチェーンが選択されます。 //:myplatformは、CPU、OS、その他の言語に依存しない一般的なプロパティの共通の宣言を参照します。- 関連するすべての
select()が//:myplatformと適切に一致します。 //:myplatformは、明確でアクセス可能な場所で定義されます。プラットフォームがプロジェクトに固有の場合はプロジェクトの repo、すべての使用プロジェクトが検索できる共通の場所などです。
--cpu、--crosstool_top、--fat_apk_cpu などの古いフラグは、安全に削除できるようになったらすぐに非推奨となり、削除されます。
最終的には、これがアーキテクチャを構成する唯一の方法になります。
プロジェクトの移行
プラットフォームをサポートする言語でビルドする場合、ビルドは次のような呼び出しですでに動作しているはずです。
bazel build //:myproject --platforms=//:myplatform正確な詳細については、ステータスと使用している言語のドキュメントをご覧ください。
言語でプラットフォーム サポートを有効にするためにフラグが必要な場合は、そのフラグも設定する必要があります。詳しくは、ステータスをご覧ください。
プロジェクトをビルドするには、次のことを確認する必要があります。
//:myplatformが存在している必要があります。通常、プロジェクト オーナーは、プロジェクトごとにターゲット マシンが異なるため、プラットフォームを定義する責任があります。デフォルトのプラットフォームをご覧ください。使用するツールチェーンが存在している必要があります。ストック ツールチェーンを使用する場合は、言語オーナーが登録方法の手順を含める必要があります。独自のカスタム ツールチェーンを作成する場合は、
MODULE.bazelファイルまたは--extra_toolchainsでそれらを登録する必要があります。ビルドでプラットフォームをサポートする言語とサポートしない言語が混在している場合は、レガシー言語が新しい API で動作するように、プラットフォーム マッピングが必要になることがあります。詳しくは、プラットフォーム マッピングをご覧ください。
問題が解決しない場合は、お問い合わせください。
デフォルトのプラットフォーム
プロジェクト オーナーは、構築するアーキテクチャを記述するために、明示的なプラットフォームを定義する必要があります。これらは --platforms でトリガーされます。
--platforms が設定されていない場合、Bazel はデフォルトでローカルビルドマシンを表す platform になります。これは @platforms//host(@bazel_tools//tools:host_platform としてエイリアス)で自動生成されるため、明示的に定義する必要はありません。ローカルマシンの OS と CPU を @platforms で宣言された constraint_value にマッピングします。
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" } に変換するか、プラットフォーム マッピングを使用して移行期間中に両方のスタイルをサポートする必要があります。
ルールセットの移行
ルールセットを所有していて、プラットフォームをサポートする場合は、次の操作を行う必要があります。
ルール ロジックで toolchain API を使用してツールチェーンを解決します。ツールチェーン API(
ctx.toolchains)をご覧ください。省略可:
--incompatible_enable_platforms_for_my_languageフラグを定義して、移行テスト中にルール ロジックが新しい API または--crosstool_topなどの古いフラグを介してツールチェーンを交互に解決するようにします。プラットフォーム コンポーネントを構成する関連プロパティを定義します。共通プラットフォーム プロパティをご覧ください。
標準ツールチェーンを定義し、ルールの登録手順(詳細)を通じてユーザーがアクセスできるようにします。
select()s と構成の移行がプラットフォームをサポートしていることを確認します。これが最大の課題です。特に、多言語プロジェクトでは、すべての言語で--platformsを読み取れない場合、失敗する可能性があります。
プラットフォームをサポートしていないルールと組み合わせる必要がある場合は、ギャップを埋めるためにプラットフォーム マッピングが必要になることがあります。
共通のプラットフォーム プロパティ
OS や CPU などの言語に依存しない共通のプラットフォーム プロパティは、@platforms で宣言する必要があります。これにより、共有、標準化、言語間の互換性が促進されます。
ルールに固有のプロパティは、ルールのリポジトリで宣言する必要があります。これにより、ルールが担当する特定のコンセプトに対する明確な所有権を維持できます。
ルールでカスタム目的の OS または CPU を使用する場合は、@platforms ではなく、ルールのリポジトリで宣言する必要があります。
プラットフォーム マッピング
プラットフォーム マッピングは、プラットフォーム認識ロジックを同じビルド内のレガシー ロジックと混在させる一時的な API です。これは、移行期間の不整合を解消するための粗削りなツールです。
プラットフォーム マッピングは、platform() と対応する一連の以前のフラグとのマッピング、またはその逆のマッピングです。次に例を示します。
platforms:
# Maps "--platforms=//platforms:ios" to "--ios_multi_cpus=x86_64 --apple_platform_type=ios".
//platforms:ios
--ios_multi_cpus=x86_64
--apple_platform_type=ios
flags:
# Maps "--ios_multi_cpus=x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
--ios_multi_cpus=x86_64
--apple_platform_type=ios
//platforms:ios
# Maps "--cpu=darwin_x86_64 --apple_platform_type=macos" to "//platform:macos".
--cpu=darwin_x86_64
--apple_platform_type=macos
//platforms:macos
Bazel はこれを使用して、プラットフォーム ベースとレガシーの両方のすべての設定が、トランジションを含め、ビルド全体で一貫して適用されるようにします。
デフォルトでは、Bazel はワークスペース ルートの platform_mappings ファイルからマッピングを読み取ります。--platform_mappings=//:my_custom_mapping を設定することもできます。
詳しくは、プラットフォーム マッピングの設計をご覧ください。
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 のバイナリをビルドできるツールチェーンを自動的に選択します。これはツールチェーン解決と呼ばれます。
使用可能なツールチェーンのセットは、MODULE.bazel ファイルで register_toolchains を使用して登録するか、コマンドラインで --extra_toolchains を使用して登録できます。
詳しくは、こちらをご覧ください。
質問
移行のタイムラインに関する一般的なサポートや質問については、bazel-discuss または適切なルールのオーナーにお問い合わせください。
プラットフォーム/ツールチェーン API の設計と進化に関する議論については、bazel-dev にお問い合わせください。