Bazel クエリ リファレンス

問題を報告 ソースを表示

このページは、bazel query を使用してビルドの依存関係を分析する際に使用する Bazel Query Language のリファレンス マニュアルです。また、bazel query がサポートする出力形式についても説明します。

実際のユースケースについては、Bazel クエリの使用方法をご覧ください。

その他のクエリのリファレンス

読み込み後フェーズのターゲット グラフで実行される query に加えて、Bazel にはアクション グラフのクエリ構成可能なクエリが含まれています。

アクション グラフのクエリ

アクション グラフ クエリ(aquery)は、分析後の構成済みターゲット グラフを操作し、アクションアーティファクト、それらの関係に関する情報を提供します。aquery は、構成済みのターゲットグラフから生成されたアクション/アーティファクトのプロパティに関心がある場合に役立ちます。たとえば、実際に実行されるコマンドや、その入力、出力、ニーモニックなどです。

詳細については、aquery リファレンスをご覧ください。

構成可能なクエリ

従来の Bazel クエリは、読み込み後フェーズのターゲット グラフで実行されるため、構成や関連するコンセプトに関する概念はありません。特に、select ステートメントが正しく解決されず、利用可能なすべての 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、特殊文字 */@.-_:$~[](アスタリスク、スラッシュ、at、ピリオド、ハイフン、アンダースコア、コロン、ドル記号、チルダ、左角括弧、右角括弧)から記述された文字のシーケンスです。ただし、引用符で囲まれていない単語をハイフン - やアスタリスク * で始めることはできません。これは、相対ターゲット名の先頭がこれらの文字であっても同様です。

    引用符で囲まれていない単語も、ターゲット名に使用できる場合でも、プラス記号 + または等号 = は使用できません。クエリ式を生成するコードを記述する場合は、ターゲット名を引用符で囲む必要があります。

    ユーザーが指定した値から 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 の種類のターゲットのみを含むようにセットをフィルタすると、元のグラフではこれらのペアのいずれも直接接続されていない場合でも、結果のサブセットのすべてのターゲットのペアの間に同じ推移的な部分順序関係が保持されます。(ビルドの依存関係グラフにはファイル ファイルのエッジはありません)。

ただし、すべての演算子は順序を保持しますが、セット演算など、一部の演算では独自の順序の制約が発生しません。次の式を考えてみます。

deps(x) union y

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

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

Sky クエリ

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

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

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

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

Sky Query モードを有効にするには、次の 2 つのフラグ(--universe_scope または --infer_universe_scope)と --order_output=no を渡します。--universe_scope=<target_pattern1>,...,<target_patternN> は、ターゲット パターンで指定されたターゲット パターンの推移的クロージャをプリロードするようクエリに指示します。ターゲット パターンには加算と減算の両方があります。その後、すべてのクエリがこの「スコープ」内で評価されます。特に、allrdeps 演算子と rbuildfiles 演算子は、このスコープからの結果のみを返します。--infer_universe_scope は、クエリ式から --universe_scope の値を推測するよう Bazel に指示します。この推定値は、クエリ式内の一意のターゲット パターンのリストですが、意図した値とは異なる場合があります。例:

bazel query --infer_universe_scope --order_output=no "allrdeps(//my:target)"

このクエリ式の一意のターゲット パターンのリストは ["//my:target"] であるため、Bazel はこれを呼び出しと同じように扱います。

bazel query --universe_scope=//my:target --order_output=no "allrdeps(//my:target)"

しかし、--universe_scope を使用したクエリの結果は //my:target だけになります。//my:target の逆依存関係は構造によってこの宇宙にはありません。その一方で、次の点を考慮してください。

bazel query --infer_universe_scope --order_output=no "tests(//a/... + b/...) intersect allrdeps(siblings(rbuildfiles(my/starlark/file.bzl)))"

これは、定義で特定の .bzl ファイルを使用するターゲットに推移的に依存する一部のディレクトリの下にあるターゲットの tests 展開で、テスト ターゲットを計算しようとする意味のあるクエリ呼び出しです。ここでは、--infer_universe_scope が便利です。特に、--universe_scope を選択するためにクエリ式を自身で解析する必要がある場合に便利です。

そのため、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/... と同じです。

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

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

let 式は変数を 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 ...) 演算子は、ゼロ個以上のターゲット パターンを空白文字(カンマなし)で区切って、その和集合を計算します。

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 ... ')'

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

依存関係の推移的終了: 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) は、//foo の推移的クロージャにある //common に直接依存するすべてのノードを評価します。(これらの数値は、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 つのターゲット間のパスを計算します。どちらのクエリも、始点の S と終点の E の 2 つの引数を受け入れます。somepath は、S のターゲットから E のターゲットへの、任意のパスにあるノードのグラフを返します。allpaths は、S のターゲットから E のターゲットへのすべてのパスにあるノードのグラフを返します。

結果のグラフは、依存関係に応じて順序付けされます。詳しくは、グラフの順序に関するセクションをご覧ください。

