プラットフォームを使った構築

Bazel は、プラットフォームツールチェーンのモデリングを高度にサポートしています。これを実際のプロジェクトに統合するには、 コード所有者、ルール メンテナー、コア Bazel デベロッパー間の慎重な連携が必要です。

このページでは、プラットフォームの目的と、プラットフォームを使用したビルド方法について説明します。

要約: Bazel のプラットフォームとツールチェーンの API は利用可能ですが、すべての言語ルール、select()、その他のレガシー参照が更新されるまで、どこでも機能するわけではありません。これは継続的な取り組みです。最終的には、すべてのビルドがプラットフォーム ベースになります。 ビルドがどこに適合するかについては、以下をご覧ください。

より正式なドキュメントについては、以下をご覧ください。

背景

ソフトウェア プロジェクトがさまざまなマシンをターゲットとし、適切な言語ツールでビルドする方法を標準化するために、プラットフォームツールチェーンが導入されました。

これは、Bazel に比較的最近追加されたものです。言語メンテナーがアドホックで互換性のない方法でこれを行っているという観察から着想を得ました。たとえば、C++ ルールでは、--cpu--crosstool_top を使用して、ビルドのターゲット CPU と C++ ツールチェーンを設定します。どちらも 「プラットフォーム」を正しくモデル化していません。これを行おうとすると、不自然で不正確なビルドが発生しました。 また、これらのフラグは Java コンパイルを制御しません。Java コンパイルは、独自の 独立したインターフェースを--java_toolchain使用して進化させました。

Bazel は、大規模な多言語、マルチプラットフォーム プロジェクトを対象としています。そのため、言語とプロジェクトの相互運用性を促進する明確な API など、これらのコンセプトに対するより原則的なサポートが求められます。これらが新しい API の 目的です。

移行

プラットフォームとツールチェーンの API は、プロジェクトが実際に使用する場合にのみ機能します。プロジェクトのルールロジック、ツールチェーン、依存関係、 select() がサポートしている必要があるため、これは簡単ではありません。すべてのプロジェクトとその依存関係が正しく機能するように、慎重な移行シーケンスが必要です 。

たとえば、Bazel の C++ ルールはプラットフォームをサポートしています。ただし、Apple ルールはサポートしていません。C++ プロジェクト は Apple を気にしないかもしれません。しかし、他のプロジェクトはそうかもしれません。そのため、 すべての C++ ビルドでプラットフォームをグローバルに有効にすることはまだ安全ではありません。

このページの残りの部分では、この移行シーケンスと、プロジェクトがいつどのように 適合するかについて説明します。

目標

すべてのプロジェクトが次の形式でビルドされると、Bazel のプラットフォーム移行が完了します。

bazel build //:myproject --platforms=//:myplatform

これは以下を意味します。

  1. プロジェクトで使用するルールは、 //:myplatform から正しいツールチェーンを推測できます。
  2. プロジェクトの依存関係で使用するルールは、正しいツールチェーンを推測できます from //:myplatform.
  3. プロジェクトに依存するプロジェクトが //:myplatform をサポートしているか、プロジェクトがレガシー API(--crosstool_top など)をサポートしている必要があります。
  4. //:myplatform は、プロジェクト間の自動互換性をサポートする CPUOS、その他の汎用コンセプトの [共通宣言][Common Platform Declaration]{: .external} を参照します。
  5. 関連するすべてのプロジェクトの select()s は、//:myplatformで暗示されるマシン プロパティを理解します。
  6. //:myplatform は、明確で再利用可能な場所に定義されます。プラットフォームがプロジェクトに固有の場合はプロジェクトの リポジトリに、それ以外の場合はこのプラットフォームを使用する可能性のあるすべてのプロジェクト が検索できる場所に定義されます。

この目標が達成されるとすぐに、古い API は削除されます。その後、プロジェクトがプラットフォームとツールチェーンを選択する標準的な方法になります。

プラットフォームを使用する必要がありますか?

プロジェクトをビルドまたはクロスコンパイルする場合は、 プロジェクトの公式ドキュメントに従ってください。

