クエリガイド

問題を報告する ソースを表示

このページでは、Bazel のクエリ言語を使用してコード内の依存関係をトレースする方法を説明します。

言語の詳細と --output フラグの詳細については、リファレンス マニュアル、Bazel クエリのリファレンスBazel cquery のリファレンスをご覧ください。コマンドラインで「bazel help query」または「bazel help cquery」と入力すると、ヘルプが表示されます。

ターゲットの欠落などのエラーを無視してクエリを実行するには、--keep_going フラグを使用します。

ルールの依存関係を検索する

//foo の依存関係を確認するには、bazel クエリで deps 関数を使用します。

$ bazel query "deps(//foo)"
//foo:foo
//foo:foo-dep
...

これは、//foo のビルドに必要なすべてのターゲットのセットです。

2 つのパッケージ間の依存関係チェーンをトレースする

ライブラリ //third_party/zlib:zlibonly//foo の BUILD ファイル内にありませんが、間接的な依存関係です。この依存関係のパスをトレースするにはどうすればよいですか?これには、allpathssomepath という 2 つの有用な関数があります。また、考えられるすべてのジョブではなく、作成したアーティファクトに含まれる内容のみを重視する場合は、--notool_deps でツールの依存関係を除外することもできます。

すべての依存関係のグラフを可視化するには、dot コマンドライン ツールを使用して、Bazel クエリの出力をパイプします。

$ bazel query "allpaths(//foo, third_party/...)" --notool_deps --output graph | dot -Tsvg > /tmp/deps.svg

依存関係グラフが大規模で複雑な場合は、1 つのパスから始めることをおすすめします。

$ bazel query "somepath(//foo:foo, third_party/zlib:zlibonly)"
//foo:foo
//translations/tools:translator
//translations/base:base
//third_party/py/MySQL:MySQL
//third_party/py/MySQL:_MySQL.so
//third_party/mysql:mysql
//third_party/zlib:zlibonly

allpaths--output graph を指定しない場合、依存関係グラフのフラット化されたリストが取得されます。

$ bazel query "allpaths(//foo, third_party/...)"
  ...many errors detected in BUILD files...
//foo:foo
//translations/tools:translator
//translations/tools:aggregator
//translations/base:base
//tools/pkg:pex
//tools/pkg:pex_phase_one
//tools/pkg:pex_lib
//third_party/python:python_lib
//translations/tools:messages
//third_party/py/xml:xml
//third_party/py/xml:utils/boolean.so
//third_party/py/xml:parsers/sgmlop.so
//third_party/py/xml:parsers/pyexpat.so
//third_party/py/MySQL:MySQL
//third_party/py/MySQL:_MySQL.so
//third_party/mysql:mysql
//third_party/openssl:openssl
//third_party/zlib:zlibonly
//third_party/zlib:zlibonly_v1_2_3
//third_party/python:headers
//third_party/openssl:crypto

例外: 暗黙的な依存関係

//foo の BUILD ファイルは、//translations/tools:aggregator を参照しません。では、直接依存関係はどこにあるのでしょうか。

一部のルールには、追加のライブラリまたはツールへの暗黙の依存関係が含まれています。たとえば、genproto ルールを作成するには、まずプロトコル コンパイラをビルドする必要があります。これにより、すべての genproto ルールがプロトコル コンパイラに対する暗黙的な依存関係を持ちます。これらの依存関係はビルドファイルに記載されていませんが、ビルドツールによって追加されます。現在、暗黙的な依存関係の完全なドキュメントは文書化されていません。--noimplicit_deps を使用すると、クエリ結果からこれらの依存関係を除外できます。cquery の場合、解決されたツールチェーンが組み込まれます。

リバース依存関係

一部のターゲットに依存するターゲットのセットを知りたい場合があります。たとえば、コードを変更する場合は、他のどのコードを壊すかを知りたい場合があります。rdeps(u, x) を使用すると、u の推移的なクロージャ内で、x 内のターゲットの逆依存関係を見つけることができます。

Bazel の Sky クエリでは allrdeps 関数がサポートされています。これにより、指定したユニバースで逆方向のクエリを実行できます。

その他の用途

bazel query を使用すると、多くの依存関係の関係を分析できます。

作業 ...

foo の下にどのようなパッケージがありますか?

bazel query 'foo/...' --output package

foo パッケージで定義されているルールは何ですか?

bazel query 'kind(rule, foo:*)' --output label_kind

foo パッケージのルールにより生成されるファイル

bazel query 'kind("generated file", //foo:*)'

Starlark マクロ foo によって生成されるターゲットは何ですか。

bazel query 'attr(generator_function, foo, //path/to/search/...)'

//foo のビルドに必要な BUILD ファイルは何ですか。

bazel query 'buildfiles(deps(//foo))' | cut -f1 -d:

test_suite が拡張する個々のテストは何ですか?

bazel query 'tests(//foo:smoke_tests)'

C++ テストは次のうちどれですか。

bazel query 'kind(cc_.*, tests(//foo:smoke_tests))'

次のうち小規模なものですか?普通?ラージ?

bazel query 'attr(size, small, tests(//foo:smoke_tests))'

bazel query 'attr(size, medium, tests(//foo:smoke_tests))'

