構成可能なクエリ(cquery)

<ph type="x-smartling-placeholder"></ph> 問題を報告する ソースを表示 夜間 · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

cquery は、query のバリアントで、 select() とビルド オプションビルドへの影響 表示されます。

Bazel による分析の結果を基にして、この処理が行われます。 フェーズ、 統合されています一方、query は、次の結果に対して実行されます。 オプションが評価される前の Bazel の読み込みフェーズ。

例:

$ cat > tree/BUILD <<EOF
sh_library(
    name = "ash",
    deps = select({
        ":excelsior": [":manna-ash"],
        ":americana": [":white-ash"],
        "//conditions:default": [":common-ash"],
    }),
)
sh_library(name = "manna-ash")
sh_library(name = "white-ash")
sh_library(name = "common-ash")
config_setting(
    name = "excelsior",
    values = {"define": "species=excelsior"},
)
config_setting(
    name = "americana",
    values = {"define": "species=americana"},
)
EOF
# Traditional query: query doesn't know which select() branch you will choose,
# so it conservatively lists all of possible choices, including all used config_settings.
$ bazel query "deps(//tree:ash)" --noimplicit_deps
//tree:americana
//tree:ash
//tree:common-ash
//tree:excelsior
//tree:manna-ash
//tree:white-ash

# cquery: cquery lets you set build options at the command line and chooses
# the exact dependencies that implies (and also the config_setting targets).
$ bazel cquery "deps(//tree:ash)" --define species=excelsior --noimplicit_deps
//tree:ash (9f87702)
//tree:manna-ash (9f87702)
//tree:americana (9f87702)
//tree:excelsior (9f87702)

各結果には、次の一意の識別子 (9f87702) が含まれます。 構成 使用されます。

