アクション グラフ クエリ(aquery)

問題を報告する ソースを表示 Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

aquery コマンドを使用すると、ビルドグラフ内のアクションをクエリできます。分析後の構成済みターゲット グラフで動作し、アクション、アーティファクト、それらの関係に関する情報を公開します。

aquery は、構成済みターゲット グラフから生成されたアクション/アーティファクトのプロパティに関心がある場合に役立ちます。たとえば、実際に実行されたコマンドとその入力、出力、ニーモニックなどです。

このツールは、いくつかのコマンドライン オプションを受け入れます。特に、aquery コマンドは通常の Bazel ビルドの上に実行され、ビルド中に使用可能なオプションのセットを継承します。

従来の query で使用可能な関数と同じセットをサポートしますが、siblingsbuildfilestests もサポートします。

aquery の出力例(詳細なし):

$ bazel aquery 'deps(//some:label)'
action 'Writing file some_file_name'
  Mnemonic: ...
  Target: ...
  Configuration: ...
  ActionKey: ...
  Inputs: [...]
  Outputs: [...]

基本的な構文

aquery の構文の簡単な例を次に示します。

bazel aquery "aquery_function(function(//target))"

クエリ式(引用符で囲まれた部分)は次の要素で構成されます。

  • aquery_function(...): aquery に固有の関数。詳しくは、以下をご覧ください。
  • function(...): 従来の query としての標準の関数
  • //target は、対象のターゲットのラベルです。
# aquery examples:
# Get the action graph generated while building //src/target_a
$ bazel aquery '//src/target_a'

# Get the action graph generated while building all dependencies of //src/target_a
$ bazel aquery 'deps(//src/target_a)'

# Get the action graph generated while building all dependencies of //src/target_a
# whose inputs filenames match the regex ".*cpp".
$ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'

aquery 関数を使用する

aquery 関数は 3 つあります。

  • inputs: 入力でアクションをフィルタします。
  • outputs: 出力でアクションをフィルタする
  • mnemonic: ニーモニックでアクションをフィルタする

expr ::= inputs(word, expr)

inputs 演算子は、expr のビルドから生成されたアクションを返します。このアクションの入力ファイル名は、word で指定された正規表現と一致します。

$ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'

outputs 関数と mnemonic 関数は、同様の構文を共有します。

関数を組み合わせて AND 演算を実現することもできます。次に例を示します。

  $ bazel aquery 'mnemonic("Cpp.*", (inputs(".*cpp", inputs("foo.*", //src/target_a))))'

上記のコマンドは、//src/target_a のビルドに関与するすべてのアクションを検索します。これらのアクションのニーモニックは "Cpp.*" と一致し、入力はパターン ".*cpp" および "foo.*" と一致します。

