Bazel クエリ リファレンス

このページは、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)として評価されます。これが唯一のデータ型です。

集合とグラフは同じデータ型を参照しますが、異なる側面を強調します。次に例を示します。

  • Set(設定): ターゲットの部分的な順序は重要ではありません。
  • グラフ: ターゲットの部分的な順序が重要です。

依存関係グラフのサイクル

ビルドの依存関係グラフは非巡回である必要があります。

クエリ言語で使用されるアルゴリズムは非循環グラフでの使用を目的としていますが、循環に対しても堅牢です。サイクルの処理方法の詳細は指定されていないため、信頼しないでください。

暗黙的な依存関係

Bazel は、BUILD ファイルで明示的に定義されたビルド依存関係に加えて、ルールに暗黙的な依存関係を追加します。たとえば、すべての Java ルールは JavaBuilder に暗黙的に依存しています。暗黙的な依存関係は、$ で始まる属性を使用して確立され、BUILD ファイルでオーバーライドすることはできません。

デフォルトでは、bazel query はクエリ結果の計算時に暗黙的な依存関係を考慮します。この動作は、--[no]implicit_deps オプションで変更できます。クエリでは構成が考慮されないため、潜在的なツールチェーンは考慮されません。

健全性

Bazel クエリ言語式は、ビルド依存関係グラフに対して動作します。これは、すべての BUILD ファイル内のすべてのルール宣言によって暗黙的に定義されるグラフです。このグラフはやや抽象的なものであり、ビルドのすべてのステップを実行する方法を完全に説明するものではないことを理解することが重要です。ビルドを実行するには、構成も必要です。詳細については、ユーザーガイドのconfigurationsのセクションをご覧ください。

Bazel クエリ言語で式を評価した結果は、すべての構成で true になります。つまり、保守的な過剰近似であり、正確ではない可能性があります。ビルド中に必要なすべてのソースファイルのセットをクエリ ツールを使用して計算すると、実際に必要なものよりも多く報告されることがあります。たとえば、メッセージがビルドでその機能を使用するつもりがなくても、メッセージ変換をサポートするために必要なすべてのファイルがクエリツールに含まれるためです。

グラフの順序の保持

オペレーションでは、サブ式から継承された順序付け制約が保持されます。これは「部分順序の保存則」と考えることができます。例を考えてみましょう。特定のターゲットの依存関係の推移的クロージングを判断するクエリを発行すると、結果セットは依存関係グラフに従って順序付けされます。このセットをフィルタして file タイプのターゲットのみを含めると、結果のサブセット内のすべてのターゲットペアの間に同じ推移的部分順序関係が保持されます。これらのペアのいずれも、元のグラフで実際には直接接続されていません。(ビルド依存関係グラフにはファイル ファイルのエッジはありません)。

ただし、すべての演算子は順序を保持しますが、集合演算子など、一部のオペレーションは独自の順序制約を導入しません。次の式について考えてみましょう。

deps(x) union y

最終的な結果セットの順序は、サブ式のすべての順序制約を保持することが保証されます。つまり、x のすべての推移的依存関係が互いに正しく順序付けられます。ただし、このクエリでは、y 内のターゲットの順序や、deps(x) 内のターゲットの y 内のターゲットに対する順序について保証されません(deps(x) にも存在する y 内のターゲットを除く)。

順序の制約を導入する演算子には、allpathsdepsrdepssomepath、ターゲット パターンのワイルドカード package:*dir/... などがあります。

Sky のクエリ

スカイクエリは、指定されたユニバース スコープで動作するクエリのモードです。

SkyQuery でのみ使用できる特別な関数

Sky Query モードには、追加のクエリ関数 allrdepsrbuildfiles があります。これらの関数はユニバース スコープ全体で動作します(そのため、通常のクエリには適していません)。

ユニバース スコープの指定

Sky Query モードは、--universe_scope または --infer_universe_scope--order_output=no の 2 つのフラグを渡すことで有効になります。--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 を選択した場合にクエリ式を手動で解析する必要がある場合は便利です。

そのため、allrdepsrbuildfiles などのユニバース スコープ演算子を使用するクエリ式では、その動作が望ましい場合にのみ --infer_universe_scope を使用してください。

