依存関係

<ph type="x-smartling-placeholder"></ph> 問題を報告する ソースを表示 夜間 · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

ビルド時に AB を必要とする場合、ターゲット A はターゲット B に依存します。 実行時間が長くなります。depends 関係は、 有向非巡回グラフ (DAG)であり、依存関係グラフと呼ばれます。

ターゲットの直接的依存関係とは、パスによって到達可能な他のターゲットのことです。 長さ 1 のテーブルが作成されます。ターゲットの推移的依存関係は、 グラフ内の任意の長さのパスを介して、依存するターゲットをリストします。

実際、ビルドのコンテキストでは、依存関係グラフが 2 つあります。 実際の依存関係の数と宣言された依存関係のグラフを確認できます。ほとんどの この 2 つのグラフは非常に似ているので 区別する必要はありませんが 以下の説明で役立ちます。

実際の依存関係と宣言された依存関係

Y が存在する場合、ターゲット X はターゲット Y実際に依存します。 X を正しくビルドできるように、最新バージョンでビルドする必要があります。Built: 生成、処理、コンパイル、リンク、アーカイブ、圧縮、実行、 ビルド中に日常的に行われるその他の種類のタスクにも使用できます。

ターゲット X にターゲット Y に対する依存関係が宣言されている(依存関係がある場合) X のパッケージで X から Y へのエッジ。

正しいビルドでは、実際の依存関係 A のグラフが次のサブグラフになっている必要があります。 宣言された依存関係のグラフ D。つまり、このデータのすべてのペアが A 内の直接接続のノード x --> y も Google Cloud 内で直接接続 D.DA過近似と言えます。

BUILD ファイル ライターは、実際の直接的なすべての ビルドシステムに追加できます。

この原則に従わないと、未定義の動作が発生します。ビルドが失敗し、 さらに悪いことに、ビルドが以前のオペレーションに依存したり、推移的 依存関係が宣言されます。Bazel による欠落チェック エラーを報告できます。ただし、このチェックを 完了しています。

間接的にインポートされたデータすべてをリストに含める必要はありません。 (実行時に A によって必要とされる場合でも)。

ターゲット X のビルド中に、ビルドツールは推移的全体を検査します。 X の依存関係を閉じて、それらのターゲットの変更が確実に適用されるようにします。 最終結果に反映され、必要に応じて中間体が再構築されます。

依存関係の推移的な性質は、よくある間違いにつながります。場合によっては あるファイル内のコードで、間接的な依存関係によって 推移的であるが直接的なエッジではない。間接的 BUILD ファイルに依存関係が含まれていない。このルールは プロバイダに直接依存している場合、次に示すように、変更を追跡する方法はありません。 例を示します。

1. 宣言された依存関係が実際の依存関係と一致する

最初はすべてうまくいきますパッケージ a 内のコードは、パッケージ b 内のコードを使用しています。 パッケージ b 内のコードはパッケージ c 内のコードを使用するため、推移的に a を使用します。 c に依存します。

a/BUILD b/BUILD
rule(
    name = "a",
    srcs = "a.in",
    deps = "//b:b",
)
      
rule(
    name = "b",
    srcs = "b.in",
    deps = "//c:c",
)
      
a / a.in b / b.in
import b;
b.foo();
    
import c;
function foo() {
  c.bar();
}
      
a、b、c を矢印で結んだ宣言された依存関係グラフ
宣言された依存関係グラフ
宣言された依存関係と一致する実際の依存関係グラフ
                  a、b、c を結ぶ矢印の付いたグラフ
実際の依存関係グラフ

宣言された依存関係が実際の依存関係を過大評価している。順調です。

2. 宣言されていない依存関係の追加

誰かが a にコードを追加すると、潜在的な危険が発生します。 c への直接的な依存関係があるが、ビルドファイルでの宣言を忘れている a/BUILD

a / a.in  
        import b;
        import c;
        b.foo();
        c.garply();
      
 
a、b、c を矢印で結んだ宣言された依存関係グラフ
宣言された依存関係グラフ
a、b、c を矢印で結んだ実際の依存関係グラフ。「
                  矢印 A を C にも接続します。これは次と一致しません:
                  宣言された依存関係グラフ
実際の依存関係グラフ

宣言された依存関係が実際の依存関係を過大評価しなくなりました。 2 つのグラフの推移的クロージャは等しいため、これは問題ないでしょう。 a には c に対する実際の依存関係があり、宣言されていない依存関係があります。

3. 宣言された依存関係グラフと実際の依存関係グラフの相違

その危険性は、誰かが b に依存しなくなるようにリファクタリングすると明らかになります。 c が、誤って a を no から a を壊してしまう あります。

  b/BUILD
 
