このページは、bazel query
を使用してビルド依存関係を分析するときに使用される Bazel クエリ言語のリファレンス マニュアルです。また、bazel query
がサポートする出力形式についても説明します。
実用的なユースケースについては、Bazel クエリの使い方をご覧ください。
その他のクエリのリファレンス
Bazel には、読み込み後フェーズのターゲット グラフで実行される query
に加えて、アクショングラフクエリと構成可能なクエリが含まれています。
アクショングラフのクエリ
アクショングラフ クエリ(aquery
)は、分析後の構成済みターゲット グラフで動作し、アクション、アーティファクト、およびそれらの関連性に関する情報を公開します。aquery
は、構成済みターゲット グラフから生成されたアクション/アーティファクトのプロパティに興味がある場合に便利です。たとえば、実行される実際のコマンド、その入力、出力、頭文字などです。
詳細については、aquery リファレンスをご覧ください。
構成可能なクエリ
従来の Bazel クエリは、読み込み後のフェーズ ターゲット グラフで実行されるため、構成とその関連コンセプトはありません。特に、選択ステートメントは正しく解決されず、代わりに選択の可能なすべての解決策が返されます。ただし、構成可能なクエリ環境 cquery
は構成を適切に処理しますが、この元のクエリのすべての機能を提供しているわけではありません。
詳細については、cquery リファレンスをご覧ください。
例
bazel query
はどのように使用されていますか?一般的な例を次に示します。
//foo
ツリーが //bar/baz
に依存するのはなぜですか?パスを表示する:
somepath(foo/..., //bar/baz:all)
すべての foo
テストが依存する C++ ライブラリは、foo_bin
ターゲットが依存しないライブラリとはどのようなものですか?
kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo:foo_bin))
トークン: 語彙構文
クエリ言語の式は、次のトークンで構成されます。
キーワード(
let
など)。キーワードは言語の予約語であり、それぞれについて以下で説明します。キーワードの完全なセットは次のとおりです。単語: 「
foo/...
」、「.*test rule
」、「//bar/baz:all
」など。文字列が「引用符で囲まれている」(先頭と末尾が単一引用符 ' または二重引用符 " で囲まれている)場合は、単語です。文字列が引用符で囲まれていない場合でも、単語として解析されることがあります。引用符で囲まれていない単語は、アルファベット文字 A ~ Za ~ z、数字 0 ~ 9、特殊文字*/@.-_:$~[]
(アスタリスク、スラッシュ、アットマーク、ピリオド、ハイフン、アンダースコア、コロン、ドル記号、波形符号、左角かっこ、右角かっこ)から取得された文字のシーケンスです。ただし、引用符で囲まれていない単語は、相対ターゲット名がこれらの文字で始まる場合でも、ハイフン-
またはアスタリスク*
で始まることはできません。外部リポジトリを参照するラベルの処理を簡素化するための特別なルールとして、@@
で始まる引用符なしの単語に+
文字を含めることができます。引用符で囲まれていない単語には、ターゲット名で使用できる場合でも、プラス記号
+
や等号=
の文字を含めることはできません。クエリ式を生成するコードを記述する場合は、ターゲット名を引用符で囲む必要があります。ユーザー指定の値から Bazel クエリ式を作成するスクリプトを作成する場合は、引用符を使用する必要があります。
//foo:bar+wiz # WRONG: scanned as //foo:bar + wiz. //foo:bar=wiz # WRONG: scanned as //foo:bar = wiz. "//foo:bar+wiz" # OK. "//foo:bar=wiz" # OK.
この引用符は、シェルで必要となる引用符(次に例を示します)とは別に使用します。
bazel query ' "//foo:bar=wiz" ' # single-quotes for shell, double-quotes for Bazel.
キーワードと演算子は、引用符で囲むと通常の単語として扱われます。たとえば、
some
はキーワードですが、「some」は単語です。foo
と「foo」はどちらも単語です。ただし、ターゲット名に一重または二重の引用符を使用する場合は注意が必要です。1 つ以上のターゲット名を引用する場合は、1 種類の引用符(すべて一重引用符またはすべて二重引用符)のみを使用します。
Java クエリ文字列の例を次に示します。
'a"'a' # WRONG: Error message: unclosed quotation. "a'"a" # WRONG: Error message: unclosed quotation. '"a" + 'a'' # WRONG: Error message: unexpected token 'a' after query expression '"a" + ' "'a' + "a"" # WRONG: Error message: unexpected token 'a' after query expression ''a' + ' "a'a" # OK. 'a"a' # OK. '"a" + "a"' # OK "'a' + 'a'" # OK
この構文は、ほとんどの場合引用符が不要になるように選択されています。(通常ではない)
".*test rule"
の例では引用符が必要です。先頭がピリオドで、スペースが含まれています。"cc_library"
を引用する必要はありませんが、引用しても問題ありません。句読点: かっこ
()
、ピリオド.
、カンマ,
など。句読点を含む単語(上記の例外を除く)は引用符で囲む必要があります。
引用符で囲まれた単語の外側の空白文字は無視されます。
Bazel クエリ言語のコンセプト
Bazel クエリ言語は式の言語です。すべての式は、ターゲットの部分順序集合、つまりターゲットのグラフ(DAG)に評価されます。これが唯一のデータ型です。
セットとグラフは同じデータ型を指しますが、その異なる側面を強調します。たとえば、次のようにします。
- セット: ターゲットの部分順序は重要ではありません。
- グラフ: ターゲットの部分順序は重要です。
依存関係グラフ内の循環
ビルド依存関係グラフは非循環である必要があります。
クエリ言語で使用されるアルゴリズムは非循環グラフでの使用を目的としていますが、循環に対しても堅牢です。サイクルの処理方法の詳細は指定されていないため、信頼しないでください。
暗黙的な依存関係
Bazel は、BUILD
ファイルで明示的に定義されたビルド依存関係に加えて、ルールに暗黙的な依存関係を追加します。暗黙的な依存関係は、次のように定義できます。
デフォルトでは、bazel query
はクエリ結果の計算時に暗黙的な依存関係を考慮します。この動作は、--[no]implicit_deps
オプションで変更できます。
クエリは構成を考慮しないため、必要なツールチェーン タイプのみが依存関係と見なされ、ツールチェーンの実装は依存関係と見なされません。ツールチェーン ドキュメントをご覧ください。
健全性
Bazel クエリ言語式は、ビルド依存関係グラフに対して動作します。これは、すべての BUILD
ファイル内のすべてのルール宣言によって暗黙的に定義されるグラフです。このグラフは抽象的であり、ビルドのすべてのステップを実行する方法の完全な説明ではないことを理解することが重要です。ビルドを実行するには、構成も必要です。詳細については、ユーザーガイドの構成セクションをご覧ください。
Bazel クエリ言語で式を評価した結果は、すべての構成で true になります。つまり、保守的な過剰近似であり、正確ではない可能性があります。クエリツールを使用してビルド中に必要なすべてのソースファイルのセットを計算すると、実際に必要な数よりも多くのファイルが報告される場合があります。たとえば、ビルドでメッセージ翻訳機能を使用しないつもりでも、クエリツールにはメッセージ翻訳をサポートするために必要なすべてのファイルが含まれます。
グラフの順序の保持について
オペレーションは、サブ式から継承された順序制約を保持します。これは「部分順序の保存則」と考えることができます。例として、特定のターゲットの依存関係の推移閉包を決定するクエリを実行すると、結果セットは依存関係グラフに従って並べ替えられます。このセットをフィルタして file
タイプのターゲットのみを含めると、結果のサブセット内のすべてのターゲットペアの間に同じ推移的部分順序関係が保持されます。これらのペアのどれも元のグラフで実際に直接接続されていない場合でも同様です。(ビルド依存関係グラフにファイル間のエッジはありません)。
ただし、すべての演算子は順序を保持しますが、集合演算子など、一部のオペレーションは独自の順序制約を導入しません。次の式について考えてみましょう。
deps(x) union y
最終的な結果セットの順序は、サブ式のすべての順序制約を保持することが保証されます。つまり、x
のすべての推移的依存関係が相互に正しく順序付けられます。ただし、このクエリでは、y
内のターゲットの順序や、deps(x)
内のターゲットの y
内のターゲットに対する順序について保証はされません(deps(x)
にも存在する y
内のターゲットを除く)。
順序の制約を導入する演算子には、allpaths
、deps
、rdeps
、somepath
、ターゲット パターンのワイルドカード package:*
、dir/...
などがあります。
スカイクエリ
Sky Query は、指定されたユニバース スコープで動作するクエリモードです。
SkyQuery でのみ使用できる特別な関数
Sky Query モードには、追加のクエリ関数 allrdeps
と rbuildfiles
があります。これらの関数はユニバース スコープ全体で動作します(そのため、通常のクエリには適していません)。
ユニバース スコープの指定
Sky クエリモードは、次の 2 つのフラグ(--universe_scope
または --infer_universe_scope
)と --order_output=no
を渡すことで有効になります。--universe_scope=<target_pattern1>,...,<target_patternN>
は、ターゲット パターンで指定されたターゲット パターンの推移閉包をプリロードするようクエリに指示します。これは加算と減算の両方を行うことができます。すべてのクエリはこの「スコープ」で評価されます。特に、allrdeps
演算子と rbuildfiles
演算子は、このスコープの結果のみを返します。--infer_universe_scope
は、クエリ式から --universe_scope
の値を推論するように Bazel に指示します。この推論された値は、クエリ式の一意のターゲット パターンのリストですが、目的の値ではない場合があります。次に例を示します。
bazel query --infer_universe_scope --order_output=no "allrdeps(//my:target)"
このクエリ式の一意のターゲット パターンのリストは ["//my:target"]
であるため、Bazel はこれを呼び出しと同じように扱います。
bazel query --universe_scope=//my:target --order_output=no "allrdeps(//my:target)"
ただし、--universe_scope
を含むクエリの結果は //my:target
のみです。//my:target
の逆依存関係は、コンストラクションによってユニバースには存在しません。一方で、次のことを検討してください。
bazel query --infer_universe_scope --order_output=no "tests(//a/... + b/...) intersect allrdeps(siblings(rbuildfiles(my/starlark/file.bzl)))"
これは、特定の .bzl
ファイルを使用しているターゲットに間接的に依存するターゲットを含むディレクトリのターゲットの tests
展開でテスト ターゲットを計算しようとする有意なクエリ呼び出しです。ここで、--infer_universe_scope
は便利なものです。特に、--universe_scope
を選択した場合にクエリ式を手動で解析する必要がある場合は便利です。
そのため、allrdeps
や rbuildfiles
などのユニバース スコープ演算子を使用するクエリ式では、その動作が望ましい場合にのみ --infer_universe_scope
を使用してください。
Sky Query には、デフォルト クエリと比較していくつかのメリットとデメリットがあります。主なデメリットは、グラフの順序に従って出力を並べ替えることができないため、特定の出力形式が禁止されることです。デフォルト クエリでは使用できない 2 つの演算子(allrdeps
と rbuildfiles
)が用意されている点が利点です。また、Sky Query は、デフォルトの実装が行う新しいグラフを作成するのではなく、Skyframe グラフをイントロスペクトして処理を行います。したがって、高速でメモリ使用量が少ない場合があります。
式: 文法の構文とセマンティクス
以下は、EBNF 表記で記述された Bazel クエリ言語の文法です。
expr ::= word
| let name = expr in expr
| (expr)
| expr intersect expr
| expr ^ expr
| expr union expr
| expr + expr
| expr except expr
| expr - expr
| set(word *)
| word '(' int | word | expr ... ')'
以降のセクションでは、この文法の各生成規則について順に説明します。
ターゲット パターン
expr ::= word
構文的には、ターゲット パターンは単なる単語です。ターゲットの(順序なしの)セットとして解釈されます。最も単純なターゲット パターンはラベルで、単一のターゲット(ファイルまたはルール)を識別します。たとえば、ターゲット パターン //foo:bar
は、1 つの要素(ターゲット、bar
ルール)を含むセットとして評価されます。
ターゲット パターンは、パッケージとターゲットのワイルドカードを含めるようにラベルを一般化します。たとえば、foo/...:all
(または foo/...
)は、foo
ディレクトリの下にあるすべてのパッケージのすべてのルールを含むセットに評価されるターゲット パターンです。bar/baz:all
は、bar/baz
パッケージ内のすべてのルールを含むセットに評価されるターゲット パターンです(サブパッケージは含まれません)。
同様に、foo/...:*
は、foo
ディレクトリの下にあるすべてのパッケージ内のすべてのターゲット(ルールとファイル)を含むセットに評価されるターゲット パターンです。bar/baz:*
は、bar/baz
パッケージ内のすべてのターゲットを含むセットに評価されますが、サブパッケージは含まれません。
:*
ワイルドカードはファイルとルールの両方に一致するため、クエリでは :all
よりも有用な場合があります。逆に、:all
ワイルドカード(foo/...
などのターゲット パターンに暗黙的に含まれる)は、通常、ビルドに便利です。
bazel query
ターゲット パターンは、bazel build
ビルド ターゲットと同じように機能します。詳細については、ターゲット パターンをご覧ください。または、bazel help target-syntax
と入力します。
ターゲット パターンは、(ラベルの場合は)単一要素のセットに評価されるか、(数千の要素を含む foo/...
の場合など)多数の要素を含むセットに評価されます。ターゲット パターンがターゲットに一致しない場合、空のセットに評価されます。
ターゲット パターン式の結果内のすべてのノードは、依存関係に従って相互に正しく並べ替えられます。したがって、foo:*
の結果は、パッケージ foo
内のターゲットのセットだけでなく、それらのターゲットに関するグラフでもあります。(結果ノードと他のノードとの相対的な順序については保証されません)。詳細については、グラフの順序のセクションをご覧ください。
変数
expr ::= let name = expr1 in expr2
| $name
Bazel クエリ言語では、変数の定義と参照が可能です。let
式の評価結果は expr2 と同じで、変数 name の自由な出現はすべて expr1 の値に置き換えられます。
たとえば、let v = foo/... in allpaths($v, //common) intersect $v
は allpaths(foo/...,//common) intersect foo/...
と同じです。
囲む let name = ...
式以外で変数参照 name
が出現すると、エラーになります。つまり、トップレベルのクエリ式には自由変数を含めることはできません。
上記の文法生成規則では、name
は word に似ていますが、C プログラミング言語で有効な識別子であるという追加の制約があります。変数への参照には、先頭に「$」文字を付ける必要があります。
各 let
式は 1 つの変数のみを定義しますが、ネストすることはできます。
ターゲット パターンと変数参照はどちらも単一のトークン(単語)で構成されているため、構文の曖昧さが生じます。ただし、有効な変数名である単語のサブセットは、有効なターゲット パターンである単語のサブセットと重複しないため、意味的なあいまいさはありません。
技術的には、let
式はクエリ言語の表現力を高めません。この言語で表現できるクエリは、let
式なしでも表現できます。ただし、多くのクエリの簡潔性が向上し、クエリ評価の効率化にもつながる可能性があります。
かっこ付きの式
expr ::= (expr)
かっこはサブ式を関連付けて、評価順序を強制します。かっこで囲まれた式は、引数の値に評価されます。
代数集合演算: 交差、結合、集合差
expr ::= expr intersect expr
| expr ^ expr
| expr union expr
| expr + expr
| expr except expr
| expr - expr
これらの 3 つの演算子は、引数に対して通常の集合演算を計算します。各演算子には、intersect
などの名義形式と ^
などの記号形式の 2 つの形式があります。どちらの形式も同等ですが、記号形式の方が入力が簡単です。(わかりやすくするため、このページの残りの部分では名詞形を使用します)。
次に例を示します。
foo/... except foo/bar/...
は、foo/...
と一致するが foo/bar/...
と一致しないターゲットのセットと評価されます。
同じクエリは次のように記述できます。
foo/... - foo/bar/...
intersect
(^
)と union
(+
)の演算は可換(対称)です。except
(-
)は非対称です。パーサーは、3 つの演算子をすべて左結合で同じ優先度と見なすため、括弧を使用することをおすすめします。たとえば、次の式のうち最初の 2 つは同じですが、3 つ目は同じではありません。
x intersect y union z
(x intersect y) union z
x intersect (y union z)
外部ソースからターゲットを読み取る: セット
expr ::= set(word *)
set(a b c ...)
演算子は、空白文字(カンマなし)で区切られた 0 個以上のターゲット パターンのセットの結合を計算します。
set()
は、Bourne シェルの $(...)
機能と組み合わせて、1 つのクエリの結果を通常のテキスト ファイルに保存し、他のプログラム(標準の UNIX シェルツールなど)を使用してそのテキスト ファイルを操作し、結果を値としてクエリツールに戻して、さらに処理できるようにします。次に例を示します。
bazel query deps(//my:target) --output=label | grep ... | sed ... | awk ... > foo
bazel query "kind(cc_binary, set($(<foo)))"
次の例では、awk
プログラムを使用して maxrank
値をフィルタリングすることで、kind(cc_library, deps(//some_dir/foo:main, 5))
が計算されます。
bazel query 'deps(//some_dir/foo:main)' --output maxrank | awk '($1 < 5) { print $2;} ' > foo
bazel query "kind(cc_library, set($(<foo)))"
これらの例では、$(<foo)
は $(cat foo)
の省略形ですが、cat
以外のシェルコマンド(前の awk
コマンドなど)も使用できます。
関数
expr ::= word '(' int | word | expr ... ')'
クエリ言語にはいくつかの関数が定義されています。関数の名前によって、必要な引数の数と型が決まります。使用できる関数は次のとおりです。
allpaths
attr
buildfiles
rbuildfiles
deps
filter
kind
labels
loadfiles
rdeps
allrdeps
same_pkg_direct_rdeps
siblings
some
somepath
tests
visible
依存関係の推移的閉包: deps
expr ::= deps(expr)
| deps(expr, depth)
deps(x)
演算子は、引数セット x の依存関係の推移閉包によって形成されたグラフとして評価されます。たとえば、deps(//foo)
の値は、単一ノード foo
をルートとする依存関係グラフで、すべての依存関係が含まれます。deps(foo/...)
の値は、foo
ディレクトリの下のすべてのパッケージ内のすべてのルールがルートとなる依存関係グラフです。このコンテキストでは、「依存関係」はルールとファイル ターゲットのみを意味します。したがって、これらのターゲットの作成に必要な BUILD
ファイルと Starlark ファイルはここに含まれません。そのためには、buildfiles
演算子を使用する必要があります。
生成されたグラフは、依存関係に従って並べ替えられます。詳細については、グラフの順序のセクションをご覧ください。
deps
演算子は、2 番目の引数(検索の深さの上限を指定する整数リテラル)をオプションで受け取ります。したがって、deps(foo:*, 0)
は foo
パッケージ内のすべてのターゲットを返します。deps(foo:*, 1)
には、foo
パッケージ内のターゲットの直接前提条件がさらに含まれ、deps(foo:*, 2)
には、deps(foo:*, 1)
内のノードから直接到達可能なノードがさらに含まれます。(これらの数値は、minrank
出力形式で示されるランクに対応しています)。depth パラメータを省略すると、検索は無制限になります。前提条件の反射的推移閉包が計算されます。
逆依存関係の推移閉包: rdeps
expr ::= rdeps(expr, expr)
| rdeps(expr, expr, depth)
rdeps(u, x)
演算子は、ユニバース セット u の推移閉包内の引数セット x の逆依存関係として評価されます。
生成されたグラフは、依存関係に従って並べ替えられます。詳しくは、グラフの順序のセクションをご覧ください。
rdeps
演算子は、オプションの 3 番目の引数を受け入れます。これは、検索の深さの上限を指定する整数リテラルです。結果のグラフには、引数セット内の任意のノードから指定された深さの距離内にあるノードのみが含まれます。したがって、rdeps(//foo, //common, 1)
は、//common
に直接依存する //foo
の推移閉包内のすべてのノードに評価されます。(これらの数値は、minrank
の出力形式で示されるランクに対応しています)。depth パラメータを省略すると、検索は無制限になります。
すべての逆依存関係の推移閉包: allrdeps
expr ::= allrdeps(expr)
| allrdeps(expr, depth)
allrdeps
演算子は rdeps
演算子とまったく同じように動作しますが、「ユニバース セット」は個別に指定されるのではなく、--universe_scope
フラグが評価した値になります。したがって、--universe_scope=//foo/...
が渡された場合、allrdeps(//bar)
は rdeps(//foo/..., //bar)
と同等です。
同じパッケージ内の直接の逆依存関係: same_pkg_direct_rdeps
expr ::= same_pkg_direct_rdeps(expr)
same_pkg_direct_rdeps(x)
演算子は、引数セット内のターゲットと同じパッケージに存在し、そのターゲットに直接依存するターゲットの完全なセットとして評価されます。
ターゲットのパッケージの処理: 兄弟
expr ::= siblings(expr)
siblings(x)
演算子は、引数セット内のターゲットと同じパッケージにあるターゲットの完全なセットを評価します。
任意の選択: 一部
expr ::= some(expr)
| some(expr, count )
some(x, k)
演算子は、引数セット x から最大 k 個のターゲットを任意に選択し、それらのターゲットのみを格納するセットとして評価します。パラメータ k は省略可能です。指定しない場合、結果は任意で選択された 1 つのターゲットのみを含むシングルトン セットになります。引数セット x のサイズが k より小さい場合、引数セット x 全体が返されます。
たとえば、式 some(//foo:main union //bar:baz)
は、//foo:main
または //bar:baz
を含むシングルトン セットに評価されます。どちらかは定義されていません。式 some(//foo:main union //bar:baz, 2)
または some(//foo:main union //bar:baz, 3)
は、//foo:main
と //bar:baz
の両方を返します。
引数がシングルトンの場合、some
は同一性関数を計算します。some(//foo:main)
は //foo:main
と同等です。
式 some(//foo:main intersect //bar:baz)
のように、指定された引数セットが空の場合はエラーになります。
パス演算子: somepath、allpaths
expr ::= somepath(expr, expr)
| allpaths(expr, expr)
somepath(S, E)
演算子と allpaths(S, E)
演算子は、2 つのターゲット セット間のパスを計算します。どちらのクエリも、開始点のセット S と終了点のセット E の 2 つの引数を受け入れます。somepath
は、S 内のターゲットから E 内のターゲットまでの任意のパス上のノードのグラフを返します。allpaths
は、S 内の任意のターゲットから E 内の任意のターゲットまでのすべてのパス上のノードのグラフを返します。
生成されたグラフは、依存関係に従って並べ替えられます。詳細については、グラフの順序のセクションをご覧ください。
ターゲットの種類のフィルタリング: kind
expr ::= kind(word, expr)
kind(pattern, input)
演算子は、一連のターゲットにフィルタを適用し、想定される種類ではないターゲットを破棄します。pattern パラメータは、一致させるターゲットの種類を指定します。
たとえば、次の BUILD
ファイル(パッケージ p
用)で定義された 4 つのターゲットの種類は、次の表のとおりです。
コード | ターゲット | 種類 |
---|---|---|
genrule( name = "a", srcs = ["a.in"], outs = ["a.out"], cmd = "...", ) |
//p:a |
genrule ルール |
//p:a.in |
ソースファイル | |
//p:a.out |
生成されたファイル | |
//p:BUILD |
ソースファイル |
したがって、kind("cc_.* rule", foo/...)
は foo
の下のすべての cc_library
、cc_binary
などのルール ターゲットのセットに評価され、kind("source file", deps(//foo))
は //foo
ターゲットの依存関係の推移閉包内のすべてのソースファイルのセットになります。
pattern 引数を引用符で囲む必要がある場合が多くあります。引用符で囲まないと、source
file
や .*_test
などの多くの正規表現が、パーサーによって単語と見なされなくなるためです。
package group
と一致する場合、:all
で終わるターゲットでは結果が得られないことがあります。代わりに :all-targets
を使用してください。
ターゲット名のフィルタリング: フィルタ
expr ::= filter(word, expr)
filter(pattern, input)
演算子は、一連のターゲットにフィルタを適用し、ラベル(絶対形式)がパターンと一致しないターゲットを破棄します。入力のサブセットとして評価されます。
最初の引数 pattern は、ターゲット名の正規表現を含む単語です。filter
式は、x がセット input のメンバーであり、x のラベル(絶対形式の //foo:bar
など)に正規表現 pattern の(アンカーなしの)一致が含まれているすべてのターゲット x を含むセットとして評価されます。すべてのターゲット名は //
で始まるため、^
正規表現アンカーの代わりに使用できます。
多くの場合、この演算子は intersect
演算子よりもはるかに高速で堅牢な代替手段となります。たとえば、//foo:foo
ターゲットのすべての bar
依存関係を確認するには、次のように評価します。
deps(//foo) intersect //bar/...
ただし、このステートメントでは、bar
ツリー内のすべての BUILD
ファイルを解析する必要があります。これにより、処理速度が低下し、無関係な BUILD
ファイルでエラーが発生しやすくなります。代替案として、次の方法があります。
filter(//bar, deps(//foo))
これにより、まず //foo
依存関係のセットが計算され、指定されたパターンに一致するターゲット(名前に //bar
がサブストリングとして含まれているターゲット)のみがフィルタされます。
filter(pattern,
expr)
演算子のもう 1 つの一般的な用途は、名前または拡張子で特定のファイルをフィルタすることです。次に例を示します。
filter("\.cc$", deps(//foo))
//foo
のビルドに使用されたすべての .cc
ファイルのリストが表示されます。
ルール属性のフィルタリング: attr
expr ::= attr(word, word, expr)
attr(name, pattern, input)
演算子は、ターゲットのセットにフィルタを適用し、ルールではないターゲット、属性 name が定義されていないルール ターゲット、属性値が指定された正規表現 pattern と一致しないルール ターゲットを破棄します。入力のサブセットに評価されます。
最初の引数 name は、指定された正規表現パターンと照合するルール属性の名前です。2 番目の引数 pattern は、属性値に対する正規表現です。attr
式は、x がセット input のメンバーであり、定義された属性 name を持つルールであり、属性値に正規表現 pattern の(アンカーなしの)一致が含まれているすべてのターゲット x を含むセットに評価されます。name がオプションの属性で、ルールで明示的に指定されていない場合、デフォルトの属性値が比較に使用されます。次に例を示します。
attr(linkshared, 0, deps(//foo))
は、linkshared 属性を持つことが許可されているすべての //foo
依存関係(cc_binary
ルールなど)を選択し、明示的に 0 に設定するか、まったく設定せずにデフォルト値を 0 にします(cc_binary
ルールなど)。
リスト型の属性(srcs
、data
など)は、[value<sub>1</sub>, ..., value<sub>n</sub>]
形式の文字列に変換されます。この形式の文字列は、[
かっこで始まり、]
かっこで終わり、複数の値を区切るために「,
」(カンマ、スペース)が使用されます。ラベルは、ラベルの絶対形式を使用して文字列に変換されます。たとえば、属性 deps=[":foo",
"//otherpkg:bar", "wiz"]
は文字列 [//thispkg:foo, //otherpkg:bar, //thispkg:wiz]
に変換されます。角かっこは常に存在するため、空のリストでは、一致目的で文字列値 []
が使用されます。次に例を示します。
attr("srcs", "\[\]", deps(//foo))
は、//foo
依存関係のうち、srcs
属性が空のルールをすべて選択します。
attr("data", ".{3,}", deps(//foo))
は、data
属性で少なくとも 1 つの値を指定する //foo
依存関係のすべてのルールを選択します(//
と :
により、すべてのラベルの長さは 3 文字以上になります)。
リスト型の属性に特定の value
を持つ //foo
依存関係のすべてのルールを選択するには、次を使用します。
attr("tags", "[\[ ]value[,\]]", deps(//foo))
これは、value
の前の文字が [
またはスペースになり、value
の後の文字がカンマまたは ]
になるためです。
ルールの公開設定のフィルタリング: 公開
expr ::= visible(expr, expr)
visible(predicate, input)
演算子は、ターゲットのセットにフィルタを適用し、必要な公開設定のないターゲットを破棄します。
最初の引数 predicate は、出力のすべてのターゲットが可視である必要があるターゲットのセットです。visible 式は、x がセット input のメンバーであるすべてのターゲット x を含むセットに評価されます。また、predicate 内のすべてのターゲット y に対して、x は y に表示されます。次に例を示します。
visible(//foo, //bar:*)
は、公開制限に違反することなく //foo
が依存できるパッケージ //bar
内のすべてのターゲットを選択します。
タイプ label: labels のルール属性の評価
expr ::= labels(word, expr)
labels(attr_name, inputs)
演算子は、セット inputs のいずれかのルールで、タイプが「ラベル」または「ラベルのリスト」の属性 attr_name で指定されたターゲットのセットを返します。
たとえば、labels(srcs, //foo)
は、//foo
ルールの srcs
属性に表示されるターゲットのセットを返します。inputs セットに srcs
属性を持つ複数のルールがある場合、それらの srcs
のユニオンが返されます。
test_suites: テストを展開してフィルタする
expr ::= tests(expr)
tests(x)
演算子は、x セット内のすべてのテストルールのセットを返します。test_suite
ルールを参照する個々のテストのセットに展開し、tag
と size
によるフィルタリングを適用します。
デフォルトでは、クエリ評価では、すべての test_suite
ルールでテスト以外のターゲットが無視されます。これは、--strict_test_suite
オプションを使用してエラーに変更できます。
たとえば、クエリ kind(test, foo:*)
は、foo
パッケージ内のすべての *_test
ルールと test_suite
ルールを一覧表示します。すべての結果は(定義により)foo
パッケージのメンバーです。一方、クエリ tests(foo:*)
は、bazel test
foo:*
によって実行される個々のテストをすべて返します。これには、test_suite
ルールを介して直接または間接的に参照される、他のパッケージに属するテストが含まれる場合があります。
パッケージ定義ファイル: buildfiles
expr ::= buildfiles(expr)
buildfiles(x)
演算子は、セット x 内の各ターゲットのパッケージを定義するファイルのセットを返します。つまり、パッケージごとに、その BUILD
ファイルと、load
を介して参照する .bzl ファイルを返します。また、これらの load
ファイルを含むパッケージの BUILD
ファイルも返されます。
この演算子は、通常、指定されたターゲットのビルドに必要なファイルまたはパッケージを特定するときに使用されます(多くの場合、下記の --output package
オプションと組み合わせて使用します)。次に例を示します。
bazel query 'buildfiles(deps(//foo))' --output package
//foo
が循環的に依存するすべてのパッケージのセットを返します。
パッケージ定義ファイル: rbuildfiles
expr ::= rbuildfiles(word, ...)
rbuildfiles
演算子は、パス フラグメントのカンマ区切りリストを受け取り、これらのパス フラグメントに伝播的に依存する BUILD
ファイルのセットを返します。たとえば、//foo
がパッケージの場合、rbuildfiles(foo/BUILD)
は //foo:BUILD
ターゲットを返します。foo/BUILD
ファイルに load('//bar:file.bzl'...
が含まれている場合、rbuildfiles(bar/file.bzl)
は //foo:BUILD
ターゲットと、//bar:file.bzl
を読み込む他の BUILD
ファイルのターゲットを返します。
--universe_scope
フラグで指定されたユニバースです。BUILD
ファイルと .bzl
ファイルに直接対応していないファイルは、結果に影響しません。たとえば、BUILD
ファイルで明示的に指定されている場合でも、ソースファイル(foo.cc
など)は無視されます。ただし、シンボリック リンクは考慮されるため、foo/BUILD
が bar/BUILD
へのシンボリック リンクである場合、rbuildfiles(bar/BUILD)
の結果には //foo:BUILD
が含まれます。
rbuildfiles
演算子は、ほぼ buildfiles
演算子の逆です。ただし、この倫理的な逆転は一方の方向でより強く適用されます。rbuildfiles
の出力は buildfiles
の入力とまったく同じです。前者にはパッケージ内の BUILD
ファイル ターゲットのみが含まれ、後者にはそのようなターゲットが含まれる場合があります。反対方向では、対応は弱くなります。buildfiles
演算子の出力は、すべてのパッケージとに対応するターゲットです。特定の入力に必要な bzl
ファイル。ただし、rbuildfiles
演算子の入力は、これらのターゲットではなく、これらのターゲットに対応するパス フラグメントです。
パッケージ定義ファイル: loadfiles
expr ::= loadfiles(expr)
loadfiles(x)
演算子は、x セット内の各ターゲットのパッケージを読み込むために必要な Starlark ファイルのセットを返します。つまり、パッケージごとに、その BUILD
ファイルから参照される .bzl ファイルを返します。
出力形式
bazel query
はグラフを生成します。bazel query
がこのグラフを表示するコンテンツ、形式、順序は、--output
コマンドライン オプションで指定します。
Sky Query で実行する場合、順序なし出力と互換性のある出力形式のみが許可されます。具体的には、graph
、minrank
、maxrank
の出力形式は禁止されています。
出力形式によっては、追加のオプションを使用できます。各出力オプションの名前には、適用される出力形式の接頭辞が付いています。そのため、--graph:factored
は --output=graph
が使用されている場合にのみ適用され、graph
以外の出力形式が使用されている場合は効果がありません。同様に、--xml:line_numbers
は --output=xml
が使用されている場合にのみ適用されます。
結果の並べ替えについて
クエリ式は常に「グラフ順序の保存則」に従いますが、結果の表示は、依存関係順序または順序なしのいずれかの方法で行うことができます。これは、結果セット内のターゲットやクエリの計算方法には影響しません。結果が stdout に出力される方法にのみ影響します。また、依存関係の順序で同等のノードは、アルファベット順に並べられる場合とそうでない場合があります。この動作は --order_output
フラグを使用して制御できます。(--[no]order_results
フラグは --order_output
フラグの機能のサブセットであり、非推奨です)。
このフラグのデフォルト値は auto
です。結果は辞書順で出力されます。ただし、somepath(a,b)
を使用すると、結果は deps
の順序で出力されます。
このフラグが no
で、--output
が build
、label
、label_kind
、location
、package
、proto
、xml
のいずれかの場合、出力は任意の順序で出力されます。通常、これが最も速い方法です。ただし、--output
が graph
、minrank
、maxrank
のいずれかの場合、このオプションはサポートされません。これらの形式では、Bazel は常に依存関係の順序またはランクで結果を出力します。
このフラグが deps
の場合、Bazel は結果をトポロジ順序で出力します。つまり、依存関係が先に、依存関係が後に出力されます。ただし、依存関係の順序で並べ替えられていないノード(一方から他方へのパスがないため)は、任意の順序で出力される場合があります。
このフラグが full
の場合、Bazel はノードを完全に確定的な(完全な)順序で出力します。まず、すべてのノードがアルファベット順に並べ替えられます。次に、リスト内の各ノードがポストオーダーの深さ優先探索の開始点として使用されます。この探索では、未訪問ノードへの出力エッジが後継ノードのアルファベット順に走査されます。最後に、ノードは訪問された順序の逆で出力されます。
この順序でノードを出力すると遅くなる可能性があるため、確定性が重要な場合にのみ使用してください。
BUILD に表示されるターゲットのソース形式を出力する
--output build
このオプションを使用すると、各ターゲットの表現は BUILD 言語で手書きされたものになります。すべての変数と関数呼び出し(glob、マクロなど)が展開されます。これは、Starlark マクロの効果を確認するのに役立ちます。また、各有効なルールは generator_name
値または generator_function
値を報告し、有効なルールを生成するために評価されたマクロの名前を指定します。
出力は BUILD
ファイルと同じ構文を使用しますが、有効な BUILD
ファイルが生成されるとは限りません。
各ターゲットのラベルを出力する
--output label
このオプションを使用すると、結果のグラフ内の各ターゲットの名前(またはラベル)のセットが、1 行に 1 つのラベルとして、トポロジ順で出力されます(--noorder_results
が指定されていない場合。結果の順序に関する注意事項をご覧ください)。(トポロジ順序とは、グラフノードがすべての後継ノードより前に表示される順序です)。もちろん、グラフの位相的な順序付けは多数あります(逆後順序は 1 つにすぎません)。どの順序付けが選択されるかは指定されていません。
somepath
クエリの出力を出力する場合、ノードの出力順序はパスの順序になります。
注意: 特殊なケースでは、同じラベルを持つ 2 つの異なるターゲットがある場合があります。たとえば、sh_binary
ルールとその唯一の(暗黙的な)srcs
ファイルの両方が foo.sh
と呼ばれている場合があります。クエリの結果にこれらのターゲットの両方が含まれている場合、出力(label
形式)には重複が含まれているように見えます。label_kind
形式(後述)を使用すると、2 つのターゲットの名前は同じですが、一方は種類が sh_binary rule
、もう一方は種類が source file
であることが明確になります。
各ターゲットのラベルと種類を出力する
--output label_kind
label
と同様に、この出力形式では、結果のグラフ内の各ターゲットのラベルがトポロジ順で出力されますが、ラベルの前にターゲットの種類が追加されます。
ターゲットをプロトコル バッファ形式で出力する
--output proto
クエリ出力を QueryResult
プロトコル バッファとして出力します。
長さ区切りのプロトコル バッファ形式でターゲットを出力する
--output streamed_proto
Target
プロトコル バッファの長さで区切られたストリームを出力します。これは、単一の QueryResult
に収まらないターゲットが多い場合にプロトコル バッファのサイズ制限を回避する場合や、(ii) Bazel がまだ出力している間に処理を開始する場合に便利です。
ターゲットをテキスト proto 形式で出力する
--output textproto
--output proto
に似ていますが、QueryResult
プロトコル バッファをテキスト形式で出力します。
ターゲットを ndjson 形式で出力する
--output streamed_jsonproto
--output streamed_proto
と同様ですが、Target
プロトコル バッファのストリームを ndjson 形式で出力します。
各ターゲットのラベルをランク順に出力します。
--output minrank --output maxrank
label
と同様に、minrank
と maxrank
の出力形式では、結果のグラフに各ターゲットのラベルが出力されますが、トポロジ順序ではなく、ランク順序でランク番号の前に表示されます。これらは、結果の並べ替え --[no]order_results
フラグの影響を受けません(結果の並べ替えに関する注記をご覧ください)。
この形式には 2 つのバリエーションがあります。minrank
は、ルートノードからそのノードまでの最短パスの長さで各ノードをランク付けします。「ルート」ノード(入ってくるエッジがないノード)はランク 0、その後継ノードはランク 1 です。エッジは常にターゲットからその前提条件(ターゲットが依存するターゲット)に向いています。
maxrank
は、ルートノードからそのノードまでの最長パスの長さで各ノードをランク付けします。繰り返しになりますが、「ルート」のランクは 0 で、他のすべてのノードのランクは、そのすべての前任者の最大ランクより 1 大きいランクです。
サイクル内のすべてのノードは同じランクと見なされます。(ほとんどのグラフは非循環ですが、BUILD
ファイルに誤った循環が含まれているため、循環が発生します)。
これらの出力形式は、グラフの深さを把握する場合に便利です。deps(x)
、rdeps(x)
、allpaths
クエリの結果に使用する場合、ランク番号は x
からそのランク内のノードまでの最短パス(minrank
の場合)または最長パス(maxrank
の場合)の長さに等しくなります。maxrank
を使用すると、ターゲットのビルドに必要なビルドステップの最長シーケンスを特定できます。
たとえば、左側のグラフは、--output minrank
と --output maxrank
がそれぞれ指定されている場合に、右側の出力を生成します。
minrank 0 //c:c 1 //b:b 1 //a:a 2 //b:b.cc 2 //a:a.cc |
maxrank 0 //c:c 1 //b:b 2 //a:a 2 //b:b.cc 3 //a:a.cc |
各ターゲットの場所を出力する
--output location
label_kind
と同様に、このオプションは結果内のターゲットごとに、ターゲットの種類とラベルを出力しますが、そのターゲットの場所を示す文字列(ファイル名と行番号)が先頭に付加されます。形式は grep
の出力に似ています。したがって、後者を解析できるツール(Emacs や vi など)でも、クエリ出力を使用して一連の一致をステップスルーできます。これにより、Bazel クエリツールを依存関係グラフ対応の「BUILD ファイルの grep」として使用できます。
ロケーション情報はターゲットの種類によって異なります(kind 演算子をご覧ください)。ルールの場合、BUILD
ファイル内のルールの宣言の場所が印刷されます。ソースファイルの場合、実際のファイルの 1 行目の場所が印刷されます。生成されたファイルの場合は、そのファイルを生成するルールの場所が出力されます。(クエリツールには、生成されたファイルの実際の場所を見つけるのに十分な情報がないため、ビルドがまだ実行されていない場合は存在しない可能性があります)。
パッケージのセットを印刷する
--output package
このオプションを使用すると、結果セット内のターゲットが属するすべてのパッケージの名前が出力されます。名前は辞書順で出力され、重複は除外されます。正式には、これはラベル(パッケージ、ターゲット)のセットからパッケージへの射影です。
外部リポジトリのパッケージは @repo//foo/bar
としてフォーマットされ、メイン リポジトリのパッケージは foo/bar
としてフォーマットされます。
この出力オプションは、deps(...)
クエリと組み合わせて、特定のターゲット セットをビルドするためにチェックアウトする必要があるパッケージのセットを検索するために使用できます。
結果のグラフを表示する
--output graph
このオプションを使用すると、クエリ結果が一般的な AT&T GraphViz 形式の有向グラフとして出力されます。通常、結果は .png
や .svg
などのファイルに保存されます。(dot
プログラムがワークステーションにインストールされていない場合は、sudo apt-get install graphviz
コマンドを使用してインストールできます)。呼び出しの例については、以下の例のセクションをご覧ください。
この出力形式は、allpaths
、deps
、または rdeps
クエリで特に便利です。これらのクエリの結果には、--output label
など、リニア形式でレンダリングすると簡単に可視化できないパスのセットが含まれます。
デフォルトでは、グラフは分解された形式でレンダリングされます。つまり、トポロジ的に同等のノードは、複数のラベルを持つ単一のノードに統合されます。一般的な結果グラフには非常に反復的なパターンが含まれているため、これによりグラフがよりコンパクトで読みやすくなります。たとえば、java_library
ルールは、同じ genrule
によって生成された数百の Java ソースファイルに依存している場合があります。分割グラフでは、これらのファイルはすべて単一のノードで表されます。この動作は、--nograph:factored
オプションで無効にできます。
--graph:node_limit n
このオプションは、出力のグラフノードのラベル文字列の最大長を指定します。長いラベルは切り捨てられます。-1 にすると切り捨てが無効になります。グラフは通常、分解された形式で印刷されるため、ノードラベルが非常に長くなることがあります。GraphViz は、このオプションのデフォルト値である 1, 024 文字を超えるラベルを処理できません。--output=graph
が使用されていない限り、このオプションは効果がありません。
--[no]graph:factored
デフォルトでは、上記で説明したように、グラフは分解された形式で表示されます。--nograph:factored
を指定すると、グラフは因数分解されずに出力されます。そのため、GraphViz を使用した可視化は実用的ではありませんが、シンプルな形式により、他のツール(grep など)による処理が容易になる場合があります。--output=graph
が使用されていない限り、このオプションは効果がありません。
XML
--output xml
このオプションを使用すると、生成されたターゲットが XML 形式で出力されます。出力は次のような XML ヘッダーで始まります。
<?xml version="1.0" encoding="UTF-8"?>
<query version="2">
次に、結果グラフ内のターゲットごとに XML 要素をトポロジ順に続けます(順序なしの結果がリクエストされていない場合)。最後に終了タグ
</query>
file
タイプのターゲットに対して単純なエントリが出力されます。
<source-file name='//foo:foo_main.cc' .../>
<generated-file name='//foo:libfoo.so' .../>
ただし、ルールの場合、XML は構造化されており、ルールのすべての属性の定義が含まれています。これには、ルールの BUILD
ファイルで値が明示的に指定されていない属性も含まれます。
また、結果には rule-input
要素と rule-output
要素が含まれるため、srcs
属性の要素が前方依存関係(前提条件)であり、outs
属性の内容が後方依存関係(コンシューマ)であることを知らなくても、依存関係グラフのトポロジを再構築できます。
--noimplicit_deps
が指定されている場合、暗黙的な依存関係の rule-input
要素は抑制されます。
<rule class='cc_binary rule' name='//foo:foo' ...>
<list name='srcs'>
<label value='//foo:foo_main.cc'/>
<label value='//foo:bar.cc'/>
...
</list>
<list name='deps'>
<label value='//common:common'/>
<label value='//collections:collections'/>
...
</list>
<list name='data'>
...
</list>
<int name='linkstatic' value='0'/>
<int name='linkshared' value='0'/>
<list name='licenses'/>
<list name='distribs'>
<distribution value="INTERNAL" />
</list>
<rule-input name="//common:common" />
<rule-input name="//collections:collections" />
<rule-input name="//foo:foo_main.cc" />
<rule-input name="//foo:bar.cc" />
...
</rule>
ターゲットのすべての XML 要素には、name
属性(値はターゲットのラベル)と location
属性(値は --output location
によって出力されるターゲットの位置)が含まれています。
--[no]xml:line_numbers
デフォルトでは、XML 出力に表示される場所には行番号が含まれます。--noxml:line_numbers
を指定すると、行番号は出力されません。
--[no]xml:default_values
デフォルトでは、XML 出力には、その種類の属性のデフォルト値である値を持つルール属性は含まれません(たとえば、BUILD
ファイルで指定されていない場合や、デフォルト値が明示的に指定されている場合など)。このオプションを使用すると、このような属性値が XML 出力に含まれます。
正規表現
クエリ言語の正規表現は Java 正規表現ライブラリを使用するため、java.util.regex.Pattern
の完全な構文を使用できます。
外部リポジトリを使用したクエリ
ビルドが外部リポジトリのルールに依存している場合、クエリ結果にはこれらの依存関係が含まれます。たとえば、//foo:bar
が @other-repo//baz:lib
に依存している場合、bazel query 'deps(//foo:bar)'
には @other-repo//baz:lib
が依存関係としてリストされます。