プラットフォームへの移行

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 を引き続き使用できます。

その他の言語

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

言語ルールセットを所有している場合は、サポートを追加するためのルールセットの移行をご覧ください。

背景

ソフトウェア プロジェクトがさまざまなアーキテクチャをターゲットとし、クロスコンパイルを行う方法を標準化するために、プラットフォームツールチェーンが導入されました。

これは、言語のメンテナーがすでにアドホックで互換性のない方法でこれを行っているという観察に基づいています。たとえば、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

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

  1. プロジェクトのルールで、//:myplatform に適切なツールチェーンを選択します。
  2. プロジェクトの依存関係で、//:myplatform に適切なツールチェーンを選択します。
  3. //:myplatform共通宣言CPUOS、その他の汎用的な言語に依存しないプロパティを参照します。
  4. 関連するすべての select()s//:myplatform と正しく一致します。
  5. //:myplatform は、明確でアクセス可能な場所に定義されます。プラットフォームがプロジェクトに固有の場合はプロジェクトのリポジトリに、すべての使用プロジェクトが検出できる共通の場所に定義されます。

--cpu--crosstool_top--fat_apk_cpu などの古いフラグは、安全に削除できるようになったらすぐに非推奨となり、削除されます。

最終的には、これがアーキテクチャを構成する唯一の方法になります。

プロジェクトを移行する

プラットフォームをサポートする言語でビルドする場合、ビルドは次のような呼び出しですでに機能しているはずです。

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

正確な詳細については、ステータスと使用している言語のドキュメントをご覧ください。

言語でプラットフォームのサポートを有効にするフラグが必要な場合は、そのフラグも設定する必要があります。詳しくは、ステータスをご覧ください。

プロジェクトをビルドするには、次のことを確認する必要があります。

  1. //:myplatform が存在する必要があります。通常、プロジェクト オーナーは、プロジェクトごとにターゲット マシンが異なるため、プラットフォームを定義する必要があります。 デフォルトのプラットフォームをご覧ください。

  2. 使用するツールチェーンが存在する必要があります。ストック ツールチェーンを使用する場合は、言語オーナーが登録方法の手順を含める必要があります。独自のカスタム ツールチェーンを作成する場合は、登録する必要があります。MODULE.bazel--extra_toolchains

  3. select()構成の切り替え が 正しく解決される必要があります。select()切り替え効果をご覧ください。

  4. ビルドでプラットフォームをサポートする言語とサポートしない言語が混在している場合は、プラットフォーム マッピングを使用して、従来の言語が新しい API で動作するようにする必要があるかもしれません。 詳しくは、プラットフォーム マッピングをご覧ください。

それでも問題が解決しない場合は、サポートにお問い合わせください

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

プロジェクト オーナーは、ビルドするアーキテクチャを記述する明示的な プラットフォームを定義する必要があります。これらは --platforms でトリガーされます。

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

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",
    },
)

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

--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" } に変換するか、プラットフォーム マッピングを使用して移行中に両方のスタイルをサポートする必要があります。

ルールセットを移行する

ルールセットを所有していて、プラットフォームをサポートする場合は、次の操作を行う必要があります。

  1. ルールロジックでツールチェーン API を使用してツールチェーンを解決します。ツールチェーン API ctx.toolchains)をご覧ください。

  2. 省略可: 移行テスト中にルールロジックが新しい API または --crosstool_top などの古いフラグを介してツールチェーンを交互に解決するように、--incompatible_enable_platforms_for_my_language フラグを定義します。

  3. プラットフォーム コンポーネントを構成する関連プロパティを定義します。 共通のプラットフォーム プロパティをご覧ください。

  4. 標準ツールチェーンを定義し、 ルールの登録手順(詳細)を通じてユーザーがアクセスできるようにします。

  5. `select()s` と 構成の切り替えがプラットフォームをサポートしていることを確認します。これが最大の課題です。特に、マルチ言語プロジェクトでは、すべての言語が --platforms を読み取れない場合、失敗する可能性があるため、困難です。

プラットフォームをサポートしていないルールと混在させる必要がある場合は、 プラットフォーム マッピングを使用してギャップを埋める必要があるかもしれません。

共通のプラットフォーム プロパティ

OSCPU などの言語に依存しない共通のプラットフォーム プロパティは、 @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 による審査

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 のバイナリをビルドできるツールチェーンを自動的に選択します。これはツールチェーンの解決と呼ばれます。

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

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

質問

一般的なサポートや移行タイムラインに関するご質問については、 bazel-discuss または適切なルールのオーナーにお問い合わせください。

プラットフォーム/ツールチェーン API の設計と進化に関するディスカッションについては、 bazel-dev にお問い合わせください。

関連情報