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

問題を報告 ソースを表示 ナイトリー · 8.0 · 7.4 · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel には、マルチアーキテクチャとクロスコンパイル ビルドのプラットフォームツールチェーンのモデリングに対する高度なサポートがあります。

このページでは、このサポートのステータスについて説明します。

関連項目:

ステータス

C++

C++ ルールは、--incompatible_enable_cc_toolchain_resolution が設定されている場合にプラットフォームを使用して toolchain を選択します。

つまり、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 ルールは、プラットフォームを使用して toolchain を選択します。

これは、従来のフラグ --java_toolchain--host_java_toolchain--javabase--host_javabase に代わるものです。

詳しくは、Java と Bazel をご覧ください。

Android

Android ルールは、--incompatible_enable_android_toolchain_resolution が設定されている場合にプラットフォームを使用して toolchain を選択します。

つまり、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 つは完了しましたが、もう 1 つは進行中です。これには、言語固有のプラットフォームとツールチェーンが定義されていること、言語ロジックが --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. 使用する toolchain が存在している必要があります。標準のツールチェーンを使用する場合は、言語オーナーがツールチェーンを登録する手順を記載する必要があります。独自のカスタム ツールチェーンを作成する場合は、MODULE.bazel ファイルまたは --extra_toolchains登録する必要があります。

  3. select()構成遷移が正しく解決されている必要があります。select()遷移をご覧ください。

  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_topselect--platforms を認識しません。プロジェクトをプラットフォームに移行する場合は、プロジェクトを constraint_values に変換するか、プラットフォーム マッピングを使用して、移行中に両方のスタイルをサポートする必要があります。

遷移

Starlark 遷移は、ビルドグラフの一部でフラグを変更します。プロジェクトで --cpu--crossstool_top、またはその他の以前のフラグを設定する遷移を使用している場合、--platforms を読み取るルールではこれらの変更は検出されません。

プロジェクトをプラットフォームに移行する場合は、return { "//command_line_option:cpu": "arm" } などの変更を return { "//command_line_option:platforms": "//:my_arm_platform" } に変換するか、プラットフォーム マッピングを使用して、移行中に両方のスタイルをサポートする必要があります。

ルールセットの移行

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

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

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

  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 による審査

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" など)を宣言します。プロバイダは、これらのツールでビルドする必要があるルールにこの情報を渡します。

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

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

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

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

質問

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

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

関連情報