cquery
는 select()
및 빌드 옵션이 빌드 그래프에 미치는 영향을 올바르게 처리하는 query
의 변형입니다.
이를 달성하기 위해 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의 유효한 프리픽스를 이해합니다.
전체 ID를 보려면 $ bazel config
를 실행하세요.
대상 패턴 평가
//foo
는 cquery
와 query
의 의미가 다릅니다. 이는 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
는 visible
, siblings
, buildfiles
, tests
를 제외한 모든 함수를 지원합니다.
cquery
에는 다음과 같은 새 함수도 도입되었습니다.
config
expr ::= config(expr, word)
config
연산자는 첫 번째 인수로 표시되는 라벨 및 두 번째 인수로 지정된 구성에 대해 구성된 대상을 찾으려고 시도합니다.
두 번째 인수의 유효한 값은 target
, host
, null
또는 커스텀 구성 해시입니다. 해시는 $
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_scopeitalicx:my_gen" | //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
는 메모리를 더 많이 사용하는 쿼리 가능한 그래프를 더 크게 만들기 때문에 이 측면을 따르지 않습니다. 이를 따르면 더 정확한 결과를 얻을 수 있습니다.
대규모 쿼리의 메모리 영향이 우려되는 경우 bazelrc에서 기본적으로 이 플래그를 사용 설정합니다.
측면을 사용 중지한 상태에서 쿼리하면 대상 Y를 빌드하는 동안 대상 X가 실패하는 문제가 발생할 수 있지만, cquery somepath(Y, X)
및 cquery deps(Y) | grep 'X'
는 종속 항목을 통해 발생하므로 결과를 반환하지 않습니다.
출력 형식
기본적으로 cquery 출력은 종속 항목 순서의 라벨 및 구성 쌍 목록을 생성합니다. 결과를 노출하는 다른 옵션도 있습니다.
전환
--transitions=lite --transitions=full
구성 전환은 최상위 타겟과 다른 구성의 최상위 타겟 아래에 타겟을 빌드하는 데 사용됩니다.
예를 들어 타겟은 tools
속성의 모든 종속 항목에 호스트 구성 전환을 적용할 수 있습니다. 이를 속성 전환이라고 합니다. 규칙은 자체 구성에 전환을 적용할 수도 있으며, 이를 규칙 클래스 전환이라고 합니다. 이 출력 형식은 유형 및 빌드 옵션에 미치는 영향 등 이러한 전환에 관한 정보를 출력합니다.
이 출력 형식은 기본적으로 NONE
로 설정되는 --transitions
플래그에 의해 트리거됩니다. FULL
또는 LITE
모드로 설정할 수 있습니다. FULL
모드는 전환 전후의 옵션을 자세히 설명하는 규칙 클래스 전환 및 속성 전환에 관한 정보를 출력합니다. LITE
모드는 옵션 차이 없이 동일한 정보를 출력합니다.
프로토콜 메시지 출력
--output=proto
이 옵션을 사용하면 결과 타겟이 바이너리 프로토콜 버퍼 형식으로 출력됩니다. 프로토콜 버퍼의 정의는 src/main/protobuf/analysis.proto에서 확인할 수 있습니다.
CqueryResult
는 cquery의 결과를 포함하는 최상위 메시지입니다. ConfiguredTarget
메시지 목록과 Configuration
메시지 목록을 포함합니다. 각 ConfiguredTarget
에는 configuration_id
에서 상응하는 Configuration
메시지의 id
필드 값과 동일한 값이 있습니다.
--[no]proto:include_configurations
기본적으로 cquery 결과는 구성된 각 대상의 일부로 구성 정보를 반환합니다. 이 정보를 생략하고 쿼리의 proto 출력과 정확히 같은 proto 출력을 가져오려면 이 플래그를 false로 설정하세요.
proto 출력 관련 옵션에 대한 자세한 내용은 쿼리의 proto 출력 문서를 참조하세요.
그래프 출력
--output=graph
이 옵션은 Graphviz와 호환되는 .dot 파일로 출력을 생성합니다. 자세한 내용은 query
의 그래프 출력 문서를 참고하세요. cquery
는 --graph:node_limit
및 --graph:factored
도 지원합니다.
파일 출력
--output=files
이 옵션은 bazel build
호출 끝에 인쇄된 목록과 유사한 쿼리로 일치하는 각 타겟에 의해 생성된 출력 파일 목록을 출력합니다. 출력에는 --output_groups
플래그에 따라 확인된 요청된 출력 그룹에 공지된 파일만 포함됩니다.
여기에는 소스 파일이 포함되지 않습니다.
Starlark를 사용하여 출력 형식 정의
--output=starlark
이 출력 형식은 쿼리 결과에서 구성된 각 대상의 Starlark 함수를 호출하고 호출에서 반환된 값을 출력합니다. --starlark:file
플래그는 단일 매개변수 target
를 사용하여 format
이라는 함수를 정의하는 Starlark 파일의 위치를 지정합니다. 이 함수는 쿼리 결과의 각 대상에 대해 호출됩니다. 편의상 --starlark:expr
플래그를 사용하여 def format(target): return expr
로 선언된 함수의 본문만 지정할 수도 있습니다.
'cquery' Starlark 언어
cquery Starlark 환경은 BUILD 또는 .bzl 파일과 다릅니다. 여기에는 모든 핵심 Starlark 기본 제공 상수 및 함수와 아래에 설명된 몇 가지 cquery 관련 상수가 포함되지만 glob
, native
또는 rule
는 포함되지 않으며 로드 문은 지원되지 않습니다.
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()])"
//bar
및 하위 패키지의 rule 대상에 의해 생성된 모든 파일의 경로를 공백으로 구분된 목록을 출력합니다.
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']"
각 대상의 라벨을 정확히 하나의 출력으로 인쇄합니다. 이 예에서는 파일에 정의된 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와 검색어
cquery
와 query
는 서로를 보완하며 다양한 틈새 시장에서 두드러집니다. 다음 중에서 무엇이 적합할지 결정하세요.
cquery
는 특정select()
브랜치를 따라 빌드한 정확한 그래프를 모델링합니다.query
는 빌드가 어떤 브랜치를 선택하는지 알 수 없으므로 브랜치를 모두 포함하여 포함합니다.cquery
의 정밀도는query
보다 더 많은 그래프를 빌드해야 합니다. 특히cquery
는 구성된 대상을 평가하고query
는 대상만 평가합니다. 이 옵션은 시간이 더 많이 걸리고 메모리를 더 많이 사용합니다.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=<whatever>
를 추가합니다.
문제 해결
재귀 대상 패턴 (/...
)
다음에 해당하는 경우:
$ 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.
이는 --universe_scope=//foo:app
패키지가 포함되어 있더라도 //foo
패키지가 범위에 속하지 않음을 잘못 나타냅니다. 이는 cquery
의 디자인 제한 때문입니다. 이 문제를 해결하려면 //foo/...
를 명시적으로 범위 범위에 포함하세요.
$ 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 "+" -))"