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` 함수는 세 가지가 있습니다.aquery
inputs: 입력으로 작업을 필터링합니다.outputs: 출력으로 작업을 필터링합니다.mnemonic: 니모닉으로 작업을 필터링합니다.
expr ::= inputs(word, expr)
inputs 연산자는 입력 파일 이름이 word에서 제공하는 정규 표현식과 일치하는 expr 빌드에서 생성된 작업을 반환합니다.
$ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'
outputs 및 mnemonic 함수는 비슷한 구문을 공유합니다.
함수를 결합하여 AND 연산을 실행할 수도 있습니다. 예를 들면 다음과 같습니다.
$ bazel aquery 'mnemonic("Cpp.*", (inputs(".*cpp", inputs("foo.*", //src/target_a))))'
위 명령어는 니모닉이 "Cpp.*"와 일치하고 입력이 패턴
".*cpp" 및 "foo.*"와 일치하는 //src/target_a 빌드와 관련된 모든 작업을 찾습니다.
생성된 구문 오류의 예는 다음과 같습니다.
$ 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를 사용하세요.
proto 메시지는 analysis.ActionGraphContainer입니다.
commands 출력 형식은 빌드 명령어 목록을
한 줄에 하나의 명령어로 출력합니다.
일반적으로 출력 순서에 의존하지 마세요. 자세한 내용은 핵심 쿼리 순서 지정 계약을 참고하세요.
--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 작업의 매니페스트 파일 콘텐츠를 포함합니다. 파일 콘텐츠는
file_contents 필드에 --output=xxxproto와 함께 반환됩니다.
--output=text를 사용하면 출력에
FileWriteContents: [<base64-encoded file contents>]
줄이 포함됩니다.
--skyframe_state, default=false
추가 분석을 실행하지 않고 Skyframe에서 작업 그래프를 덤프합니다.
기타 도구 및 기능
Skyframe 상태에 대해 쿼리
Skyframe은 Bazel의 평가 및 증분 모델입니다. 각 Bazel 서버 인스턴스에서 Skyframe은 종속 항목 그래프 를 저장합니다. 이 그래프는 분석 단계의 이전 실행에서 구성되었습니다.
경우에 따라 Skyframe에서 작업 그래프를 쿼리하는 것이 유용합니다. 사용 사례는 다음과 같습니다.
bazel build //target_a실행bazel build //target_b실행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는 Bazel 인스턴스에서 Skyframe이 유지하는 작업 그래프의 콘텐츠를 가져와서 선택적으로 필터링하고 콘텐츠를 출력합니다. 분석 단계를 다시 실행하지 않습니다.
특별 고려사항
출력 형식
--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
위 명령어는 before 및 after 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: 입력 파일의 형식입니다. proto 및 textproto aquery 출력이 지원됩니다.
--attrs=(cmdline|inputs), default=cmdline: 비교할 작업의 속성입니다.
Aspect-on-Aspect
Aspect는 서로 위에 적용될 수 있습니다. 그러면 이러한 Aspect에서 생성된 작업의 aquery 출력에는 Aspect 경로가 포함됩니다. 이는 작업을 생성한 타겟에 적용된 Aspect의 시퀀스입니다.
Aspect-on-Aspect의 예는 다음과 같습니다.
t0 ^ | <- a1 t1 ^ | <- a2 t2
ti를 종속 항목에 Aspect 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=...)]
...
이는 작업 X가 a1(t0)에 적용된 Aspect a2에 의해 생성되었음을 의미합니다. 여기서 a1(t0)은 타겟 t0에 적용된 Aspect 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`가 정확히 동일한 별도의 작업으로 처리합니다.execPath 따라서
동일한 아티팩트가 중복되어 표시됩니다.
aquery 문제/계획된 기능 목록은 GitHub에서 확인할 수 있습니다.
FAQ
입력 파일의 콘텐츠가 변경되었지만 ActionKey는 동일하게 유지됩니다.
aquery의 컨텍스트에서 ActionKey는 String를 나타냅니다.
ActionAnalysisMetadata#getKey에서 가져온 것입니다.
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와 혼동해서는 안 됩니다.