액션 그래프 쿼리 (검색어)

aquery 명령어를 사용하면 빌드 그래프에서 작업을 쿼리할 수 있습니다. 분석 후 구성된 타겟 그래프에서 작동하며 작업, 아티팩트, 관계에 관한 정보를 노출합니다.

aquery는 구성된 타겟 그래프에서 생성된 작업/아티팩트의 속성에 관심이 있을 때 유용합니다. 예를 들어 실행된 실제 명령어와 입력/출력/니모닉입니다.

이 도구는 여러 명령줄 옵션을 허용합니다. 특히 aquery 명령어는 일반 Bazel 빌드 위에 실행되며 빌드 중에 사용할 수 있는 옵션 집합을 상속합니다.

query, siblings, buildfiles, tests에서도 사용할 수 있는 동일한 함수 집합을 지원합니다.

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 함수에는 다음 세 가지가 있습니다.

  • inputs: 입력으로 작업을 필터링합니다.
  • outputs: 출력으로 작업 필터링
  • mnemonic: 니모닉으로 작업 필터링

expr ::= inputs(word, expr)

inputs 연산자는 expr 빌드에서 생성된 작업을 반환하며, 입력 파일 이름은 word에서 제공한 정규식과 일치합니다.

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

outputsmnemonic 함수는 유사한 구문을 공유합니다.

함수를 결합하여 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|commands|proto|jsonproto|textproto), default=text

기본 출력 형식 (text)은 사람이 읽을 수 있는 형식입니다. 머신이 읽을 수 있는 형식에는 proto, textproto 또는 jsonproto을 사용하세요. 프로토 메시지는 analysis.ActionGraphContainer입니다.

commands 출력 형식은 줄당 하나의 명령어로 빌드 명령어 목록을 출력합니다.

일반적으로 출력 순서에 의존하지 마세요. 자세한 내용은 핵심 쿼리 순서 지정 계약을 참고하세요.

--include_commandline, default=true

작업 명령줄의 콘텐츠를 출력에 포함합니다 (클 수 있음).

--include_artifacts, default=true

출력에 작업 입력 및 출력의 이름을 포함합니다 (클 수 있음).

--include_aspects, default=true

출력에 Aspect에서 생성된 작업을 포함할지 여부입니다.

--include_param_files, default=false

명령어에 사용된 param 파일의 콘텐츠를 포함합니다 (잠재적으로 큼).

--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에서 작업 그래프를 덤프합니다.

기타 도구 및 기능

Skyframe 상태에 대한 쿼리

Skyframe은 Bazel의 평가 및 증분 모델입니다. 각 Bazel 서버 인스턴스에서 Skyframe은 이전 분석 단계 실행에서 구성된 종속성 그래프를 저장합니다.

경우에 따라 Skyframe에서 작업 그래프를 쿼리하는 것이 유용합니다. 사용 사례의 예는 다음과 같습니다.

  1. bazel build //target_a 실행
  2. bazel build //target_b 실행
  3. foo.out 파일이 생성되었습니다.

Bazel 사용자는 //target_a 또는 //target_b 빌드에서 foo.out가 생성되었는지 확인하고 싶습니다.

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 도구를 사용하여 서로 다른 두 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 출력에는 측면 경로가 포함됩니다. 이는 작업을 생성한 타겟에 적용된 측면의 시퀀스입니다.

Aspect-on-Aspect의 예:

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

ti를 종속 항목에 측면 ai를 적용하는 규칙 ri의 타겟이라고 가정해 보겠습니다.

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=...)]
  ...

이는 a1(t0)에 적용된 측면 a2에 의해 작업 X가 생성되었음을 의미합니다. 여기서 a1(t0)는 타겟 t0에 적용된 측면 a1의 결과입니다.

AspectDescriptor의 형식은 다음과 같습니다.

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

AspectClass은 Aspect 클래스 이름 (네이티브 Aspect의 경우) 또는 bzl_file%aspect_name (Starlark Aspect의 경우)일 수 있습니다. AspectDescriptor종속 항목 그래프의 위상 순서로 정렬됩니다.

JSON 프로필과 연결

aquery는 빌드에서 실행되는 작업에 관한 정보 (실행되는 이유, 입력/출력)를 제공하는 반면 JSON 프로필은 실행 시점과 기간을 알려줍니다. 작업의 기본 출력이라는 공통 분모를 통해 이 두 정보 집합을 결합할 수 있습니다.

JSON 프로필에 작업의 출력을 포함하려면 --experimental_include_primary_output --noslim_profile로 프로필을 생성하세요. 슬림 프로필은 기본 출력 포함과 호환되지 않습니다. 작업의 기본 출력은 aquery에 의해 기본적으로 포함됩니다.

현재 이러한 두 데이터 소스를 결합하는 표준 도구는 제공되지 않지만 위의 정보를 사용하여 자체 스크립트를 빌드할 수 있습니다.

알려진 문제

공유 작업 처리

구성된 타겟 간에 작업이 공유되는 경우도 있습니다.

실행 단계에서는 이러한 공유 작업이 하나로 간주되어 한 번만 실행됩니다. 하지만 aquery는 실행 전, 분석 후 작업 그래프에서 작동하므로 이러한 항목을 출력 아티팩트가 정확히 동일한 execPath를 갖는 별도의 작업으로 취급합니다. 따라서 동일한 아티팩트가 중복되어 표시됩니다.

aquery 문제/계획된 기능 목록은 GitHub에서 확인할 수 있습니다.

FAQ

입력 파일의 콘텐츠가 변경되더라도 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와 혼동해서는 안 됩니다.

업데이트

문제/기능 요청이 있는 경우 여기에서 문제를 신고하세요.