このページは、bazel query
を使用してビルド依存関係を分析するときに使用する Bazel クエリ言語のリファレンス マニュアルです。また、bazel query
がサポートする出力形式についても説明します。
実際のユースケースについては、Bazel クエリの使用方法をご覧ください。
その他のクエリ リファレンス
読み込み後のフェーズのターゲット グラフで実行される query
に加えて、Bazel にはアクション グラフのクエリと構成可能なクエリが含まれています。
アクション グラフのクエリ
アクション グラフ クエリ(aquery
)は、分析後の構成済みターゲット グラフで動作し、アクション、アーティファクト、およびそれらの関係に関する情報を公開します。aquery
は、構成されたターゲット グラフから生成されたアクション/アーティファクトのプロパティを確認したい場合に便利です。たとえば、実際のコマンド、およびその入力、出力、ニーモニック。
詳細については、aquery のリファレンスをご覧ください。
構成可能なクエリ
従来の Bazel クエリは読み込み後のフェーズのターゲット グラフに対して実行されるため、構成の概念や関連するコンセプトがありません。特に、SELECT ステートメントが正しく解決されず、選択可能なすべての解像度が返されます。ただし、構成可能なクエリ環境 cquery
は構成を適切に処理しますが、この元のクエリのすべての機能を提供するわけではありません。
詳細については、cquery リファレンスをご覧ください。
例
bazel query
の活用方法一般的な例を次に示します。
//foo
ツリーが //bar/baz
に依存するのはなぜですか?経路を表示します。
somepath(foo/..., //bar/baz:all)
foo_bin
ターゲットが依存していないすべての foo
テストが依存する C++ ライブラリは何ですか?
kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo:foo_bin))
トークン: 字句構文
クエリ言語の式は、次のトークンで構成されています。
キーワード(
let
など)キーワードは言語の予約済み語です。以下で説明します。キーワードの完全なセットは次のとおりです。単語(「
foo/...
」、「.*test rule
」、「//bar/baz:all
」など)。文字シーケンスが「引用符で囲まれている」(単一引用符で始まって終了、二重引用符で始まっている場合)ことを意味しています。文字シーケンスが引用符で囲まれていなくても、単語として解析される場合があります。引用符で囲まれていない単語は、アルファベット A ~ Z、a ~ z、数字 0 ~ 9、特殊文字*/@.-_:$~[]
(アスタリスク、スラッシュ、アット、ピリオド、ハイフン、アンダースコア、コロン、ドル記号、チルダ、左角かっこ、右角かっこ)から描画された文字の並びです。引用符で囲まれていない単語は、ハイフン-
またはアスタリスク*
で始めることはできません。ただし、相対名 [ターゲット名][//concepts/labels#target-names] は文字で始めることができます。引用符で囲まれていない単語には、
+
や等号(=
)は使用できません。クエリ式を生成するコードを作成する場合は、ターゲット名を引用符で囲む必要があります。ユーザー指定の値から 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)と評価されます。これが唯一のデータ型です。
セットとグラフは同じデータ型を参照しますが、データのさまざまな側面を強調します。次に例を示します。
- 設定: ターゲットの部分的な順序は重要ではありません。
- グラフ: ターゲットの部分的な順序が重要です。
依存関係グラフのサイクル
ビルド依存関係グラフは非巡回である必要があります。
クエリ言語で使用されるアルゴリズムは、非巡回グラフでの使用を想定していますが、サイクルに対して堅牢です。サイクルの処理の詳細は指定されず、信頼できません。
暗黙的な依存関係
BUILD
ファイルで明示的に定義されているビルド依存関係に加えて、Bazel はルールに暗黙的の依存関係を追加します。たとえば、すべての Java ルールは暗黙的に JavaBuilder に依存します。暗黙的な依存関係は、$
で始まる属性を使用して確立され、BUILD
ファイルでオーバーライドできません。
デフォルトでは、bazel query
はクエリ結果を計算する際に暗黙的な依存関係を考慮します。この動作は --[no]implicit_deps
オプションで変更できます。なお、クエリでは構成が考慮されないため、潜在的なツールチェーンは考慮されません。
サウンド
Bazel クエリ言語式は、ビルド依存関係グラフ(すべての BUILD
ファイル内のすべてのルール宣言で暗黙的に定義されるグラフ)に基づいて動作します。このグラフはある程度抽象的なものであり、ビルドのすべてのステップを実行する方法の詳細な説明ではないということを理解することが重要です。ビルドを実行するには、構成も必要です。詳細については、ユーザーガイドの構成セクションをご覧ください。
Bazel クエリ言語で式を評価した結果は、すべての構成に対して真になります。つまり、控えめに過大評価される可能性があり、正確ではありません。ビルド時に必要なすべてのソースファイルセットをクエリツールで計算すると、必要以上にレポートされる可能性があります。これは、たとえばビルド時にこの機能を使用するつもりがなくても、クエリツールにはメッセージの翻訳をサポートするために必要なすべてのファイルが含まれるためです。
グラフの順序の保持
オペレーションでは、サブ式から継承した順序の制約が保持されます。これは「部分的な保存の法則」と考えることができます。たとえば、特定のターゲットの依存関係の推移的終了を判断するクエリを発行すると、結果セットは依存関係グラフに従って順序付けされます。file
という種類のターゲットのみを含めるようにフィルタすると、これらのペアのいずれも元のグラフで直接接続されていなくても、生成されるサブセットのターゲットごとに、同じ推移的な部分的な順序関係が保持されます。(ビルド依存関係グラフにファイル ファイルのエッジはありません)。
ただし、すべての演算子は順序を保持しますが、集合演算などの一部の演算では、それ自体の並べ替え制約が導入されません。次の式を考えてみましょう。
deps(x) union y
最終結果セットの順序は、そのサブ式のすべての順序付けの制約が維持されます。つまり、x
のすべての推移的な依存関係が互いに正しい順序で並べられます。ただし、このクエリでは、y
のターゲットの順序や、y
のターゲットに対する deps(x)
のターゲットの順序は保証されません(ただし、y
のターゲットが deps(x)
に存在する場合を除く)。
順序の制約を導入している演算子には、allpaths
、deps
、rdeps
、somepath
や、ターゲット パターンのワイルドカード package:*
、dir/...
などがあります。
Sky クエリ
Sky Query は、指定されたユニバース スコープで動作するクエリのモードです。
SkyQuery でのみ使用できる特別な関数
Sky クエリモードには、追加のクエリ関数 allrdeps
と rbuildfiles
があります。これらの関数はユニバース スコープ全体にわたって動作します(そのため、通常のクエリでは意味がありません)。
ユニバース スコープの指定
Sky クエリモードを有効にするには、--universe_scope
または --infer_universe_scope
の 2 つのフラグと --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 クエリには、デフォルトのクエリと比べて次のような利点と欠点があります。主なデメリットは、出力をグラフの順序に従って並べ替えることができないため、特定の出力形式が禁止されていることです。これには、デフォルト クエリでは使用できない 2 つの演算子(allrdeps
と rbuildfiles
)が用意されているという利点があります。また、Sky Query は、デフォルトの実装で新規グラフを作成するのではなく、Skyframe グラフをイントロスペクトして処理を行います。そのため、より高速でメモリの使用量が少なくなる状況もあります。
式: 文法の構文とセマンティクス
Bazel クエリ言語の文法は、EBNF 表記で表します。
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/...
と同じです。
変数参照 name
が、囲む let name = ...
式以外の出現はエラーです。つまり、トップレベルのクエリ式に自由変数を含めることはできません。
上記の文法の制作では、name
は word に似ていますが、C プログラミング言語の法的な識別子であるという追加の制約があります。変数への参照の先頭に「$」を付ける必要があります。
各 let
式は 1 つの変数のみを定義しますが、それらをネストできます。
ターゲット パターンと変数参照は、どちらも単一のトークン(単語)で構成されているため、構文が曖昧になります。ただし、有効な変数名である単語のサブセットが、有効なターゲット パターンである単語のサブセットと切り離されているため、セマンティックの曖昧さはありません。
技術的には、let
式はクエリ言語の表現性を向上させません。その言語で表現されるクエリも、それなしで表現できます。ただし、多くのクエリの簡潔性が向上するため、より効率的なクエリ評価につながる可能性があります。
丸かっこ式
expr ::= (expr)
かっこはサブ式を関連付けて評価の順序を強制します。かっこ式は、引数の値を評価します。
代数集合演算: 積、和、差の違い
expr ::= expr intersect expr
| expr ^ expr
| expr union expr
| expr + expr
| expr except expr
| expr - expr
これら 3 つの演算子は、引数に対して通常の set 演算を計算します。各演算子には、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 ...)
演算子は、ゼロ個以上のターゲット パターンをスペースで区切って結合を計算します(カンマなし)。
Bourne シェルの $(...)
機能と組み合わせて、set()
は 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)
の省略形ですが、前の awk
コマンドなど、cat
以外のシェルコマンドも使用できます。
関数
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
依存関係の一時的な終了: 依存関係
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
は ID 関数を計算します。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 つのターゲット セットの間のパスを計算します。どちらのクエリも 2 つの引数を受け入れます。1 つはセットの S、もう 1 つはセットの E です。somepath
は、S のターゲットから E のターゲットへの任意のパスにあるノードのグラフを返します。allpaths
は、S のターゲットから E のターゲットへのすべてのパスにあるノードのグラフを返します。
結果のグラフは、依存関係の関係で並べ替えられます。詳しくは、グラフの順序のセクションをご覧ください。
somepath(S1 + S2, E) 。考えられる結果の一つです。 |
somepath(S1 + S2, E) という結果も発生する可能性があります。 |
allpaths(S1 + S2, E) |
ターゲット種類のフィルタリング: 種類
expr ::= kind(word, expr)
kind(pattern, input)
演算子は、一連のターゲットにフィルタを適用し、想定外の種類のターゲットを破棄します。pattern パラメータは、照合するターゲットの種類を指定します。
以下の表に、BUILD
ファイル(パッケージ p
用)で定義されている 4 つのターゲットの種類を示します。
コード | Target | 種類 |
---|---|---|
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)
演算子の一般的な用途は、特定のファイルを名前または拡張子でフィルタリングすることです。次に例を示します。
filter("\.cc$", deps(//foo))
//foo
の作成に使用されたすべての .cc
ファイルのリストが表示されます。
ルール属性のフィルタリング: 属性
expr ::= attr(word, word, expr)
attr(name, pattern, input)
演算子は一連のターゲットにフィルタを適用し、ルールでないターゲット、属性 name が定義されていないルール ターゲット、指定された正規表現 pattern と属性値が一致しないルール ターゲットを破棄して、入力のサブセットを評価します。
最初の引数 name は、指定された正規表現パターンに対して照合する必要があるルール属性の名前です。2 番目の引数 pattern は、属性値の正規表現です。attr
式は、すべてのターゲット x を含むセットを評価します。たとえば、x はセット input のメンバーであり、定義済みの属性 name を含むルールであり、属性値に正規表現 pattern に対する(アンカー)一致が含まれています。name がオプションの属性であり、ルールが明示的に指定しない場合は、デフォルトの属性値が比較に使用されます。次に例を示します。
attr(linkshared, 0, deps(//foo))
linkshared 属性(cc_binary
ルールなど)を持つことができる //foo
依存関係をすべて選択し、明示的に 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))
srcs
属性が空の //foo
依存関係の中ですべてのルールを選択します。
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 のメンバーであり、predicate x のすべてのターゲット y が y が見えるように、すべてのターゲット x を含むセットに評価されます。次に例を示します。
visible(//foo, //bar:*)
パッケージ //bar
の中で、公開設定の制限に違反することなく //foo
が依存できるすべてのターゲットを選択します。
ラベルタイプ「labels」のルール属性の評価
expr ::= labels(word, expr)
labels(attr_name, inputs)
演算子は、セット inputs のルール内で、型が attr_name の「label」または「label のリスト」で指定されたターゲットのセットを返します。
たとえば、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
ファイルに直接対応していないファイルは結果に影響しません。たとえば、ソースファイル(foo.cc
など)は、BUILD
ファイルで明示的に指定されていても無視されます。ただし、シンボリック リンクは考慮されるため、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 はノードを完全に確定的な(合計)順序で出力します。まず、すべてのノードがアルファベット順に並べ替えられます。次に、リスト内の各ノードが、訪問後のノードへの送信エッジを後継ノード順で走査するポストオーダー深度検索の開始として使用されます。最後に、ノードはアクセスされた順序とは逆の順序で出力されます。
ノードの表示はこの順序で遅くなる可能性があるため、決定論が重要である場合にのみ使用してください。
ビルド時に表示されるターゲットのソース形式を出力します。
--output 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
と同様に、この出力形式では、結果のグラフの各ターゲットのラベルがトポロジ形式で出力されますが、ラベルの前にターゲットの kind が付加されます。
各ターゲットのラベルをランク順に出力する
--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 クエリツールを依存関係グラフ対応の「ビルドファイル用 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 ソースファイルに依存している場合があります。因数分解グラフでは、これらのファイルはすべて 1 つのノードで表されます。この動作は、--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
属性と、値が --output location
によって出力されるターゲットの場所である location
属性が含まれます。
--[no]xml:line_numbers
デフォルトでは、XML 出力に表示されるロケーションには行番号が含まれています。--noxml:line_numbers
を指定した場合、行番号は出力されません。
--[no]xml:default_values
デフォルトでは、その種類の属性のデフォルト値であるルール属性は XML 出力に含まれません(たとえば、BUILD
ファイルで指定されていない場合や、デフォルト値が明示的に指定された場合)。このオプションを使用すると、このような属性値が XML 出力に含まれます。
正規表現
クエリ言語の正規表現では Java 正規表現ライブラリを使用するため、java.util.regex.Pattern
で完全な構文を使用できます。
外部リポジトリに対するクエリ
ビルドが外部リポジトリ(WORKSPACE ファイルで定義されている)のルールに依存している場合、クエリ結果にはこれらの依存関係が含まれます。たとえば、//foo:bar
が //external:some-lib
に依存し、//external:some-lib
が @other-repo//baz:lib
にバインドされている場合、bazel query 'deps(//foo:bar)'
は @other-repo//baz:lib
と //external:some-lib
の両方を依存関係としてリストします。
外部リポジトリ自体はビルドの依存関係ではありません。つまり、上記の例では //external:other-repo
は依存関係ではありません。ただし、次のように //external
パッケージのメンバーとしてクエリできます。
# Querying over all members of //external returns the repository.
bazel query 'kind(http_archive, //external:*)'
//external:other-repo
# ...but the repository is not a dependency.
bazel query 'kind(http_archive, deps(//foo:bar))'
INFO: Empty results