リモート実行用に Bazel ルールを適用する

問題を報告 ソースを表示

このページは、カスタムビルドとテストのルールを作成する Bazel ユーザーで、リモート実行における Bazel ルールの要件を理解する必要がある方を対象としています。

リモート実行により、Bazel はデータセンターなどの別のプラットフォームでアクションを実行できます。Bazel は、リモート実行に gRPC プロトコルを使用します。bazel-buildfarm でリモート実行を試すことができます。bazel-buildfarm は、分散リモート実行プラットフォームを提供することを目的としたオープンソース プロジェクトです。

このページでは、さまざまな環境タイプまたはプラットフォームを指すときに、次の用語を使用します。

  • ホスト プラットフォーム - Bazel が実行される場所。
  • 実行プラットフォーム - Bazel アクションが実行される場所。
  • ターゲット プラットフォーム - ビルドの出力(および一部のアクション)が実行される場所。

概要

リモート実行用に Bazel ビルドを構成する場合は、このページに記載されているガイドラインに従って、ビルドがリモートでエラーなく実行されるようにする必要があります。これは、リモート実行の特性によるものです。

  • 分離されたビルド アクション。ビルドツールは状態を保持せず、ビルドツール間で依存関係が漏洩することはありません。

  • 多様な実行環境。ローカルビルド構成は、リモート実行環境に必ずしも適しているわけではありません。

このページでは、リモート実行のカスタム Bazel ビルドルールとテストルールを実装する際に発生する可能性のある問題と、その回避方法について説明します。以下のトピックを扱います。

ツールチェーン ルールを使用したビルドツールの呼び出し

Bazel ツールチェーン ルールは、コンパイラやリンカーなどの使用するビルドツールと、ルールの作成者が定義したパラメータを使用して構成方法をビルドルールに指示する構成プロバイダです。ツールチェーン ルールを使用すると、ビルドルールとテストルールで、リモート実行に対応した予測可能かつ事前構成された方法でビルドツールを呼び出すことができます。たとえば、PATHJAVA_HOME、またはリモート実行環境で同等の値(またはまったく設定されていない)されている他のローカル変数を介してビルドツールを呼び出す代わりに、ツールチェーン ルールを使用します。

現在、ScalaRustGo の Bazel ビルドルールとテストルールにツールチェーン ルールが存在し、bash などの他の言語やツールでは新しいツールチェーン ルールが開発中です。ルールで使用するツールにツールチェーン ルールが存在しない場合は、ツールチェーン ルールの作成を検討してください。

暗黙的な依存関係の管理

ビルドツールがビルド アクション間の依存関係にアクセスできる場合、各リモートビルド アクションは他のビルド アクションとは別に実行されるため、それらのアクションはリモートで実行されたときに失敗します。一部のビルドツールは、ツール呼び出しに明示的に含まれていないビルド アクションやアクセス依存関係全体で状態を保持するため、リモートで実行されたビルド アクションは失敗します。

たとえば、Bazel がステートフル コンパイラに foo をローカルでビルドするよう指示する場合、コンパイラは foo のビルド出力への参照を保持します。次に、Bazel がコンパイラに対し、foo に依存する bar をビルドするよう指示すると、コンパイラ呼び出しに含める依存関係を BUILD ファイルに明示的に記述しなくても、両方のアクションで同じコンパイラ インスタンスが実行される限り、アクションは正常に実行されます(ローカル実行で通常行われます)。ただし、リモート実行のシナリオでは、各ビルド アクションが個別のコンパイラ インスタンスを実行するため、コンパイラ状態と foo に対する bar の暗黙的な依存関係が失われ、ビルドは失敗します。

こうした依存関係の問題を検出して排除できるように、Bazel 0.14.1 にはローカルの Docker サンドボックスが用意されています。このサンドボックスには、リモート実行と同じ制約があります。サンドボックスを使用して依存関係に関連するビルドエラーを特定して解決し、リモート実行用のビルドを準備します。詳しくは、Docker サンドボックスを使用した Bazel リモート実行のトラブルシューティングをご覧ください。

プラットフォーム依存のバイナリの管理

通常、ホスト プラットフォームでビルドされたバイナリは、依存関係が一致しない可能性があるため、任意のリモート実行プラットフォームで安全に実行できません。たとえば、Bazel に付属の SingleJar バイナリは、ホスト プラットフォームをターゲットとしています。ただし、リモート実行の場合、SingleJar は、リモート実行プラットフォームをターゲットとするように、コードのビルドプロセスの一部としてコンパイルする必要があります。(ターゲット選択ロジックをご覧ください)。