Sky Query には、デフォルト クエリと比較していくつかのメリットとデメリットがあります。主なデメリットは、出力をグラフの順序で並べ替えることができず、特定の出力形式が禁止されていることです。デフォルト クエリでは使用できない 2 つの演算子(allrdepsrbuildfiles)が用意されている点が利点です。また、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 $vallpaths(foo/...,//common) intersect foo/... と同等です。

含まれている let name = ... 式以外で変数参照 name が発生すると、エラーになります。つまり、トップレベルのクエリ式に自由変数を含めることはできません。

上記の文法生成規則では、nameword に似ていますが、C プログラミング言語で有効な識別子であるという追加の制約があります。変数を参照する場合は、先頭に「$」を付ける必要があります。

let 式で定義される変数は 1 つだけですが、変数をネストできます。

ターゲット パターンと変数参照はどちらも単一のトークン(単語)で構成されているため、構文の曖昧さが生じます。ただし、有効な変数名である単語のサブセットは、正当なターゲット パターンである単語のサブセットと重複していないため、意味のあいまいさはありません。

厳密に言えば、let 式はクエリ言語の表現性を高めるものではありません。この言語で表現可能なクエリも、それなしで表現できます。ただし、多くのクエリの簡潔さが改善され、クエリの評価の効率が高まる可能性もあります。

かっこ付きの式

expr ::= (expr)

括弧はサブ式を関連付けて、強制的に評価順序を適用します。かっこで囲まれた式は、その引数の値に評価されます。

代数集合演算: 交差、結合、集合差

expr ::= expr intersect expr
       | expr ^ expr
       | expr union expr
       | expr + expr
       | expr except expr
       | expr - expr

これらの 3 つの演算子は、引数に対して通常の集合演算を計算します。各演算子には 2 つの形式があります。intersect などの名詞形式と、^ などの記号形式があります。どちらの形式も同等ですが、記号形式の方が入力が簡単です。(わかりやすくするために、このページの残りの部分では名詞形式を使用します)。

次に例を示します。

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 個以上のターゲット パターンのセットの結合を計算します。

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) の省略形ですが、cat 以外のシェルコマンド(上記の awk コマンドなど)も使用できます。

関数

expr ::= word '(' int | word | expr ... ')'

クエリ言語にはいくつかの関数が定義されています。関数の名前によって、必要な引数の数と型が決まります。次の関数を使用できます。

依存関係の推移的閉包: 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 の任意のターゲットまでの、すべてのパス上のノードのグラフを返します。

結果のグラフは、依存関係関係に従って並べ替えられます。詳しくは、グラフの順序のセクションをご覧ください。

