このページでは、Bazel のクエリ言語を使用してコード内の 依存関係をトレースする方法について説明します。
言語の詳細と --output フラグの詳細については、
リファレンス マニュアルの Bazel クエリ リファレンス
と Bazel cquery リファレンスをご覧ください。コマンドラインで
bazel help query または bazel help cquery と入力すると、ヘルプが表示されます。
ターゲットが見つからないなどのエラーを無視してクエリを実行するには、
--keep_going フラグを使用します。
ルールの依存関係を見つける
//foo の依存関係を確認するには、bazel query で
deps 関数を使用します。
$ bazel query "deps(//foo)" //foo:foo //foo:foo-dep ...
これは、//foo のビルドに必要なすべてのターゲットのセットです。
2 つのパッケージ間の依存関係チェーンをトレースする
ライブラリ //third_party/zlib:zlibonly は
//foo の BUILD ファイルにはありませんが、間接的な依存関係です。この依存関係パスをトレースするにはどうすればよいですか?ここでは、
allpaths と somepath の 2 つの関数が役立ちます。ビルドしたアーティファクトに含まれるものだけに関心があり、考えられるすべてのジョブに関心がない場合は、
ツール依存関係を--notool_depsを使用して除外することもできます。
すべての依存関係のグラフを可視化するには、bazel query の出力を
dot コマンドライン ツールにパイプします。
$ bazel query "allpaths(//foo, third_party/...)" --notool_deps --output graph | dot -Tsvg > /tmp/deps.svg
依存関係グラフが大きく複雑な場合は、単一のパスから始めることをおすすめします。
$ 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 ルールをビルドするには、まず Protocol
Compiler をビルドする必要があります。そのため、すべての genproto ルールは
プロトコル コンパイラに暗黙的に依存します。これらの依存関係はビルドファイルには記載されていませんが、
ビルドツールによって追加されます。暗黙的な依存関係の完全なセットは
現在ドキュメント化されていません。--noimplicit_deps を使用すると、これらの依存関係をクエリ結果から除外できます。cquery の場合、これには解決済みのツールチェーンが含まれます。
逆依存関係
特定のターゲットに依存するターゲットのセットを知りたい場合があります。たとえば、
コードを変更する場合、どのコードが破損する可能性があるかを知りたい場合があります。
rdeps(u, x) を使用すると、u の推移的閉包内の x のターゲットの逆依存関係を見つけることができます。
Bazel の Sky Query
は 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/contrib を除く、foo ツリーが依存するパッケージは何ですか?
bazel query 'deps(foo/... except foo/contrib/...)' --output package
存在するルールの依存関係 ...
bar はどの 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 テストは、//foo プロダクション バイナリが 依存しない どの C++ ライブラリに依存していますか?
bazel query 'kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo))'この依存関係が存在する理由 ...
bar が groups2 に依存するのはなぜですか?
bazel query 'somepath(bar/...,groups2/...:*)'
このクエリの結果を取得すると、多くの場合、単一の
ターゲットがbarの予期しない、または重大で望ましくない
依存関係として際立っていることがわかります。クエリは次のようにさらに絞り込むことができます。
docker/updater:updater_systest(py_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
依存するもの ...
bar の下のどのルールが 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 までの最長パスを取得できませんが、開始点から最も遠いノード(またはノード)を見つけたり、x から依存するすべての y までの最長パスの長さを表示したりできます。maxrank を使用します。
bazel query 'deps(//foo-tests)' --output maxrank | tail -1 85 //third_party/zlib:zutil.c
この結果は、このビルドで 順序どおりに実行する必要がある長さ 85 のパスが存在することを示しています。