Bazel クエリ リファレンス

問題を報告する ソースを表示

このページは、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) に存在する場合を除く)。

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

Sky クエリ

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

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

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

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

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 を選択した場合に、クエリ式を自分で解析する必要がある場合に便利です。

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

Sky クエリには、デフォルトのクエリと比べて次のような利点と欠点があります。主なデメリットは、出力をグラフの順序に従って並べ替えることができないため、特定の出力形式が禁止されていることです。これには、デフォルト クエリでは使用できない 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/... と同じです。

変数参照 name が、囲む let 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 つの演算子は、引数に対して通常の 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 ... ')'

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

依存関係の一時的な終了: 依存関係

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_librarycc_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 ルールなど)にします。

リスト型属性(srcsdata など)は、[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 のすべてのターゲット yy が見えるように、すべてのターゲット 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 ルールを参照の個々のテストセットに展開し、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 ファイルに直接対応していないファイルは結果に影響しません。たとえば、ソースファイル(foo.cc など)は、BUILD ファイルで明示的に指定されていても無視されます。ただし、シンボリック リンクは考慮されるため、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 はグラフを生成します。コンテンツ、形式、順序は、bazel query がこのグラフを表示するのに --output コマンドライン オプションで指定します。

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 はノードを完全に確定的な(合計)順序で出力します。まず、すべてのノードがアルファベット順に並べ替えられます。次に、リスト内の各ノードが、訪問後のノードへの送信エッジを後継ノード順で走査するポストオーダー深度検索の開始として使用されます。最後に、ノードはアクセスされた順序とは逆の順序で出力されます。

ノードの表示はこの順序で遅くなる可能性があるため、決定論が重要である場合にのみ使用してください。

ビルド時に表示されるターゲットのソース形式を出力します。

--output build

このオプションを使用すると、各ターゲットは、ビルド言語で手書きされたものが表現されます。すべての変数と関数呼び出し(glob、マクロなど)が展開されます。これは、Starlark マクロの効果を確認する際に役立ちます。さらに、有効なルールごとに generator_namegenerator_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 と同様に、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」として使用できます。

場所の情報はターゲットの種類によって異なります(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 ソースファイルに依存している場合があります。因数分解グラフでは、これらのファイルはすべて 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