Bazel は、マルチ アーキテクチャ ビルドとクロスコンパイル ビルドのモデリング プラットフォームとツールチェーンの高度なサポートを備えています。
このページでは、このサポートの状況をまとめています。
関連項目:
ステータス
C++
C++ ルールは、--incompatible_enable_cc_toolchain_resolution
が設定されている場合にプラットフォームを使用して toolchain を選択します。
つまり、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 ルールは、プラットフォームを使用して toolchain を選択します。
これは、以前のフラグ --java_toolchain
、--host_java_toolchain
、--javabase
、--host_javabase
に代わるものです。
詳しくは、Java と Bazel をご覧ください。
Android
Android ルールは、--incompatible_enable_android_toolchain_resolution
が設定されている場合にプラットフォームを使用して toolchain を選択します。
つまり、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 ビルドでプラットフォーム API を引き続き使用できます(Apple ルールと純粋な C++ を組み合わせてビルドする場合など)。
その他の言語
言語ルールセットをお持ちの場合は、ルールセットの移行でサポートを追加する方法をご覧ください。
背景
プラットフォームとツールチェーンが導入され、ソフトウェア プロジェクトがさまざまなアーキテクチャをターゲットにしてクロスコンパイルする方法を標準化しました。
これは、言語のメンテナンス担当者がすでにその場しのぎで互換性のない方法でこれを行っているという観察からヒントを得ています。たとえば、C++ ルールでは --cpu
と --crosstool_top
を使用して、ターゲット CPU とツールチェーンを宣言していました。どちらも「プラットフォーム」を正しくモデル化しません。これにより、不適切で正しくないビルドが作成されました。
Java、Android などの言語は、同様の目的のために独自のフラグを進化させましたが、いずれのフラグも相互に相互運用されていません。これにより、クロス ランゲージ ビルドが混乱し、複雑になりました。
Bazel は、大規模なマルチ言語マルチプラットフォーム プロジェクトを対象としています。そのため、明確な標準 API など、これらのコンセプトに対する原則に基づくサポートが必要になります。
移行の必要性
新しい 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
は、アクセスが容易で明確な場所に定義されています。プラットフォームがプロジェクトに固有の場合はプロジェクトのリポジトリに、すべてのコンシューマ プロジェクトが見つけられる共通の場所に定義します。
--cpu
、--crosstool_top
、--fat_apk_cpu
などの古いフラグは、安全に削除できるとすぐに非推奨になり、削除されます。
結局のところ、これがアーキテクチャを構成する唯一の方法です。
プロジェクトの移行
プラットフォームをサポートする言語でビルドする場合、ビルドはすでに次のような呼び出しで機能しているはずです。
bazel build //:myproject --platforms=//:myplatform
詳しくは、ステータスとご利用の言語のドキュメントをご覧ください。
言語でプラットフォーム サポートを有効にするためのフラグが必要な場合は、そのフラグも設定する必要があります。詳しくは、ステータスをご覧ください。
プロジェクトをビルドするには、次の点を確認する必要があります。
//:myplatform
が存在している必要があります。プロジェクトが異なれば対象マシンが異なるため、通常はプロジェクト オーナーがプラットフォームを定義する責任があります。デフォルトのプラットフォームをご覧ください。使用する toolchain が存在している必要があります。標準のツールチェーンを使用する場合は、言語オーナーがツールチェーンを登録する手順を記載する必要があります。独自のカスタム ツールチェーンを作成する場合は、
MODULE.bazel
ファイルまたは--extra_toolchains
でregisterする必要があります。ビルドでプラットフォームをサポートする言語とサポートしない言語が混在している場合は、レガシー言語が新しい 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 を使用して toolchain を解決します。Toolchain API(
ctx.toolchains
)をご覧ください。省略可:
--incompatible_enable_platforms_for_my_language
フラグを定義して、移行テスト中にルールロジックが新しい API または--crosstool_top
などの古いフラグを使用して toolchain を交互に解決するようにします。プラットフォーム コンポーネントを構成する関連プロパティを定義します。共通のプラットフォーム プロパティをご覧ください。
標準のツールチェーンを定義し、ルールの登録手順を通じてユーザーがアクセスできるようにします(詳細)
select()
と構成の移行がプラットフォームをサポートしていることを確認します。これは最大の課題です特に、複数言語のプロジェクトでは困難です(すべての言語で--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"
など)を宣言します。プロバイダは、これらのツールでビルドする必要があるルールにこの情報を渡します。
ツールチェーンは、ターゲットにできるマシンの constraint_value
(target_compatible_with = ["@platforms//os:linux"]
)と、ツールを実行できるマシンの constraint_value
(exec_compatible_with = ["@platforms//os:mac"]
)を宣言します。
$ bazel build //:myproject --platforms=//:myplatform
をビルドする際、Bazel はビルドマシンで実行可能なツールチェーンと //:myplatform
のビルドバイナリを自動的に選択します。これはツールチェーンの解決と呼ばれます。
使用可能なツールチェーンのセットは、MODULE.bazel
ファイルで register_toolchains
を使用して登録するか、コマンドラインで --extra_toolchains
を使用して登録できます。
詳しくはこちらをご覧ください。
質問
移行のタイムラインに関する一般的なサポートや質問については、bazel-discuss または適切なルールのオーナーにお問い合わせください。
プラットフォーム API やツールチェーン API の設計と進化については、bazel-dev にお問い合わせください。