生成される構文エラーの例:

        $ bazel aquery 'deps(inputs(".*cpp", //src/target_a))'
        ERROR: aquery filter functions (inputs, outputs, mnemonic) produce actions,
        and therefore can't be the input of other function types: deps
        deps(inputs(".*cpp", //src/target_a))

オプション

ビルド オプション

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

Aquery オプション

--output=(text|summary|proto|jsonproto|textproto), default=text

デフォルトの出力形式(text)は人間が読める形式です。マシンが読み取れる形式には prototextproto、または jsonproto を使用します。proto メッセージは analysis.ActionGraphContainer です。

--include_commandline, default=true

アクション コマンドラインの内容を出力に含めます(大きくなる可能性があります)。

--include_artifacts, default=true

出力にアクションの入力と出力の名前を含めます(大きくなる可能性があります)。

--include_aspects, default=true

Aspect によって生成されたアクションを出力に含めるかどうか。

--include_param_files, default=false

コマンドで使用されるパラメータ ファイルの内容を含めます(大きくなる可能性があります)。

--include_file_write_contents, default=false

actions.write() アクションのファイルの内容と SourceSymlinkManifest アクションのマニフェスト ファイルの内容を含めます。ファイルの内容は、--output=xxxproto を含む file_contents フィールドで返されます。--output=text を使用すると、出力に FileWriteContents: [<base64-encoded file contents>] 行が含まれます。

--skyframe_state, default=false

追加の分析を行わずに、Skyframe から Action Graph をダンプします。

その他のツールと機能

Skyframe の状態に対するクエリ

Skyframe は、Bazel の評価と増分モデルです。Skyframe は、Bazel サーバーの各インスタンスで、分析フェーズの以前の実行から構築された依存関係グラフを保存します。

場合によっては、Skyframe で Action Graph をクエリすると便利です。ユースケースの例:

  1. 実行 bazel build //target_a
  2. 実行 bazel build //target_b
  3. ファイル foo.out が生成されました。

Bazel ユーザーとして、foo.out//target_a または //target_b のビルドから生成されたかどうかを判断したい

bazel aquery 'outputs("foo.out", //target_a)'bazel aquery 'outputs("foo.out", //target_b)' を実行して、foo.out の作成を担当するアクションと、ターゲットを特定できます。ただし、以前にビルドされたターゲットの数は 2 より大きくなる可能性があり、複数の aquery コマンドを実行するのは面倒です。

代わりに、--skyframe_state フラグを使用できます。

  # List all actions on Skyframe's action graph
  $ bazel aquery --output=proto --skyframe_state

  # or

  # List all actions on Skyframe's action graph, whose output matches "foo.out"
  $ bazel aquery --output=proto --skyframe_state 'outputs("foo.out")'

--skyframe_state モードでは、aquery は、Skyframe が Bazel のインスタンスに保持しているアクション グラフのコンテンツを取得し、(必要に応じて)フィルタリングを実行して、分析フェーズを再実行せずにコンテンツを出力します。

特記事項

出力形式

--skyframe_state は現在、--output=proto--output=textproto でのみ使用できます

クエリ式にターゲット ラベルが含まれていない

現在、--skyframe_state はターゲットに関係なく、Skyframe に存在するアクション グラフ全体をクエリします。クエリでターゲット ラベルを --skyframe_state とともに指定すると、構文エラーとみなされます。

  # WRONG: Target Included
  $ bazel aquery --output=proto --skyframe_state **//target_a**
  ERROR: Error while parsing '//target_a)': Specifying build target(s) [//target_a] with --skyframe_state is currently not supported.

  # WRONG: Target Included
  $ bazel aquery --output=proto --skyframe_state 'inputs(".*.java", **//target_a**)'
  ERROR: Error while parsing '//target_a)': Specifying build target(s) [//target_a] with --skyframe_state is currently not supported.

  # CORRECT: Without Target
  $ bazel aquery --output=proto --skyframe_state
  $ bazel aquery --output=proto --skyframe_state 'inputs(".*.java")'

aquery 出力の比較

aquery_differ ツールを使用して、2 つの異なる aquery 呼び出しの出力を比較できます。たとえば、ルール定義に変更を加え、実行されるコマンドラインが変更されていないことを確認する場合などです。aquery_differ はそのためのツールです。

このツールは bazelbuild/bazel リポジトリで入手できます。これを使用するには、リポジトリをローカルマシンにクローンします。使用例を次に示します。

  $ bazel run //tools/aquery_differ -- \
  --before=/path/to/before.proto \
  --after=/path/to/after.proto \
  --input_type=proto \
  --attrs=cmdline \
  --attrs=inputs

上記のコマンドは、beforeafter の aquery 出力の違い(一方には存在し、他方には存在しないアクション、各 aquery 出力でコマンドライン/入力が異なるアクションなど)を返します。上記のコマンドを実行した結果は次のようになります。

  Aquery output 'after' change contains an action that generates the following outputs that aquery output 'before' change doesn't:
  ...
  /list of output files/
  ...

  [cmdline]
  Difference in the action that generates the following output(s):
    /path/to/abc.out
  --- /path/to/before.proto
  +++ /path/to/after.proto
  @@ -1,3 +1,3 @@
    ...
    /cmdline diff, in unified diff format/
    ...

コマンド オプション

--before, --after: 比較する aquery 出力ファイル

--input_type=(proto|text_proto), default=proto: 入力ファイルの形式。prototextproto の aquery 出力がサポートされています。

--attrs=(cmdline|inputs), default=cmdline: 比較するアクションの属性。

アスペクト オン アスペクト

アスペクトを重ねて適用することもできます。これらのアスペクトによって生成されたアクションの aquery 出力には、アスペクト パスが含まれます。これは、アクションを生成したターゲットに適用されたアスペクトのシーケンスです。

アスペクト オン アスペクトの例:

  t0
  ^
  | <- a1
  t1
  ^
  | <- a2
  t2

ti をルール ri のターゲットとします。このルールは、依存関係にアスペクト ai を適用します。

a2 がターゲット t0 に適用されるとアクション X が生成されるとします。アクション X の bazel aquery --include_aspects 'deps(//t2)' のテキスト出力は次のようになります。

  action ...
  Mnemonic: ...
  Target: //my_pkg:t0
  Configuration: ...
  AspectDescriptors: [//my_pkg:rule.bzl%**a2**(foo=...)
    -> //my_pkg:rule.bzl%**a1**(bar=...)]
  ...

これは、アクション Xa1(t0) に適用されたアスペクト a2 によって生成されたことを意味します。ここで、a1(t0) はターゲット t0 に適用されたアスペクト a1 の結果です。

AspectDescriptor の形式は次のとおりです。

  AspectClass([param=value,...])

AspectClass は、Aspect クラスの名前(ネイティブ Aspect の場合)または bzl_file%aspect_name(Starlark Aspect の場合)にできます。AspectDescriptor は、依存関係グラフのトポロジカル順に並べ替えられます。

JSON プロファイルとのリンク

aquery はビルドで実行されているアクション(実行されている理由、入力/出力)に関する情報を提供しますが、JSON プロファイルは実行のタイミングと期間を教えてくれます。これらの 2 つの情報を、アクションの主な出力という共通の分母で組み合わせることができます。

アクションの出力を JSON プロファイルに含めるには、--experimental_include_primary_output --noslim_profile を使用してプロファイルを生成します。スリム プロファイルは、プライマリ出力の組み込みと互換性がありません。アクションのプライマリ出力は、aquery によってデフォルトで含まれます。

現在、これら 2 つのデータソースを組み合わせるための標準ツールは提供されていませんが、上記の情報を使用して独自のスクリプトを作成することは可能です。

既知の問題

共有アクションの処理

アクションは、構成されたターゲット間で共有されることがあります。

実行フェーズでは、これらの共有アクションは1 つと見なされ、1 回だけ実行されます。ただし、aquery は実行前の分析後のアクション グラフで動作するため、これらは出力アーティファクトの execPath がまったく同じである別々のアクションとして扱われます。その結果、同等のアーティファクトが重複して表示されます。

aquery の問題と計画されている機能のリストは、GitHub で確認できます。

よくある質問

入力ファイルの内容が変更されても、ActionKey は同じままです。

aquery のコンテキストでは、ActionKeyActionAnalysisMetadata#getKey から取得した String を指します。

  Returns a string encoding all of the significant behaviour of this Action that might affect the
  output. The general contract of `getKey` is this: if the work to be performed by the
  execution of this action changes, the key must change.

  ...

  Examples of changes that should affect the key are:

  - Changes to the BUILD file that materially affect the rule which gave rise to this Action.
  - Changes to the command-line options, environment, or other global configuration resources
      which affect the behaviour of this kind of Action (other than changes to the names of the
      input/output files, which are handled externally).
  - An upgrade to the build tools which changes the program logic of this kind of Action
      (typically this is achieved by incorporating a UUID into the key, which is changed each
      time the program logic of this action changes).
  Note the following exception: for actions that discover inputs, the key must change if any
  input names change or else action validation may falsely validate.

これは入力ファイルの内容の変更を除外するものであり、RemoteCacheClient#ActionKey と混同しないでください。

アップデート

問題や機能リクエストについては、こちらから問題を報告してください。