このページは、bazel query
を使用してビルドの依存関係を分析する際に使用する Bazel Query Language のリファレンス マニュアルです。また、bazel query
がサポートする出力形式についても説明します。
実際のユースケースについては、Bazel クエリの方法をご覧ください。
その他のクエリ リファレンス
読み込み後フェーズのターゲット グラフで実行される query
に加えて、Bazel にはアクション グラフ クエリと構成可能なクエリが含まれています。
アクション グラフ クエリ
アクション グラフ クエリ(aquery
)は、分析後の構成済みターゲット グラフで動作し、アクション、アーティファクト、それらの関係に関する情報を表示します。aquery
は、構成済みのターゲットグラフから生成されるアクション/アーティファクトのプロパティを確認したい場合に便利です。たとえば、実際に実行されるコマンドとその入力、出力、ニーモニックなどです。
詳細については、aquery リファレンスをご覧ください。
構成可能なクエリ
従来の Bazel クエリは、読み込み後のフェーズのターゲット グラフで実行されるため、構成や関連するコンセプトはありません。特に、select ステートメントが正しく解決されないため、選択時に使用可能なすべての解像度が返されます。ただし、構成可能なクエリ環境 cquery
では、構成は適切に処理されますが、元のクエリのすべての機能が提供されるわけではありません。
詳細については、cquery リファレンスをご覧ください。
例
bazel query
の活用方法一般的な例を以下に示します。
//foo
ツリーが //bar/baz
に依存するのはなぜですか?経路を表示する:
somepath(foo/..., //bar/baz:all)
すべての foo
テストで、foo_bin
ターゲットに依存しない C++ ライブラリはどれですか。
kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo:foo_bin))
トークン: 語彙構文
クエリ言語の式は、次のトークンで構成されます。
キーワード(例:
let
)。キーワードは言語の予約語です。各語について以下で説明します。すべてのキーワードは次のとおりです。単語: 「
foo/...
」、「.*test rule
」、「//bar/baz:all
」などの単語。文字シーケンスが「引用符」で囲まれている場合(先頭と末尾は単一引用符「'」、先頭と末尾が二重引用符「"」)は、単語です。引用符で囲まれていない文字列も、単語として解析されることがあります。引用符で囲まれていない単語は、アルファベット A ~ 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)として評価されます。これは唯一のデータ型です。
Set と graph は同じデータ型を参照しますが、次のように異なる点が重視されます。
- Set: ターゲットの順序の部分的な順序は関係ありません。
- グラフ: ターゲットの順序の部分的な順序が重要です。
依存関係グラフのサイクル
ビルド依存関係グラフは非巡回にする必要があります。
クエリ言語で使用されるアルゴリズムは、非巡回グラフでの使用を意図していますが、周期に対して堅牢です。サイクルの扱い方の詳細は指定されていないため、信頼しないでください。
暗黙的な依存関係
Bazel は、BUILD
ファイルで明示的に定義されているビルド依存関係に加えて、暗黙的な依存関係をルールに追加します。たとえば、すべての Java ルールは JavaBuilder に暗黙的に依存します。暗黙的な依存関係は、$
で始まる属性を使用して設定されます。これらの依存関係を BUILD
ファイルでオーバーライドすることはできません。
デフォルトの bazel query
では、クエリ結果を計算するときに暗黙的な依存関係が考慮されます。この動作は --[no]implicit_deps
オプションで変更できます。クエリでは構成が考慮されないため、ツールチェーンの候補は考慮されません。
健全性
Bazel クエリ言語式は、ビルド依存関係グラフ(すべての BUILD
ファイルのすべてのルール宣言によって暗黙的に定義されるグラフ)で動作します。このグラフは抽象的で、ビルドのすべてのステップの実行方法を完全に説明しているわけではない点を理解することが重要です。ビルドを実行するには、設定も必要です。詳しくは、ユーザーガイドの設定セクションをご覧ください。
Bazel クエリ言語で式を評価した結果は、すべての構成で真になります。クエリツールを使用してビルド時に必要なすべてのソースファイルのセットを計算する場合、実際は必要以上に多いと報告される場合があります。たとえば、ビルドでこの機能を使用するつもりがなくても、メッセージ翻訳のサポートに必要なすべてのファイルがクエリ ツールによって含まれるためです。
グラフの順序の保持について
演算では、サブ式から継承された並べ替え制約が保持されます。これは「部分順序保存の法則」と考えることができます。例を考えてみましょう。特定のターゲットの依存関係の推移的クロージングを求めるクエリを発行すると、結果セットは依存関係グラフに従って並べ替えられます。file
の種類のターゲットのみを含むようにセットをフィルタした場合、元のグラフでは実際にはこれらのペアが直接接続されていない場合でも、結果のサブセット内のすべてのターゲットのペア間で同じ推移的な部分順序関係が保持されます。(ビルド依存関係グラフにはファイル ファイルのエッジはありません)。
ただし、すべての演算子は順序を保持しますが、set オペレーションなどの一部のオペレーションでは、それ自体の順序付けの制約は生じません。次の式を考えてみましょう。
deps(x) union y
最終的な結果セットの順序は、そのサブ式の順序付けに関する制約をすべて維持することが保証されています。つまり、x
の推移的な依存関係のすべてが、相互に関連して正しく順序付けられます。ただし、このクエリでは、y
内のターゲットの順序や、y
内のターゲットに対する deps(x)
内のターゲットの順序については保証されません(ただし、y
内のターゲットが deps(x)
内にある場合を除く)。
順序の制約を導入する演算子には、allpaths
、deps
、rdeps
、somepath
、ターゲット パターンのワイルドカード package:*
、dir/...
などがあります。
Sky クエリ
Sky Query は、指定したユニバース スコープで動作するクエリモードです。
SkyQuery でのみ使用できる特殊な関数
Sky Query モードには、追加のクエリ関数 allrdeps
と rbuildfiles
があります。これらの関数は、ユニバース スコープ全体で動作します(そのため、通常のクエリでは意味がありません)。
ユニバース スコープの指定
Sky Query モードを有効にするには、--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 Query には、デフォルトのクエリと比較して、いくつかの長所と短所があります。主なデメリットは、グラフの順序に従って出力を並べ替えることができないため、特定の出力形式が使用できないことです。メリットは、デフォルト クエリでは使用できない 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
構文的には、ターゲット パターンは単なる 1 つの単語です。これは(順序付けされていない)ターゲットのセットとして解釈されます。最も単純なターゲット パターンは、単一のターゲット(ファイルまたはルール)を識別するラベルです。たとえば、ターゲット パターン //foo:bar
は、ターゲットである bar
ルールという 1 つの要素を含むセットに評価されます。
ターゲット パターンは、パッケージとターゲットにワイルドカードを含むようにラベルを一般化します。たとえば、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
は単語に似ていますが、C プログラミング言語の法的な識別子であるという追加の制約があります。変数への参照は、先頭に「$」を付ける必要があります。
各 let
式が定義する変数は 1 つだけですが、ネストできます。
ターゲット パターンと変数参照はどちらも 1 つの単語 1 つのトークンのみで構成され、構文があいまいになります。ただし、正規の変数名である単語のサブセットは、正規のターゲット パターンである単語のサブセットと重複しないため、意味のあいまいさはありません。
技術的に言うと、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)
外部ソースからターゲットを読み取る: set
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)
の省略形ですが、前述の 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
はアイデンティティ関数を計算します。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 のターゲットへのすべてのパスにあるノードのグラフを返します。
結果のグラフは、依存関係に応じて並べ替えられます。詳しくは、グラフの順序のセクションをご覧ください。
somepath(S1 + S2, E) 、表示される結果は 1 件です。 |
somepath(S1 + S2, E) 、もう 1 つの可能な結果です。 |
allpaths(S1 + S2, E) |
ターゲットの種類のフィルタリング: kind
expr ::= kind(word, expr)
kind(pattern, input)
演算子は、一連のターゲットにフィルタを適用し、想定された種類でないターゲットを破棄します。pattern パラメータは、照合するターゲットの種類を指定します。
たとえば、以下に示す BUILD
ファイル(パッケージ p
の場合)で定義されている 4 つのターゲットの種類は、次の表のとおりです。
コード | Target | kind |
---|---|---|
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
ファイルのリストを提供します。
ルール属性のフィルタリング: 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))
リンク共有属性(cc_binary
ルールなど)を持つことが許可されるすべての //foo
依存関係を選択し、明示的に 0 に設定するか、まったく設定せずに(cc_binary
ルールなど)、デフォルト値は 0 にします。
リスト型の属性(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 文字以上になります)。
list-type 属性に特定の 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:*)
は、公開設定の制限に違反することなく、//foo
が依存できるパッケージ //bar
内のすべてのターゲットを選択します。
type label のルール属性の評価
expr ::= labels(word, expr)
labels(attr_name, inputs)
演算子は、セット inputs のなんらかのルールで属性 attr_name に指定されたターゲットのセットを「ラベル」または「ラベルのリスト」で返します。
たとえば、labels(srcs, //foo)
は、//foo
ルールの srcs
属性に表示されるターゲットのセットを返します。inputs セット内に srcs
属性を持つルールが複数ある場合は、それらの srcs
の和集合が返されます。
[test_suites: tests] を展開してフィルタする
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
ルールを介して直接的または間接的に参照される他のパッケージに属するテストが含まれる場合があります。
パッケージ定義ファイル: buildfile
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
はグラフを生成します。--output
コマンドライン オプションで、bazel query
がこのグラフを表示する内容、形式、順序を指定します。
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
が指定されている場合を除く。結果の順序に関する注意事項をご覧ください)。(トポロジ上の順序とは、グラフノードがそのすべての後続ノードより前に表示される順序のことです)。もちろん、グラフのトポロジの順序は数多くあります(「逆ポスト順序(reverse postorder)」は 1 つだけです)。どの順序が選択されるかは指定されません。
somepath
クエリの出力が出力される場合、ノードが出力される順序はパスの順序です。
注意: 場合によっては、同じラベルを持つ 2 つの異なるターゲットが存在することがあります。たとえば、sh_binary
ルールとその唯一の(暗黙的な)srcs
ファイルの両方が foo.sh
と呼ばれることがあります。クエリの結果にこれらのターゲットの両方が含まれている場合、label
形式の出力には重複が含まれているように見えます。label_kind
(下記参照)形式を使用すると、2 つのターゲットが同じ名前を持ちますが、一方の種類が sh_binary rule
で、他の種類が source file
である、という違いが明確になります。
各ターゲットのラベルと種類を出力します。
--output label_kind
この出力形式では、label
と同様に、結果のグラフの各ターゲットのラベルがトポロジ順に出力されますが、さらにターゲットの kind がラベルの前に出力されます。
プロトコル バッファ形式でターゲットを出力する
--output proto
クエリ出力を QueryResult
プロトコル バッファとして出力します。
長さ区切りのプロトコル バッファ形式でターゲットを出力します。
--output streamed_proto
Target
プロトコル バッファの長さ区切りストリームを出力します。これは、(i)ターゲットが多すぎて 1 つの 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
などの線形形式でレンダリングすると簡単に視覚化できないパスのセットが結果に含まれます。
デフォルトでは、グラフは因数分解形式でレンダリングされます。つまり、トポロジが同等のノードは、複数のラベルを持つ 1 つのノードにマージされます。通常の結果グラフには繰り返しの多いパターンが含まれるため、これによりグラフがコンパクトで読みやすくなります。たとえば、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
属性(値がターゲットのラベル)と location
属性(値が --output 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