サムパス
somepath(S1 + S2, E)、1 件の候補。
サムパス
somepath(S1 + S2, E): もう一つの結果。
すべてのパス
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_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 を含むセットを評価します。そのため、x はセット input のメンバーであり、x のラベル(//foo:bar などの絶対形式)には正規表現 pattern に一致する(アンカーでない)一致が含まれます。すべてのターゲット名は // で始まるため、^ 正規表現アンカーの代わりに使用できます。

多くの場合、この演算子は intersect 演算子に代わるより高速で堅牢な演算子です。たとえば、//foo:foo ターゲットのすべての bar 依存関係を表示するには、次のように評価します。

deps(//foo) intersect //bar/...

ただし、このステートメントでは bar ツリー内のすべての BUILD ファイルを解析する必要がありますが、処理に時間がかかり、関係のない BUILD ファイルではエラーが発生しやすくなります。代替案は次のとおりです。

filter(//bar, deps(//foo))

これは、最初に //foo 依存関係のセットを計算してから、指定されたパターンに一致するターゲット(つまり、部分文字列として //bar を含む名前のターゲット)のみをフィルタします。

filter(pattern, expr) 演算子のもう 1 つの一般的な用途は、特定のファイルを名前または拡張子でフィルタリングすることです。たとえば

filter("\.cc$", deps(//foo))

//foo のビルドに使用されたすべての .cc ファイルのリストが返されます。

ルール属性のフィルタリング: attr

expr ::= attr(word, word, expr)

attr(name, pattern, input) 演算子は、ターゲットのセットにフィルタを適用し、ルールではないターゲット、属性 name が定義されていないルール ターゲット、属性値が指定された正規表現 pattern と一致しないルール ターゲットを破棄します。入力のサブセットとして評価されます。

最初の引数の name は、指定された正規表現パターンと照合するルール属性の名前です。2 番目の引数 pattern は、属性値に対する正規表現です。attr 式は、x がセット input のメンバーであり、定義された属性 name を持つルールであり、属性値に正規表現 pattern に対する(アンカーでない)一致が含まれるなど、すべてのターゲット x を含むセットを評価します。name がオプションの属性であり、ルールで明示的に指定されていない場合、比較にデフォルトの属性値が使用されます。たとえば

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

リンク共有属性(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 文字以上になります)。

list-type 属性で特定の value を持つ //foo 依存関係にあるすべてのルールを選択するには、次のコマンドを使用します。

attr("tags", "[\[ ]value[,\]]", deps(//foo))

これは、value の前の文字が [ またはスペースになり、value の後の文字がカンマまたは ] になるためです。

ルールの公開設定のフィルタリング: 表示

expr ::= visible(expr, expr)

visible(predicate, input) 演算子は、一連のターゲットにフィルタを適用し、必要な可視性のないターゲットを破棄します。

最初の引数 predicate は、出力内のすべてのターゲットを参照する必要があるターゲットのセットです。visible 式は、x がセット input のメンバーになるように、すべてのターゲット x を含むセットを評価します。また、predicate のすべてのターゲット y は、y から参照できます。x例:

visible(//foo, //bar:*)

これは、公開設定に関する制限に違反することなく //foo が依存できるパッケージ //bar 内のすべてのターゲットを選択します。

タイプラベルのルール属性の評価: ラベル

expr ::= labels(word, expr)

labels(attr_name, inputs) 演算子は、セット inputs 内のルールでタイプ「ラベル」または「ラベルのリスト」の属性 attr_name で指定されたターゲットのセットを返します。

たとえば、labels(srcs, //foo) は、//foo ルールの srcs 属性に表示されるターゲットのセットを返します。inputs セットに srcs 属性を持つルールが複数ある場合、それらの srcs の和集合が返されます。

test_suites: Testing を展開してフィルタする

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 ルールを介して直接的または間接的に参照される他のパッケージに属するテストが含まれる場合があります。

パッケージ定義ファイル: 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 ファイルのターゲットを返します。

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 はグラフを生成します。--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 と同様に、結果のグラフの各ターゲットのラベルがトポロジ順に出力されますが、ターゲットのラベルの前に kind が付加されています。

--output proto

クエリ出力を QueryResult プロトコル バッファとして出力します。

--output streamed_proto

Target プロトコル バッファの長さ区切りストリームを出力します。これは、(i)ターゲットが多すぎて 1 つの QueryResult に収まらない場合にプロトコル バッファのサイズ制限を回避するため、または(i)Bazel が出力している間に処理を開始したい場合に有用です。

--output textproto

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

--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 コマンドを使用してインストールできます)。呼び出しの例については、以下の例をご覧ください。

この出力形式は、--output label などの線形形式でレンダリングすると簡単に可視化できないパスのセットが結果に含まれる場合、allpathsdeps、または rdeps クエリで特に役立ちます。

デフォルトでは、グラフは因数分解形式でレンダリングされます。つまり、トポロジ的に同等のノードが、複数のラベルを持つ 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