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

問題を報告する ソースを表示

Bazel は、マルチビルドとクロスコンパイル ビルド用に、プラットフォームツールチェーンをモデル化するための高度なサポートを備えています。

このページでは、このサポートの状態の概要を紹介しています。

関連項目:

ステータス

C++

C++ ルールでは、--incompatible_enable_cc_toolchain_resolution が設定されているときにプラットフォームを使用してツールチェーンを選択します。

つまり、以下のコマンドで C++ プロジェクトを構成できます。

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

instead of the legacy:

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 ビルドでプラットフォーム API を使用する(たとえば、Apple ルールと純粋な C++ を組み合わせる場合など)。

その他の言語

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

言語ルールセットを所有している場合は、ルールセットの移行を参照してサポートを追加します。

背景

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

これを、言語の維持者がアドホックかつ互換性のない方法ですでに行っているという考えに触発されました。たとえば、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

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

  1. プロジェクトのルールでは、//:myplatform に適切なツールチェーンを選択します。
  2. プロジェクトの依存関係は、//:myplatform に適切なツールチェーンを選択します。
  3. //:myplatform は、CPUOS、およびその他の言語に依存しない一般的なプロパティの一般的な宣言を参照します。
  4. 関連するすべての select()//:myplatform と適切に一致している。
  5. //:myplatform は、プロジェクトに固有のプラットフォームの場合はプロジェクトのリポジトリ、または消費するすべてのプロジェクトで確認できる一般的な場所で、わかりやすくアクセスできる場所で定義されます。

--cpu--crosstool_top--fat_apk_cpu などの古いフラグは、安全な状態になったら直ちに非推奨になり、削除されます。

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

プロジェクトの移行

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

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

詳しくは、ステータスと言語に関するドキュメントをご覧ください。

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

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

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

  2. 使用するツールチェーンが存在していること。ストック ツールチェーンを使用する場合は、言語所有者がそれを登録する手順を追加する必要があります。独自のカスタム ツールチェーンを作成する場合は、WORKSPACE または --extra_toolchains を使用して登録する必要があります。

  3. select()構成遷移は、適切に解決する必要があります。select()Transition をご覧ください。

  4. プラットフォームをサポートしている言語とそうでない言語が混在している場合、以前の言語を新しい API と連携させるには、プラットフォームのマッピングが必要になる場合があります。詳しくは、プラットフォームのマッピングをご覧ください。

問題が解決しない場合は、お問い合わせください。

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

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

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

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

ルールセットを移行する

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

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

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

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

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

  5. select()構成の遷移がプラットフォームをサポートするようにします。これは最大の課題です。これは特に、多言語プロジェクトでは困難です(すべての言語が --platforms を読み取れない場合、失敗する可能性があります)。

プラットフォームをサポートしていないルールと組み合わせる必要がある場合は、ギャップを埋めるためにプラットフォーム マッピングが必要になる場合があります。

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

OSCPU などの一般的な言語横断型のプラットフォーム プロパティは、@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 はマシン プロパティです。同じ「種類」の値は、共通の 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" など)を宣言します。プロバイダは、これらのツールでビルドする必要があるルールにこの情報を渡します。

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

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

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

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

質問

移行スケジュールに関する一般的なサポートと質問については、bazel-discuss または適切なルールのオーナーにお問い合わせください。

プラットフォームやツールチェーン API の設計と進化については、bazel-dev にお問い合わせください。

関連ドキュメント