bazel query 'attr(size, large, tests(//foo:smoke_tests))'

foo の下にあるパターンに一致するテストは何ですか?

bazel query 'filter("pa?t", kind(".*_test rule", //foo/...))'

パターンは正規表現で、ルールの完全な名前に適用されます。これは

bazel query 'kind(".*_test rule", //foo/...)' | grep -E 'pa?t'

ファイル path/to/file/bar.java に含まれているパッケージは何ですか?

 bazel query path/to/file/bar.java --output=package

path/to/file/bar.java? のビルドラベル

bazel query path/to/file/bar.java

path/to/file/bar.java をソースとして含むルール ターゲットは何ですか?

fullname=$(bazel query path/to/file/bar.java)
bazel query "attr('srcs', $fullname, ${fullname//:*/}:*)"

どのようなパッケージ依存関係が存在するのか ...

foo が依存するパッケージ(foo をビルドするために確認する必要があるもの)

bazel query 'buildfiles(deps(//foo:foo))' --output package

foo ツリーが依存するパッケージ(foo/contrib を除く)

bazel query 'deps(foo/... except foo/contrib/...)' --output package

存在するルールの依存関係

バーが依存する genproto ルール

bazel query 'kind(genproto, deps(bar/...))'

サーブレット ツリーで Java バイナリルールによって推移的に依存する JNI(C++)ライブラリの定義を確認します。

bazel query 'some(kind(cc_.*library, deps(kind(java_binary, //java/com/example/frontend/...))))' --output location
それらに依存するすべての Java バイナリの定義を確認する
bazel query 'let jbs = kind(java_binary, //java/com/example/frontend/...) in
  let cls = kind(cc_.*library, deps($jbs)) in
    $jbs intersect allpaths($jbs, $cls)'

どのようなファイルの依存関係が存在するのか。

foo のビルドに必要な Java ソースファイルの完全なセットは、次のうちどれですか。

ソースファイル:

bazel query 'kind("source file", deps(//path/to/target/foo/...))' | grep java$

生成されたファイル:

bazel query 'kind("generated file", deps(//path/to/target/foo/...))' | grep java$

QUX のテストを構築するために必要な Java ソースファイルの完全なセットは?

ソースファイル:

bazel query 'kind("source file", deps(kind(".*_test rule", javatests/com/example/qux/...)))' | grep java$

生成されたファイル:

bazel query 'kind("generated file", deps(kind(".*_test rule", javatests/com/example/qux/...)))' | grep java$

X と Y の依存関係にはどのような違いがありますか。

//foo//foo:foolib に依存しないターゲットは何ですか?

bazel query 'deps(//foo) except deps(//foo:foolib)'

foo テストが依存する C++ ライブラリ、//foo 本番環境バイナリが依存していないものは何ですか。

bazel query 'kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo))'

この依存関係が存在する理由

bargroups2 に依存する理由

bazel query 'somepath(bar/...,groups2/...:*)'

このクエリの結果が得られると、単一のターゲットが bar の予期しない、または悪質な、重要な依存関係であることに気づくことがよくあります。クエリをさらに絞り込むには、次のようにします。

docker/updater:updater_systestpy_test)から依存する cc_library へのパスを表示する

bazel query 'let cc = kind(cc_library, deps(docker/updater:updater_systest)) in
  somepath(docker/updater:updater_systest, $cc)'

ライブラリ //photos/frontend:lib が同じライブラリ //third_party/jpeglib//third_party/jpeg の 2 つのバリアントに依存しているのはなぜですか。

このクエリは、「両方のライブラリに依存する //photos/frontend:lib のサブグラフを表示」に要約されます。トポロジ形式で表示した場合、結果の最後の要素が最も問題の原因となります。

bazel query 'allpaths(//photos/frontend:lib, //third_party/jpeglib)
                intersect
               allpaths(//photos/frontend:lib, //third_party/jpeg)'
//photos/frontend:lib
//photos/frontend:lib_impl
//photos/frontend:lib_dispatcher
//photos/frontend:icons
//photos/frontend/modules/gadgets:gadget_icon
//photos/thumbnailer:thumbnail_lib
//third_party/jpeg/img:renderer

依存する要因

棒の下のどのルールが Y に依存するか?

bazel query 'bar/... intersect allpaths(bar/..., Y)'

T のパッケージに含まれる T に直接依存するターゲットは、次のうちどれですか。

bazel query 'same_pkg_direct_rdeps(T)'

依存関係の互換性を破る方法

bar が X に依存しないようにするため、どの依存関係パスを解除する必要がありますか?

グラフを svg ファイルに出力するには:

bazel query 'allpaths(bar/...,X)' --output graph | dot -Tsvg > /tmp/dep.svg

その他

//foo-tests ビルドには連続したステップがいくつありますか。

残念ながら、クエリ言語は現在、x から y までの最長パスを示すことができませんが、開始点から最も遠い(a)ノードを発見することや、x から依存するすべての y への最長パスの length を表示することはできます。maxrank を使用します。

bazel query 'deps(//foo-tests)' --output maxrank | tail -1
85 //third_party/zlib:zutil.c

結果は、このビルドでは長さ 85 のパスが存在し、これは順番に存在している必要があることを示しています。