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)
每筆結果都包含一個專屬 ID (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
的設定中建構。大多數
此為不透明的雜湊值,定義
此外還會從 0 自動調整資源配置
您完全不必調整資源調度設定
如要查看設定的完整內容,請執行:
$ bazel config 9f87702
主機設定會使用特殊 ID (HOST)
。非產生的來源檔案,例如
srcs
中常見的這些變數,請使用特殊 ID (null)
(因為
不需要設定)。
9f87702
是完整 ID 的前置字串。這是因為完整的 ID
SHA-256 雜湊,這類很冗長且難以追蹤。cquery
瞭解
開頭,例如
Git 短雜湊。
如要查看完整 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
則支援除了
allrdeps
,
buildfiles
,
rbuildfiles
,
siblings
、
tests
和
visible
。
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", )
Genrules 會在 主機設定 因此,下列查詢會產生下列輸出內容:
查詢 | 已建構的目標 | 輸出 |
---|---|---|
bazel cquery "//x:tool" | //x:tool | //x:tool(targetconfig) |
bazel cquery "//x:tool"--universe_scope="//x:my_gen" | //x:my_gen | //x:tool(hostconfig) |
如果設定此標記,則會建構其內容。如未設定,所有指定
系統會改為建構解除
會使用建構的目標做為查詢的宇宙。無論您選擇哪種方式,目標
必須能在頂層建構元件 (也就是與頂層元件相容)
選項)。cquery
會傳回這些項目的遞移性關閉結果
頂層指定目標
即使可以建立所有目標在頂端的查詢運算式中
否則可能會有所助益。例如,如果您明確設定
--universe_scope
可防止多次建立目標:
載入 Google Cloud 的某些設定這項工具也能協助您
才能觸及理想目標對象 (因為目前不支援
就可以以任何其他方式完全指定此設定)。建議您設定這個標記
和 deps(//foo)
相比,
--implicit_deps
(布林值,default=True)
將此旗標設為 false,會濾除未在 中明確設定的所有結果 並由 Bazel 在其他位置設定。這包含已解決的篩選問題 工具鍊。
--tool_deps
(布林值,default=True)
將此標記設為 false 會過濾掉已設定的所有目標,
從查詢目標到他們之間穿越目標的轉換路徑
系統產生的設定
非目標設定:
如果查詢的目標屬於目標設定,則設定 --notool_deps
會
只會傳回同時包含目標設定中的目標。如果查詢原因
目標設定在非目標設定中,設定 --notool_deps
只會傳回
也在非目標設定中調整目標這項設定通常不會影響篩選功能
已解決的工具鍊
--include_aspects
(布林值,default=True)
切面可
額外增加依附元件根據預設,cquery
不會追蹤切面,原因如下:
會使可查詢的圖表變大,而耗用更多記憶體。但追蹤這些數字會產生
準確的結果
如果您不必擔心大型查詢對記憶體的影響,請在 你的 bazelrc
如果查詢的切面遭到停用,您可能會遇到指定目標 X 失敗的問題
建構目標 Y,但 cquery somepath(Y, X)
和 cquery deps(Y) | grep 'X'
未傳回任何結果,因為依附元件是透過切面發生。
輸出格式
根據預設,cquery 輸出會產生依依附元件排序的標籤和設定組合清單。 您也可以透過其他選項查看結果。
轉場
--transitions=lite --transitions=full
設定轉換 會在不同的頂層目標底下 而非頂層目標
舉例來說,目標可能會強制將
tools
屬性中的依附元件。這些稱為「屬性」
轉場效果規則也可以自行設定轉換作業、
稱為規則類別轉換這個輸出格式會輸出
例如轉換類型和對建構的影響
只要設定成「自動重新啟動」
和「在主機維護期間」選項即可
這個輸出格式是由 --transitions
旗標觸發,根據預設,
已設為 NONE
。可設為 FULL
或 LITE
模式。FULL
模式輸出內容
規則類別轉換和屬性轉換的資訊,包括
轉換前後的選項差異LITE
種交通方式
輸出的資訊相同,但沒有選項差異。
通訊協定訊息輸出
--output=proto
這個選項會使產生的目標以二進位通訊協定列印 緩衝區格式。如需瞭解通訊協定緩衝區的定義,請前往 src/main/protobuf/analysis.proto.
CqueryResult
是包含 cquery 結果的頂層訊息。這項服務
含有 ConfiguredTarget
訊息清單和 Configuration
清單
訊息。每個 ConfiguredTarget
都有一個值相等的 configuration_id
至id
對應Configuration
訊息中的欄位。
--[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
旗標會指定
Starlark 檔案,以單一參數定義名為 format
的函式。
target
。系統會為每個目標呼叫這個函式
結果。或者,為了方便起見,您可以
的函式主體,方法是使用def format(target): return expr
--starlark:expr
標記。
「cquery」Starlark 方言
cquery Starlark 環境與 BUILD 或 .bzl 檔案不同。包括
所有核心 Starlark
內建常數和函式
加上下方說明的幾個查詢相關變數,但不包括 (例如) glob
。
native
或 rule
,而且不支援載入陳述式。
build_options(target)
build_options(target)
會傳回其鍵為建構選項 ID 的地圖 (請參閱
設定)
以及其值是 Starlark 值值並非法定的 Starlark 版本選項
系統會忽略此地圖中的值。
如果目標為輸入檔案,build_options(target)
會傳回 None,做為輸入檔案
目標則為空值
供應商(目標)
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']"
顯示只有一個輸出內容的目標標籤。本範例使用 檔案中定義的 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"
存在於兩種設定中,而 「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
不會自動從建構圖表中抹除建構圖表
因此容易擷取過去的結果
舉個簡單的例子,您可以定義情境
並指示 AI 如何回應服務中心查詢舉例來說,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.
這可能誤表示套件 //foo
不在範圍內
--universe_scope=//foo:app
包含的項目。這是因為
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 "+" -))"