サムパス
somepath(S1 + S2, E)、考えられる結果の 1 つ。
サムパス
somepath(S1 + S2, E)、可能性のある別の結果。
Allpaths
allpaths(S1 + S2, 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_librarycc_binary などのルール ターゲットのセットに評価され、kind("source file", deps(//foo))//foo ターゲットの依存関係の推移閉包内のすべてのソースファイルのセットになります。

pattern 引数を引用符で囲む必要がある場合が多くあります。引用符で囲まないと、source file.*_test などの多くの正規表現が、パーサーによって単語と見なされなくなるためです。

package group と照合する場合、:all で終わるターゲットでは結果が返されない可能性があります。代わりに :all-targets を使用してください。

ターゲット名のフィルタリング: filter

expr ::= filter(word, expr)

filter(pattern, input) 演算子は、一連のターゲットにフィルタを適用し、ラベル(絶対形式)がパターンと一致しないターゲットを破棄します。入力のサブセットとして評価されます。

最初の引数 pattern は、ターゲット名に対する正規表現を含む単語です。filter 式は、xinput セットのメンバーであり、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 式は、xinput セットのメンバーであり、定義された属性 name を持つルールであり、属性値に正規表現 pattern の(アンカーなしの)一致が含まれているすべてのターゲット x を含むセットに評価されます。name が省略可能な属性で、ルールで明示的に指定されていない場合は、デフォルトの属性値が比較に使用されます。次に例を示します。

attr(linkshared, 0, deps(//foo))

は、linkshared 属性を持つことが許可されているすべての //foo 依存関係(cc_binary ルールなど)を選択し、明示的に 0 に設定するか、まったく設定せずにデフォルト値を 0 にします(cc_binary ルールなど)。

リスト型属性(srcsdata など)は、[ かっこで始まり ] かっこで始まり、,(カンマ、スペース)を使用して複数の値を区切り、[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 のメンバーであり、predicate のすべてのターゲットの yy から参照できるように、すべてのターゲット x を含むセットと評価します。x例:

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 ルールを、そのルールが参照する個々のテストセットに展開して、tagsize によるフィルタリングを適用します。

デフォルトでは、クエリ評価はすべての 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 ファイルのターゲットを返します。

rbuildfiles 演算子のスコープは、--universe_scope フラグで指定されたユニバースです。BUILD ファイルと .bzl ファイルに直接対応していないファイルは、結果に影響しません。たとえば、BUILD ファイルで明示的に指定されている場合でも、ソースファイル(foo.cc など)は無視されます。ただし、シンボリック リンクは考慮されるため、foo/BUILDbar/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 で実行する場合、順序なし出力と互換性のある出力形式のみが許可されます。具体的には、graphminrankmaxrank の出力形式は禁止されています。

出力形式によっては、追加のオプションを使用できます。各出力オプションの名前には、適用される出力形式の接頭辞が付いています。そのため、--graph:factored--output=graph が使用されている場合にのみ適用され、graph 以外の出力形式が使用されている場合は効果がありません。同様に、--xml:line_numbers--output=xml が使用されている場合にのみ適用されます。

結果の並べ替えについて

クエリ式は常にグラフ順序保存の法則に従いますが、結果の表示は、依存関係の順序付けまたは順序なしのどちらでも行えます。これは、結果セットのターゲットやクエリの計算方法には影響しません。結果が stdout に出力される方法にのみ影響します。また、依存関係の順序で同等のノードは、アルファベット順に並べられる場合とそうでない場合があります。この動作は、--order_output フラグを使用して制御できます。(--[no]order_results フラグは --order_output フラグの機能のサブセットであり、非推奨です)。

このフラグのデフォルト値は auto で、結果が辞書順で出力されます。ただし、somepath(a,b) を使用すると、結果は deps の順序で出力されます。

このフラグが no で、--outputbuildlabellabel_kindlocationpackageprotoxml のいずれかである場合、出力は任意の順序で出力されます。通常、これが最も速い方法です。ただし、--outputgraphminrankmaxrank のいずれかである場合はサポートされません。これらの形式を使用すると、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 プロトコル バッファの長さ区切りのストリームを出力します。これは、(i)ターゲットが多すぎるために 1 つの QueryResult に収まらない場合、または(ii)Bazel が出力中に処理を開始できない場合に、プロトコル バッファのサイズ制限を回避するために役立ちます。

--output textproto

--output proto と同様に、QueryResult プロトコル バッファをテキスト形式で出力します。

--output streamed_jsonproto

--output streamed_proto と同様に、Target プロトコル バッファのストリームを ndjson 形式で出力します。

--output minrank --output maxrank

label と同様に、minrankmaxrank の出力形式では、結果のグラフに各ターゲットのラベルが出力されますが、トポロジ順に表示されるのではなく、ランク番号が先行するランク順に表示されます。これらは、結果の並べ替え --[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 for BUILD ファイル」として使用できます。

ロケーション情報はターゲットの種類によって異なります(kind 演算子をご覧ください)。ルールの場合は、BUILD ファイル内のルールの宣言の場所が出力されます。ソースファイルの場合は、実際のファイルの 1 行目の場所が出力されます。生成されたファイルの場合は、そのファイルを生成するルールの場所が出力されます。(クエリツールには、生成されたファイルの実際の場所を見つけるのに十分な情報がないため、ビルドがまだ実行されていない場合には、いずれの場合も、ファイルが存在しない可能性があります)。

--output package

このオプションは、結果セット内のターゲットが属するすべてのパッケージの名前を出力します。名前は辞書順で出力され、重複は除外されます。これは形式上、ラベルのセット(パッケージ、ターゲット)からパッケージへの射影です。

外部リポジトリのパッケージは @repo//foo/bar の形式になりますが、メイン リポジトリのパッケージは foo/bar の形式になります。

この出力オプションは、deps(...) クエリと組み合わせて使用することで、特定のターゲット セットをビルドするためにチェックアウトする必要があるパッケージのセットを探すことができます。

結果のグラフを表示する

--output graph

このオプションを使用すると、クエリ結果が一般的な AT&T GraphViz 形式の有向グラフとして出力されます。通常、結果は .png.svg などのファイルに保存されます。(dot プログラムがワークステーションにインストールされていない場合は、sudo apt-get install graphviz コマンドを使用してインストールできます)。呼び出しの例については、以下の例のセクションをご覧ください。

この出力形式は、allpathsdepsrdeps クエリで特に役立ちます。--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 を依存関係としてリストします。