Bazel は、プラットフォームとツールチェーンのモデリングに対する高度なサポートを備えています。実際のプロジェクトに統合するには、コードオーナー、ルールメンテナー、コア Bazel 開発者の協力が必要です。
このページでは、プラットフォームの目的と、プラットフォームを使用して構築する方法について説明します。
tl;dr: Bazel のプラットフォームとツールチェーン API を使用できますが、すべての言語ルール、select()
、その他の従来の参照が更新されるまで、どこでも動作する必要があります。これは継続的な取り組みです。最終的には、すべてのビルドがプラットフォーム ベースになります。ビルドが配置されている場所については、下記をご覧ください。
正式なドキュメントについては、以下をご覧ください。
背景
プラットフォームとツールチェーンは、ソフトウェア プロジェクトがさまざまなマシンをターゲットにし、適切な言語ツールでビルドする方法を標準化するために導入されました。
これは、Bazel に比較的最近追加された機能です。言語の維持者がアドホックかつ互換性のない方法ですでにこの処理を行っていることが、インスピレーションとなりました。たとえば、C++ ルールは --cpu
と --crosstool_top
を使用して、ビルドのターゲット CPU と C++ ツールチェーンを設定します。どちらも「プラットフォーム」を正しくモデル化していません。このような試みは、不正なビルドや不正確なビルドの原因となりました。また、これらのフラグは、--java_toolchain
との独立した独自のインターフェースを進化させる Java コンパイルも制御しません。
Bazel は、複数の言語を使用する大規模なプラットフォーム プロジェクトを対象としています。そのためには、言語とプロジェクトの相互運用性を促進する明確な 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
などの一般的なコンセプトの一般的な宣言を参照します。- 関連するすべてのプロジェクトの
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"]
)を宣言します。
$ 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()
を持ち、SomeCommonLib が @commonlib//constraints:arm
に 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
instead of the legacy:
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 ツールチェーンを選択するプラットフォームをサポートしていません。
また、以前の --crosstool_top
を使用して C++ ツールチェーンを設定するため、プラットフォーム対応の C++ 依存関係もサポートされません。この移行が行われるまで、Apple プロジェクトと Platorm 対応 C++ をプラットフォーム マッピングで混在させることができます(例)。
その他の言語
新しい言語のルールを作成する場合は、プラットフォームを使用して言語のツールチェーンを選択します。適切なチュートリアルについては、ツールチェーンのドキュメントをご覧ください。
select()
プロジェクトでは constraint_value
ターゲットに対して select()
を使用できますが、完全なプラットフォームはできません。これは、select()
ができる限りさまざまなマシンをサポートしていることが意図されています。ARM
固有のソースを含むライブラリは、より具体的な理由がない限り、すべての ARM
マシンをサポートする必要があります。
constraint_value
から 1 つ以上を選択するには、次のコマンドを使用します。
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 にお問い合わせください。