実行プラットフォームで安全に実行できる場合を除き、ビルドに必要なビルドツールのバイナリをソースコードとともにリリースしないでください。代わりに、次のいずれかを行います。

  • ツールのソースコードを配布または外部参照して、リモート実行プラットフォーム用にビルドできるようにします。

  • ツールが安定している場合は、リモート実行環境(ツールチェーン コンテナなど)にツールをプリインストールし、ツールチェーン ルールを使用してビルドで実行します。

config 形式の WORKSPACE ルールの管理

Bazel の WORKSPACE ルールは、ビルドに必要なツールとライブラリのホスト プラットフォームをプローブするために使用できます。ローカルビルドの場合、これらは Bazel の実行プラットフォームでもあります。ビルドがローカルのビルドツールとアーティファクトに明示的に依存している場合、リモート実行プラットフォームがホスト プラットフォームと同一でなければ、リモート実行時に失敗します。

WORKSPACE ルールによって実行される次のアクションは、リモート実行に対応していません。

  • バイナリをビルドする。WORKSPACE ルールでコンパイル アクションを実行すると、ホスト プラットフォームと異なる場合に、リモート実行プラットフォームと互換性のないバイナリが生成されます。

  • pip パッケージをインストールします。WORKSPACE ルールを介してインストールされた pip パッケージでは、依存関係をホスト プラットフォームにプリインストールする必要があります。このようなパッケージは、特にホスト プラットフォーム専用にビルドされており、ホスト プラットフォームと異なる場合、リモート実行プラットフォームと互換性がありません。

  • ローカルツールまたはアーティファクトへのシンボリック リンク。WORKSPACE ルールを使用して作成されたホスト プラットフォームにインストールされているツールやライブラリへのシンボリック リンクは、Bazel で特定できないため、リモート実行プラットフォームで失敗します。代わりに、標準のビルド アクションを使用してシンボリック リンクを作成し、シンボリック リンクされたツールとライブラリに Bazel の runfiles ツリーからアクセスできるようにします。repository_ctx.symlink を使用して、外部リポジトリ ディレクトリ外のターゲット ファイルをシンボリック リンクしないでください。

  • ホスト プラットフォームのミューテーション。リモート実行プラットフォームで予期しない動作が発生する可能性があるため、Bazel runfiles ツリーの外部にあるファイルの作成、環境変数の作成、同様のアクションは避けてください。

潜在的な非密閉動作を見つけるには、Workspace ルールログを使用します。

外部依存関係がホスト プラットフォームに依存する特定のオペレーションを実行する場合は、次のように WORKSPACE とビルドルールの間でオペレーションを分割する必要があります。

  • プラットフォームの検査と依存関係の列挙。これらのオペレーションは、WORKSPACE ルールを介してローカルで安全に実行できます。このルールでは、インストールされているライブラリの確認、ビルドが必要なパッケージのダウンロード、コンパイルに必要なアーティファクトの準備を行うことができます。リモート実行の場合、これらのルールは、事前チェック済みアーティファクトを使用して、ホスト プラットフォームの検査中に通常取得される情報を提供できるようにすることも必要です。事前にチェックされたアーティファクトにより、Bazel は依存関係をローカルにあるかのように記述できます。これには、条件文または --override_repository フラグを使用します。

  • ターゲット固有のアーティファクトとプラットフォームのミューテーションを生成またはコンパイルする。これらのオペレーションは、通常のビルドルールで実行する必要があります。外部依存関係のターゲット固有のアーティファクトを生成するアクションは、ビルド中に実行する必要があります。

リモート実行用の事前チェック済みアーティファクトを簡単に生成するには、WORKSPACE ルールを使用して、生成されたファイルを出力します。これらのルールは、各ツールチェーン コンテナ内など、新しい実行環境ごとに実行し、ソース リポジトリでリモート実行ビルドの出力を確認して参照できます。

たとえば、TensorFlow の cudapython のルールの場合、WORKSPACE ルールは次の BUILD files を生成します。ローカル実行では、ホスト環境を確認して生成されたファイルが使用されます。リモート実行の場合、環境変数に条件文を使用すると、リポジトリにチェックインされたファイルをルールで使用できます。

BUILD ファイルは genrules を宣言します。これはローカルとリモートの両方で実行でき、こちらに示すように、以前に repository_ctx.symlink で実行されていた必要な処理を実行できます。