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

問題を報告 ソースを表示

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 のルールはプラットフォームをサポートしていないため、サポートはまだ予定されていません。

Apple ビルドでは、プラットフォーム マッピングを使用してプラットフォーム API を引き続き使用できます(Apple ルールとピュア C++ を組み合わせてビルドする場合など)。

その他の言語

  • 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()//:myplatform と適切に一致します。
  5. //:myplatform は、明確でアクセス可能な場所で定義します。プラットフォームがプロジェクトに固有の場合はプロジェクトのリポジトリか、すべての使用プロジェクトが見つけられる共通の場所で定義します。

--cpu--crosstool_top--fat_apk_cpu などの古いフラグは非推奨となり、安全に行える状態になり次第削除されます。

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

プロジェクトの移行

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

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

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

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

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

  1. //:myplatform は必須です。プロジェクトが異なるマシンをターゲットとするため、プラットフォームを定義するのはプロジェクト オーナーの責任です。デフォルトのプラットフォームをご覧ください。

  2. 使用するツールチェーンが存在している必要があります。ストック ツールチェーンを使用する場合、言語の所有者はツールチェーンの登録方法を含める必要があります。独自のカスタム ツールチェーンを作成する場合は、MODULE.bazel ファイルまたは --extra_toolchains でそれらをregisterする必要があります。

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

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

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

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

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

--platforms が設定されていない場合、Bazel はデフォルトでローカルビルドマシンを表す platform になります。これは @platforms//host で自動生成される(@bazel_tools//tools:host_platform としてエイリアスされる)ため、明示的に定義する必要はありません。ローカルマシンの OSCPU が、@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" } に変換するか、プラットフォーム マッピングを使用して両方のスタイルをサポートする必要があります。

ルールセットを移行する

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

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

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

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

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

  5. select()構成の移行がプラットフォームをサポートしていることを確認します。これは最大の課題ですこのことは、多言語プロジェクトでは特に困難です(すべての言語で --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",
    ],
)

constraint_value はマシン プロパティです。同じ「kind」の値は、共通の 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"])の constraint_value を宣言します。

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

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

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

質問

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

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

関連情報