プロジェクト、言語、ツールチェーンのメンテナーは、最終的に新しい API をサポートする必要があります。グローバル移行が完了するまで待つか 早期にオプトインするかは、具体的な価値 / コストのニーズによって異なります。

  • 関心のある正確なプロパティでツールチェーンを select() または選択できます。 代わりに、--cpu などのハードコードされたフラグを使用します。たとえば、複数の CPU が同じ命令セットをサポートできます。
  • より正確なビルド。上記の例で select() を使用して --cpu し、 同じ命令セットをサポートする新しい CPU を追加すると、select() は新しい CPU を認識できません。ただし、プラットフォームでの select() は正確なままです。
  • シンプルなユーザー エクスペリエンス。すべてのプロジェクトが --platforms=//:myplatform を理解します。コマンドラインで言語固有の フラグを複数指定する必要はありません。
  • シンプルな言語設計。すべての言語で、ツールチェーンの定義 、ツールチェーンの使用、プラットフォームに適したツールチェーンの選択に共通の API を使用します。
  • ターゲット プラットフォームと互換性がない場合、ビルドフェーズとテストフェーズでターゲットを スキップできます。

料金

  • プラットフォームをまだサポートしていない依存プロジェクトは、自動的に動作しない可能性があります 。
  • 動作させるには、一時的なメンテナンスが必要になる場合があります
  • 新しい API とレガシー API の共存には、混乱を避けるために、より慎重なユーザー ガイダンスが必要です。
  • 一般的なプロパティ の正規定義はまだ進化しており、追加の初期貢献が必要になる場合があります。OSCPU
  • 言語固有のツールチェーンの正規定義はまだ進化しており、 追加の初期貢献が必要になる場合があります。

API による審査

platformconstraint_value ターゲットのコレクションです。

platform(
    name = "myplatform",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:arm",
    ],
)

A constraint_value はマシン プロパティです。同じ「種類」の値は、共通の constraint_settingの下にグループ化されます。

constraint_setting(name = "os")
constraint_value(
    name = "linux",
    constraint_setting = ":os",
)
constraint_value(
    name = "mac",
    constraint_setting = ":os",
)

toolchainStarlark ルールです。その 属性は、言語のツール(compiler = "//mytoolchain:custom_gcc"など)を宣言します。そのプロバイダは、これらのツールでビルドする必要があるルールにこの情報を渡します。

ツールチェーンは、ターゲットにできるマシンのconstraint_valuetarget_compatible_with = ["@platforms//os:linux"])と、ツールを実行できるマシン(exec_compatible_with = ["@platforms//os:mac"])を宣言します。

$ bazel build //:myproject --platforms=//:myplatform をビルドすると、Bazel はビルドマシンで実行でき、//:myplatform のバイナリをビルドできるツールチェーンを自動的に選択します。これはツールチェーンの解決と呼ばれます。

使用可能なツールチェーンのセットは、WORKSPACEregister_toolchains を使用して登録するか、 コマンドラインで --extra_toolchains を使用して登録できます。

詳細については、こちらをご覧ください。

ステータス

現在のプラットフォームのサポートは言語によって異なります。Bazel の主要なルールはすべて プラットフォームに移行しています。ただし、このプロセスには時間がかかります。これには主に 3 つの理由があります。

  1. 新しいツールチェーン APIctx.toolchains)からツール情報を取得し、 --cpu--crosstool_top などのレガシー設定の読み取りを停止するように、ルールロジックを更新する必要があります。これは比較的簡単です。

  2. ツールチェーンのメンテナーは、ツールチェーンを定義し、 ユーザーがアクセスできるようにする必要があります(GitHub リポジトリと WORKSPACE エントリ)。 これは技術的には簡単ですが、ユーザー エクスペリエンスを維持するために インテリジェントに整理する必要があります。

    プラットフォーム定義も必要です(Bazel が実行されるマシンと同じマシンでビルドする場合を除く )。通常、プロジェクトは独自のプラットフォームを定義する必要があります。

  3. 既存のプロジェクトを移行する必要があります。select()切り替えも 移行する必要があります。これが最大の課題です。特に、 多言語プロジェクトでは困難です(すべての言語で --platformsを読み取れない場合、失敗する可能性があります)。

新しいルールセットを設計する場合は、最初からプラットフォームをサポートする必要があります。 これにより、プラットフォーム API が普及するにつれて価値が高まり、ルールが他の ルールやプロジェクトと自動的に互換性を持つようになります。

一般的なプラットフォーム プロパティ