cquery は構成されたターゲット グラフに対して実行されるため、インサイトがないということです ビルド アクションや [test_suite](/versions/6.1.0/reference/be/general#test_suite) へのアクセスなどのアーティファクトに 構成されていないからです。前者については、[aquery](/versions/6.1.0/docs/aquery) をご覧ください。

基本的な構文

単純な cquery 呼び出しは次のようになります。

bazel cquery "function(//target)"

クエリ式 "function(//target)" は、以下で構成されます。

  • function(...) は、ターゲットで実行する関数です。cquery ほとんどの query関数の集合と、 作成します。
  • //target は、関数にフィードされる式です。この例では、 単純なターゲットです。ただし、クエリ言語では関数のネストも可能です。 例については、クエリの手順をご覧ください。

cquery には、読み込みと分析を行うターゲットが必要です。 学びました特に指定されていない限り、cquery は、 クエリ式です。--universe_scope を参照してください。 を使用して、トップレベルのビルド ターゲットの依存関係をクエリできます。

構成

次の行をご覧ください。

//tree:ash (9f87702)

は、//tree:ash が ID 9f87702 の構成でビルドされていることを意味します。ほとんどの これは、変数を定義するビルド オプション値の不透明なハッシュです。 できます。

構成の完全な内容を表示するには、次のコマンドを実行します。

$ bazel config 9f87702

ホスト構成では、特別な ID (HOST) が使用されます。などの未生成のソースファイル srcs で一般的に見られるオブジェクトには、特別な ID (null) を使用します( 構成する必要はありません)。

9f87702 は、完全な ID の接頭辞です。これは、完全な ID が SHA-256 ハッシュは長く、追跡が困難です。cquery は、すべての有効な プレフィックスを付加します。例: Git ショート ハッシュ。 完全な ID を表示するには、$ bazel config を実行します。

ターゲット パターンの評価

//foo は、cqueryquery で意味が異なります。その理由は、 cquery は、構成されたターゲットを評価します。ビルドグラフには複数の //foo の構成済みバージョン。

cquery の場合、クエリ式のターゲット パターンが評価されます。 そのパターンに一致するラベルが、構成済みのすべてのターゲットに適用されます。出力: 決定的だが、cqueryコアクエリ注文コントラクト

これにより、query よりもクエリ式でより繊細な結果が得られます。 たとえば、次の例では複数の結果が生成されます。

# Analyzes //foo in the target configuration, but also analyzes
# //genrule_with_foo_as_tool which depends on a host-configured
# //foo. So there are two configured target instances of //foo in
# the build graph.
$ bazel cquery //foo --universe_scope=//foo,//genrule_with_foo_as_tool
//foo (9f87702)
//foo (HOST)

クエリ対象のインスタンスを正確に宣言するには、次のコマンドを使用します。 config 関数

queryターゲット パターンを表示 ドキュメントをご覧ください。

関数

一連の関数query でサポートされますが、cquery では次を除くすべてがサポートされています allrdeps, buildfiles, rbuildfiles, siblings tests visible cquery には、次の新しい関数も導入されています。

config

expr ::= config(expr, word)

config 演算子は、構成されているターゲットを見つけようとします。 最初の引数で指定されるラベルと、 使用します。

2 番目の引数で有効な値は、targethostnull、または カスタム構成ハッシュ。ハッシュは、$ bazel config または以前の cquery の出力から取得できます。

例:

$ bazel cquery "config(//bar, host)" --universe_scope=//foo
$ bazel cquery "deps(//foo)"
//bar (HOST)
//baz (3732cc8)

$ bazel cquery "config(//baz, 3732cc8)"

最初の引数のすべての結果が、指定された 見つかったもののみが返されます。結果がない場合 見つからない場合、クエリは失敗します。

オプション

ビルド オプション

cquery は、通常の Bazel ビルドで実行されるため、次のセットを継承します。 ビルド中に使用可能なオプション

Cquery オプションの使用

--universe_scope(カンマ区切りリスト)

多くの場合、構成済みのターゲットの依存関係は 遷移 依存関係が互いに異なるものになります。このフラグ ターゲットが依存関係または推移的なターゲットとして作成されたかのように、ターゲットをクエリできる 依存関係が存在します。例:

# x/BUILD
genrule(
     name = "my_gen",
     srcs = ["x.in"],
     outs = ["x.cc"],
     cmd = "$(locations :tool) $< >$@",
     tools = [":tool"],
)
cc_library(
    name = "tool",
)

genrule のツールは ホスト構成 したがって、次のクエリでは次のような出力が生成されます。

クエリ ターゲット構築 出力
bazel cquery "//x:tool" //x:tool //x:tool(targetconfig)
bazel cquery "//x:tool"--universe_scope=&quot;//x:my_gen&quot; //x:my_gen //x:tool(hostconfig)

このフラグを設定すると、その内容がビルドされます。未設定の場合、すべてのターゲット クエリ式で記述されているとおりに作成されます。の推移的クロージャは、 構築ターゲットがクエリ全体として使用されます。いずれにしても 最上位でビルド可能であること(つまり、最上位レベルと互換性があること) オプション)。cquery は、これらを推移的に閉じて結果を返します。 使用しないでください。

