Bazel には、マルチ アーキテクチャ ビルドとクロスコンパイル ビルド用のプラットフォームとツールチェーンのモデリングの高度なサポートがあります。
このページでは、このサポートの現状について概説しています。
関連項目:
ステータス
C++
--incompatible_enable_cc_toolchain_resolution
が設定されている場合、C++ ルールはプラットフォームを使用してツールチェーンを選択します。
つまり、次のように 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
--incompatible_enable_android_toolchain_resolution
が設定されている場合、Android ルールはプラットフォームを使用してツールチェーンを選択します。
つまり、以下を使用して 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 ビルドでは、プラットフォーム マッピングを使用してプラットフォーム API を引き続き使用できます(Apple のルールと純粋な C++ を組み合わせてビルドする場合など)。
その他の言語
言語ルールセットを所有している場合は、ルールセットを移行するでサポートの追加をご覧ください。
背景
プラットフォームとツールチェーンは、ソフトウェア プロジェクトが異なるアーキテクチャをターゲットとしてクロスコンパイルする方法を標準化するために導入されました。
これは、言語メンテナンス担当者がアドホックで互換性のない方法ですでにこの作業をしているという観察から触発されました。たとえば、C++ ルールでは、--cpu
と --crosstool_top
を使用してターゲット CPU とツールチェーンを宣言していました。どちらも「プラットフォーム」を正しくモデル化しているわけではありません。これにより、不自然なビルドや誤ったビルドが生成されていました。
Java、Android、その他の言語は、同様の目的で独自のフラグを進化させましたが、互いに相互運用することはありません。そのため言語横断的なビルドが 複雑でわかりにくくなっていました
Bazel は、大規模な多言語マルチプラットフォーム プロジェクトを対象としています。そのためには、明確な標準 API など、より原則に基づいたサポートが必要です。
移行の必要性
新しい API にアップグレードするには、API のリリースと、それを使用するためのルールロジックのアップグレードの 2 つの作業が必要です。
最初の処理は完了しましたが、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
は必須です。プロジェクトごとに異なるマシンをターゲットにしているため、通常はプロジェクト オーナーがプラットフォームを定義する責任を負います。デフォルトのプラットフォームをご覧ください。使用するツールチェーンが存在している必要があります。ストック ツールチェーンを使用している場合は、言語オーナーがツールチェーンの登録方法を指定する必要があります。独自のカスタム ツールチェーンを作成する場合は、それらを
WORKSPACE
または--extra_toolchains
にregisterする必要があります。select()
と構成の移行を適切に解決する必要があります。select() と Transition をご覧ください。プラットフォームをサポートする言語とサポートしない言語がビルドに混在している場合は、以前の言語が新しい API と連携できるように、プラットフォーム マッピングが必要になることがあります。詳しくは、プラットフォーム マッピングをご覧ください。
それでも問題が解決しない場合は、お問い合わせください。
デフォルトのプラットフォーム
プロジェクト オーナーは、ビルドするアーキテクチャを記述するために明示的なプラットフォームを定義する必要があります。その後、--platforms
でトリガーされます。
--platforms
が設定されていない場合、Bazel はデフォルトでローカルビルドマシンを表す platform
になります。これは @local_config_platform//:host
で自動生成されるため、明示的に定義する必要はありません。ローカルマシンの 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" }
に変換するか、プラットフォーム マッピングを使用して両方のスタイルをサポートする必要があります。
ルールセットを移行する
ルールセットを所有していて、プラットフォームをサポートする場合は、以下を行う必要があります。
ルールロジックで、ツールチェーン API を使用してツールチェーンを解決できるようにします。ツールチェーン API(
ctx.toolchains
)を参照してください。省略可:
--incompatible_enable_platforms_for_my_language
フラグを定義して、移行テスト中にルールロジックが新しい API または古いフラグ(--crosstool_top
など)を使用してツールチェーンを交互に解決します。プラットフォーム コンポーネントを構成する関連プロパティを定義します。共通のプラットフォーム プロパティをご覧ください。
標準のツールチェーンを定義し、ルールの登録手順でユーザーがアクセスできるようにします(詳細)。
select()
と構成の遷移がプラットフォームをサポートしていることを確認します。これが最大の課題ですこれは、多言語プロジェクトでは特に困難です(すべての言語で--platforms
を読み取れない場合、失敗する可能性があります)。
プラットフォームをサポートしていないルールを組み合わせる必要がある場合は、プラットフォーム マッピングでギャップを埋めることができます。
共通のプラットフォーム プロパティ
OS
や CPU
など、共通の言語間プラットフォーム プロパティは、@platforms
で宣言する必要があります。これにより、共有、標準化、言語間互換性が促進されます。
ルールに固有のプロパティは、ルールのリポジトリで宣言する必要があります。これにより、ルールの対象となる特定のコンセプトに対して明確な所有権を維持できます。
ルールでカスタム目的の OS または CPU を使用している場合は、@platforms
ではなく、ルールのリポジトリで宣言する必要があります。
プラットフォーム マッピング
プラットフォーム マッピングは、プラットフォーム対応のロジックを同じビルド内のレガシー ロジックと混在させるための一時的な 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_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
はマシン プロパティです。同じ「kind」の値は、共通の 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-discuss または該当するルールのオーナーにお問い合わせください。
プラットフォーム/ツールチェーン API の設計と進化に関するディスカッションについては、bazel-dev にお問い合わせください。