プロジェクト間で共通の OSCPU などのプラットフォーム プロパティは、標準化された一元的な場所で宣言する必要があります。これにより、プロジェクト間 および言語間の互換性が促進されます。

たとえば、MyAppconstraint_value @myapp//cpus:armselect() があり、SomeCommonLib@commonlib//constraints:armselect() がある場合、これらは互換性のない 条件で「arm」モードをトリガーします。

グローバルに共通のプロパティは @platforms リポジトリ で宣言されます(上記の例の正規ラベルは @platforms//cpu:arm です)。 言語に共通のプロパティは、それぞれの 言語のリポジトリで宣言する必要があります。

デフォルトのプラットフォーム

通常、プロジェクト オーナーは、ビルドするマシンの種類を記述する明示的な プラットフォームを定義する必要があります。これらは --platformsでトリガーされます。

--platforms が設定されていない場合、Bazel はデフォルトで ローカル ビルドマシンを表す platform になります。これは @local_config_platform//:host で自動生成されるため、明示的に定義する必要はありません。ローカルマシンの OSCPUconstraint_values で宣言された @platformsにマッピングします。

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切り替えが互換性がある場合に限ります。詳細については、 #7260C++ ツールチェーンの構成をご覧ください。

このモードはデフォルトでは有効になっていません。これは、Apple プロジェクトが --cpu--crosstool_top)を使用して C++ 依存関係を構成しているためです。そのため、これは Apple ルールがプラットフォームに移行するかどうかによって異なります。

Java

Bazel の Java ルールはプラットフォームを使用します。

これにより、レガシー フラグ --java_toolchain--host_java_toolchain--javabase--host_javabase が置き換えられます。

構成フラグの使用方法については、Bazel と Java のマニュアルをご覧ください。 詳細については、設計ドキュメントをご覧ください。

レガシー フラグをまだ使用している場合は、Issue #7849 の移行プロセスに従ってください。

Android

Bazel の Android ルールは、 --incompatible_enable_android_toolchain_resolution を設定すると、プラットフォームを使用してツールチェーンを選択します。

これはデフォルトでは有効になっていません。ただし、移行は順調に進んでいます。

Apple

Bazel の Apple ルールは、Apple ツールチェーンを選択するプラットフォームをまだサポートしていません。

また、プラットフォーム対応の C++ 依存関係もサポートしていません。これは、 レガシー --crosstool_top を使用して C++ ツールチェーンを設定するためです。これが移行されるまで、Apple プロジェクトとプラットフォーム対応の C++ をプラットフォーム マッピング)と組み合わせることができます。

その他の言語

  • Bazel の Rust ルールはプラットフォームを完全にサポートしています。
  • Bazel の Go ルールは プラットフォーム を完全にサポートしています(詳細)。

新しい言語のルールを設計する場合は、プラットフォーム を使用して言語のツールチェーンを選択します。詳細については、 ツールチェーンのドキュメントをご覧ください。

select()

プロジェクトは select() ターゲットで constraint_value できますが、完全な プラットフォームではできません。これは、select() ができるだけ多くの種類のマシンをサポートするように意図されています。ARM-specific ソースを含むライブラリは、より具体的な理由がない限り、 すべてARM-搭載マシンをサポートする必要があります。

1 つ以上の constraint_value で選択するには、次のようにします。

config_setting(
    name = "is_arm",
    constraint_values = [
        "@platforms//cpu:arm",
    ],
)

これは、従来 --cpu で選択するのと同じです。

config_setting(
    name = "is_arm",
    values = {
        "cpu": "arm",
    },
)

詳しくはこちらをご覧ください。こちら

select--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 つのオプションがあります。

  1. プロジェクトの言語(存在する場合 )の [プラットフォームを使用] フラグをオンにして、関心のあるプロジェクトが動作するかどうかを確認するために必要なテストを行います。

  2. 関心のあるプロジェクトが --cpu--crosstool_top などのレガシー フラグに依存している場合は、これらを --platforms と組み合わせて使用します。

    bazel build //:my_mixed_project --platforms==//:myplatform --cpu=... --crosstool_top=...

    これにはメンテナンス コストがかかります(設定が一致していることを手動で確認する必要があります )。ただし、不正な 切り替えがない場合は、これで動作するはずです。

  3. 両方のスタイルをサポートするために、プラットフォーム マッピングを作成し、 --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

関連情報