rule(
    name = "b",
    srcs = "b.in",
    deps = "//d:d",
)
      
  b / b.in
 
      import d;
      function foo() {
        d.baz();
      }
      
a と b を矢印でつないで宣言された依存関係グラフ。
                  b は c に接続されなくなり、a と c の接続が切断されます。
宣言された依存関係グラフ
b と c への接続を示す実際の依存関係グラフ。
                  b はもはや c に接続しない
実際の依存関係グラフ

宣言された依存関係グラフは、実際の 推移的に閉じている場合でも、依存関係をその可能性が高くなります。

この問題は、実際の依存関係が Terraform の状態を 手順 2 で導入された a から c に、BUILD ファイルで正しく宣言されていました。

依存関係のタイプ

ほとんどのビルドルールには、リソースの種類を指定する 3 つの属性があります。 汎用依存関係: srcsdepsdataこれらについて説明します。対象 詳細については、以下をご覧ください。 すべてのルールに共通する属性

多くのルールには、ルール固有の種類に応じた追加の属性も用意されています。 compilerresources など。これらの詳細については 百科事典を作成する

srcs の依存関係

ソースファイルを出力するルールまたはルールによって直接使用されるファイル。

deps の依存関係

ヘッダー ファイルを提供する個別にコンパイルされたモジュールを指すルール シンボル、ライブラリ、データなど

data の依存関係

ビルド ターゲットを正常に実行するには、いくつかのデータファイルが必要になる場合があります。これらのデータファイルは ソースコードではありません。ターゲットのビルド方法には影響しません。たとえば、 単体テストでは、関数の出力とファイルの内容を比較する場合があります。ユーザーが 単体テストを作成します。このファイルは必要なく、 テストします。実行中に起動するツールについても同様です。

ビルドシステムは、隔離されたディレクトリでテストを実行します。このディレクトリには、 data は利用できます。したがって、バイナリ/ライブラリ/テストを実行するためにファイルが必要な場合は、 その変数(またはそれらを含むビルドルール)を data で指定します。例:

# I need a config file from a directory named env:
java_binary(
    name = "setenv",
    ...
    data = [":env/default_env.txt"],
)

# I need test data from another directory
sh_test(
    name = "regtest",
    srcs = ["regtest.sh"],
    data = [
        "//data:file1.txt",
        "//data:file2.txt",
        ...
    ],
)

これらのファイルは、相対パス path/to/data/file で参照できます。テストでは テストのソースのパスを結合することで、これらのファイルを参照できます。 ワークスペースの相対パスを指定します。たとえば、 ${TEST_SRCDIR}/workspace/path/to/data/file

ラベルを使用したディレクトリの参照

BUILD ファイルを見ると、一部の data ラベルに気づくかもしれません。 ディレクトリを参照します。以下の例のように、ラベルの末尾は /. または / です。 これは使用しないでください。

非推奨 - data = ["//data/regression:unittest/."]

非推奨 - data = ["testdata/."]

非推奨 - data = ["testdata/"]

これは特にテストには便利であるように思える。 ディレクトリ内のすべてのデータファイルを使用します。

しかし、これはやめておきましょう。増分再ビルド(および テストの再実行など)は、変更後にビルドシステムで ビルド(またはテスト)への入力であるファイルの完全なセット。このように 場合、ビルドシステムは、ディレクトリ自体が (ファイルの追加や削除によって)行われたものの、変更を検出して 個々のファイルの編集は、包含するディレクトリには影響しないため、それらの変更は行いません。 ビルドシステムへの入力としてディレクトリを指定するのではなく、 その中に含まれるファイルのセットを明示的に列挙することも、 glob() 関数。(** を使用して、 glob() は再帰的になります)。

推奨 - data = glob(["testdata/**"])

残念ながら、ディレクトリ ラベルを使用しなければならない場合もあります。 たとえば、testdata ディレクトリに、名前に ラベル構文に準拠している。 ファイルの明示的な列挙、または glob() 関数が無効なラベルを生成する エラーが発生します。この場合はディレクトリ ラベルを使用する必要がありますが、 上記で説明した誤った再ビルドに関連するリスク。

ディレクトリのラベルを使用する必要がある場合は、ディレクトリの 相対 ../ パスを持つ親パッケージ。代わりに、次のような絶対パスを使用してください。 //data/regression:unittest/.

複数のファイルを使用する必要があるテストなどの外部ルールは、 明示的に宣言する必要があります。filegroup() を使用すると、次のことができます。 BUILD ファイルにファイルをグループ化します。

filegroup(
        name = 'my_data',
        srcs = glob(['my_unittest_data/*'])
)

これにより、テストでデータの依存関係としてラベル my_data を参照できます。

BUILD ファイル 公開設定