一番上のクエリ式ですべてのターゲットを構築できる場合でも、 しない方がよい場合があります。たとえば、サービス アカウント キーを明示的に --universe_scope により、ターゲットのビルドが 構成を管理する必要がなくなります。使用する構成のどのバージョンを (現在のところ、ターゲット タイプを (完全に指定する必要はありません)。このフラグを設定する必要があります。 クエリ式が deps(//foo) よりも複雑な場合。

--implicit_deps(ブール値、デフォルト=True)

このフラグを false に設定すると、明示的に設定されていないすべての結果が除外されます。 BUILD ファイルに記述し、代わりに Bazel で他の場所に設定します。これには、解決済みのフィルタリングが含まれます 統合できます。

--tool_deps(ブール値、デフォルト=True)

このフラグを false に設定すると、 そのパスは、ターゲットとターゲットの間の 構成と ターゲット以外の構成。 クエリされたターゲットがターゲット構成にある場合、--notool_deps を設定すると、 ターゲット構成に含まれているターゲットのみが返されます。クエリ対象の ターゲットがターゲット以外の構成にある場合、--notool_deps を設定すると、 ターゲット以外の構成でもターゲットを絞ることができます。通常、この設定はフィルタリングには影響しません。 解決されたツールチェーンが 含まれます

--include_aspects(ブール値、デフォルト=True)

アスペクトが追加可能 ビルドに追加できます。デフォルトでは、cquery はアスペクトをフォローしません。理由は次のとおりです。 クエリ可能なグラフが大きくなり、より多くのメモリが使用されます。しかし それに従えば 正確な結果を得られます。

大規模なクエリのメモリへの影響が心配でない場合は、 使用します。

アスペクトを無効にしてクエリを実行すると、ターゲット X が失敗し、 ターゲット Y をビルドしていますが、依存関係がアスペクトを通じて発生しているため、cquery somepath(Y, X)cquery deps(Y) | grep 'X' は結果を返しません。

出力形式

デフォルトでは、cquery はラベルと構成のペアの依存関係順のリストを出力します。 結果を公開するためのその他のオプションは他にもあります。

切り替え効果

--transitions=lite
--transitions=full

構成の遷移 さまざまなリソースの最上位レベルのターゲットの下に 構成ミスがないかチェックします。

たとえば、あるターゲットから、すべての VM の tools 属性で指定する必要があります。これらは属性と呼ばれ、 使用できます。ルールによって独自の構成に移行を課すこともできます。 いわゆるルールクラス遷移と呼ばれるものです。この出力形式では、 種類やビルドへの影響など 。

この出力形式は --transitions フラグによってトリガーされます。このフラグはデフォルトで NONE に設定。FULL モードまたは LITE モードに設定できます。FULL モードの出力 ルールクラスの遷移と属性の遷移に関する情報が表示されます。 移行前と移行後のオプションの詳しい差分を確認できます。LITE モード オプション diff なしで同じ情報が出力されます。

プロトコル メッセージ出力

--output=proto

このオプションを使用すると、生成されるターゲットがバイナリ プロトコルで出力されます。 あります。プロトコル バッファの定義については、 src/main/protobuf/analysis.proto.

CqueryResult は、cquery の結果を含むトップレベルのメッセージです。これは、 ConfiguredTarget 個のメッセージのリストと Configuration 個のリストがある ブロックすることもできます。各 ConfiguredTarget には、値が等しい configuration_id があります。 対応する Configuration メッセージの id フィールドのものに置き換えます。

--[no]proto:include_configurations

デフォルトでは、クエリの結果は各クエリの一部として構成情報を返します。 表示されます。この情報を省略して proto 出力を取得する場合 出力する場合は、このフラグを false に設定します。

クエリの proto 出力のドキュメントを参照 をご覧ください。

出力をグラフ化する

--output=graph

このオプションは、Graphviz 互換の .dot ファイルとして出力を生成します。query さんのチャンネルを見る 詳しくは、グラフ出力のドキュメントをご覧ください。cquery--graph:node_limit--graph:factored

ファイル出力

--output=files

このオプションは、一致したターゲットごとに生成された出力ファイルのリストを出力します。 bazel build の最後に出力されるリストと同様のクエリで照合します。 呼び出すことができます。出力には、リクエストされたファイルでアドバタイズされたファイルのみが含まれます。 出力グループが --output_groups フラグ。 これにはソースファイルが含まれます。

Starlark を使用した出力形式の定義

--output=starlark

この出力形式では、Starlark 関数がクエリの結果の構成済みターゲットごとに出力され、 返されます。--starlark:file フラグは、Pod のロケーションを指定します。 単一のパラメータを持つ format という名前の関数を定義する Starlark ファイル target。この関数は、 わかりますまたは、便宜上、 def format(target): return expr として宣言された関数の本体を、 --starlark:expr フラグ。

「cquery」Starlark 言語

cquery Starlark 環境は、BUILD ファイルまたは .bzl ファイルとは異なります。内容 すべてのコア Starlark 組み込みの定数と関数 に加えて、後述する cquery 固有のパラメータ(glob などは除く)が含まれます。 nativerule などを使用できます。また、load ステートメントはサポートされていません。

build_options(target)

build_options(target) は、キーがビルド オプション識別子であるマップを返します( 構成) その値が Starlark 値です有効な値でない Starlark のビルド オプション このマップでは省略されています

ターゲットが入力ファイルの場合、build_options(target) は入力ファイルとして None を返します。 ターゲットに null 構成があります。

プロバイダ(ターゲット)

providers(target) は、キーが名前であるマップを返します。 プロバイダ (例: "DefaultInfo")とその値が Starlark 値です。プロバイダ 値が正規でない Starlark 値はこのマップから省略されます。

//foo によって生成されたすべてのファイルのベース名のスペース区切りリストを出力します。

  bazel cquery //foo --output=starlark \
    --starlark:expr="' '.join([f.basename for f in target.files.to_list()])"

rule ターゲットによって生成されたすべてのファイルのパスのスペース区切りリストを出力します。 //bar とそのサブパッケージ:

  bazel cquery 'kind(rule, //bar/...)' --output=starlark \
    --starlark:expr="' '.join([f.path for f in target.files.to_list()])"

//foo によって登録されたすべてのアクションのニーモニックのリストを出力します。

  bazel cquery //foo --output=starlark \
    --starlark:expr="[a.mnemonic for a in target.actions]"

cc_library //baz によって登録されたコンパイル出力のリストを出力します。

  bazel cquery //baz --output=starlark \
    --starlark:expr="[f.path for f in target.output_groups.compilation_outputs.to_list()]"

//foo のビルド時にコマンドライン オプション --javacopt の値を出力します。

  bazel cquery //foo --output=starlark \
    --starlark:expr="build_options(target)['//command_line_option:javacopt']"

各ターゲットのラベルを 1 つだけ出力します。この例では、 ファイルで定義されている Starlark 関数。

  $ cat example.cquery

  def has_one_output(target):
    return len(target.files.to_list()) == 1

  def format(target):
    if has_one_output(target):
      return target.label
    else:
      return ""

  $ bazel cquery //baz --output=starlark --starlark:file=example.cquery

厳密に Python 3 である各ターゲットのラベルを出力します。この例では、 ファイルで定義されている Starlark 関数。

  $ cat example.cquery

  def format(target):
    p = providers(target)
    py_info = p.get("PyInfo")
    if py_info and py_info.has_py3_only_sources:
      return target.label
    else:
      return ""

  $ bazel cquery //baz --output=starlark --starlark:file=example.cquery

ユーザー定義のプロバイダから値を抽出します。

  $ cat some_package/my_rule.bzl

  MyRuleInfo = provider(fields={"color": "the name of a color"})

  def _my_rule_impl(ctx):
      ...
      return [MyRuleInfo(color="red")]

  my_rule = rule(
      implementation = _my_rule_impl,
      attrs = {...},
  )

  $ cat example.cquery

  def format(target):
    p = providers(target)
    my_rule_info = p.get("//some_package:my_rule.bzl%MyRuleInfo'")
    if my_rule_info:
      return my_rule_info.color
    return ""

  $ bazel cquery //baz --output=starlark --starlark:file=example.cquery

Cquery と query の比較

cqueryquery は互いに補完し合い、 特定することです以下を参考に、どちらが適しているかを判断してください。

  • cquery は特定の select() 分岐をたどって、 作成したグラフをモデル化できます。query はどれかわかりません そうすると、すべてのブランチを含めることで過大近似値になります。
  • cquery の精度のために、次の値よりも多くのグラフを構築する必要があります。 query では可能です。具体的には、cquery 構成されたターゲットを評価しますが、query のみを評価します。 targets を評価します。これには時間とメモリの使用量が多くなります。
  • cqueryによる解釈 クエリ言語ではあいまいさが生じます 回避したいデータqueryたとえば "//foo" が 2 つの構成に存在し、 cquery "deps(//foo)" で使用すべきですか? [config](#config) 関数が役立ちます。
  • cquery は比較的新しいツールであるため、特定の用途はサポートされていません。 対応できます詳しくは、既知の問題をご覧ください。

既知の問題

cquery が「ビルド」するすべてのターゲット同じ構成にする必要があります。

クエリを評価する前に、cquery はビルドを ビルド アクションが実行される前のステップです。ターゲットとなる 「ビルド」デフォルトでは、クエリに表示されるすべてのラベルから選択されます。 式(これはオーバーライドして --universe_scope に置き換えます)。これらの 同じ構成にする必要があります。

これらは通常、最上位の「ターゲット」を共有しますが構成、 構成を変更することもできます。 受信エッジ遷移。 ここで cquery が不足しています。

回避策: 可能であれば、--universe_scope をより厳格に設定します。 あります。例:

# This command attempts to build the transitive closures of both //foo and
# //bar. //bar uses an incoming edge transition to change its --cpu flag.
$ bazel cquery 'somepath(//foo, //bar)'
ERROR: Error doing post analysis query: Top-level targets //foo and //bar
have different configurations (top-level targets with different
configurations is not supported)

# This command only builds the transitive closure of //foo, under which
# //bar should exist in the correct configuration.
$ bazel cquery 'somepath(//foo, //bar)' --universe_scope=//foo

--output=xml はサポートされていません。

非確定的な出力。

cquery は、ビルドグラフを自動的にワイプしません。 過去のコマンドの結果を取得しやすくなるため、 分析できますたとえば、genquery はホスト遷移を実行します。 tools 属性です。つまり、 ホスト構成

この移行によって生じる影響は以下で確認できます。

$ cat > foo/BUILD <<<EOF
genrule(
    name = "my_gen",
    srcs = ["x.in"],
    outs = ["x.cc"],
    cmd = "$(locations :tool) $< >$@",
    tools = [":tool"],
)
cc_library(
    name = "tool",
)
EOF

    $ bazel cquery "//foo:tool"
tool(target_config)

    $ bazel cquery "deps(//foo:my_gen)"
my_gen (target_config)
tool (host_config)
...

    $ bazel cquery "//foo:tool"
tool(host_config)

回避策: 起動オプションを変更して、構成されたターゲットの再分析を強制します。 たとえば、ビルドコマンドに --test_arg=&lt;whatever&gt; を追加します。

トラブルシューティング

再帰ターゲット パターン(/...

問題が発生した場合:

$ bazel cquery --universe_scope=//foo:app "somepath(//foo:app, //foo/...)"
ERROR: Error doing post analysis query: Evaluation failed: Unable to load package '[foo]'
because package is not in scope. Check that all target patterns in query expression are within the
--universe_scope of this query.

にもかかわらず、パッケージ //foo が対象範囲外であることを誤って示唆しています。 --universe_scope=//foo:app に含まれている。これは、インフラストラクチャの設計上の制約が原因で、 cquery。回避策として、ユニバースに //foo/... を明示的に含めます。 scope:

$ bazel cquery --universe_scope=//foo:app,//foo/... "somepath(//foo:app, //foo/...)"

それでも問題が解決しない場合(たとえば、//foo/... の一部のターゲットが (選択したビルドフラグを使用してビルドする)と、手動で 構成要素パッケージを前処理するクエリによって構成します。

# Replace "//foo/..." with a subshell query call (not cquery!) outputting each package, piped into
# a sed call converting "<pkg>" to "//<pkg>:*", piped into a "+"-delimited line merge.
# Output looks like "//foo:*+//foo/bar:*+//foo/baz".
#
$  bazel cquery --universe_scope=//foo:app "somepath(//foo:app, $(bazel query //foo/...
--output=package | sed -e 's/^/\/\//' -e 's/$/:*/' | paste -sd "+" -))"