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

問題を報告 ソースを表示

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 ビルドでは、プラットフォーム マッピングを使用してプラットフォーム API を引き続き使用できます(Apple のルールと純粋な C++ を組み合わせてビルドする場合など)。

その他の言語

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

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

背景

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

これは、言語メンテナンス担当者がアドホックで互換性のない方法ですでにこの作業をしているという観察から触発されました。たとえば、C++ ルールでは、--cpu--crosstool_top を使用してターゲット CPU とツールチェーンを宣言していました。どちらも「プラットフォーム」を正しくモデル化しているわけではありません。これにより、不自然なビルドや誤ったビルドが生成されていました。

Java、Android、その他の言語は、同様の目的で独自のフラグを進化させましたが、互いに相互運用することはありません。そのため言語横断的なビルドが 複雑でわかりにくくなっていました

Bazel は、大規模な多言語マルチプラットフォーム プロジェクトを対象としています。そのためには、明確な標準 API など、より原則に基づいたサポートが必要です。

移行の必要性

新しい API にアップグレードするには、API のリリースと、それを使用するためのルールロジックのアップグレードの 2 つの作業が必要です。

最初の処理は完了しましたが、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_toolchainsregisterする必要があります。

  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 搭載マシンをサポートする必要があります。

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 "--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 レビュー

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

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

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

質問

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

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

関連ドキュメント