Bazel 查詢參考資料

回報問題 查看原始碼

本頁是您透過 bazel query 分析建構依附元件時使用的 Bazel Query Language 參考手冊。以及 bazel query 支援的輸出格式。

如需實際用途,請參閱 Bazel 查詢教學

其他查詢參考資料

除了 query 會在載入後階段目標圖形上執行,Bazel 還包含「動作圖查詢」和「可設定的查詢」

動作圖表查詢

動作圖表查詢 (aquery) 會在分析後的目標圖表上運作,並顯示動作成果及其關係的相關資訊。如果您想瞭解透過已設定的目標圖表產生的動作/構件屬性,aquery 就非常實用。例如,實際指令執行及其輸入、輸出內容和記憶。

詳情請參閱查詢參考資料

可設定的查詢

傳統的 Bazel 查詢會在載入後階段目標圖上執行,因此沒有設定的概念和相關概念。值得注意的是,系統不會正確解析特定陳述式,而是傳回所有可能的選取解析度。不過,可設定查詢環境 cquery 可正確處理設定,但並未提供這個原始查詢的所有功能。

詳情請參閱 cquery 參考資料

示例

使用者如何使用bazel query?常見的例子如下:

為什麼 //foo 樹狀結構依附於 //bar/baz?顯示路徑:

somepath(foo/..., //bar/baz:all)

所有 foo 測試依附於 foo_bin 目標不包括的 C++ 程式庫有哪些?

kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo:foo_bin))

符記:詞法語法

查詢語言中的運算式由下列符記組成:

  • 關鍵字,例如 let。關鍵字是該語言的保留字詞,以下說明每個字詞。完整的關鍵字組合如下:

  • 字詞,例如「foo/...」或「.*test rule」或「//bar/baz:all」。如果字元序列是「引用」(以單引號開頭和結尾為單引號,或以雙引號「"」結尾),則它就是字詞。未加上引號的字元序列仍可將其剖析為字詞。未加引號的字詞是從 A 到 Z 字母字元、數字 0 到 9 和特殊字元 */@.-_:$~[] 組成的序列,這些字元包括星號、正斜線、 at、句號、連字號、底線、冒號、美元符號、波浪號、左方括號、右正方形。不過,未加引號的字詞不得以連字號 - 或星號 * 開頭,即使相對目標名稱可能會以這些字元開頭。

    未加引號的字詞也不得包含半形字元,或是等號 + 或等號 =,即使目標名稱允許使用字元也一樣。編寫會產生查詢運算式的程式碼時,目標名稱應加上引號。

    如要編寫根據使用者提供的值建構 Bazel 查詢運算式的指令碼,則「需要」查詢。

     //foo:bar+wiz    # WRONG: scanned as //foo:bar + wiz.
     //foo:bar=wiz    # WRONG: scanned as //foo:bar = wiz.
     "//foo:bar+wiz"  # OK.
     "//foo:bar=wiz"  # OK.
    

    請注意,此引述並非殼層要求的任何引用內容,例如:

    bazel query ' "//foo:bar=wiz" '   # single-quotes for shell, double-quotes for Bazel.
    

    系統會將關鍵字和運算子分別視為一般字詞,舉例來說,some 是關鍵字,但「some」是字詞。foo 和「foo」都是字詞。

    但是,在目標名稱中使用單引號或雙引號時,請小心。引用一或多個目標名稱時,請只使用一種類型的引號 (全部或所有雙引號)。

    以下是 Java 查詢字串的範例:

      'a"'a'         # WRONG: Error message: unclosed quotation.
      "a'"a"         # WRONG: Error message: unclosed quotation.
      '"a" + 'a''    # WRONG: Error message: unexpected token 'a' after query expression '"a" + '
      "'a' + "a""    # WRONG: Error message: unexpected token 'a' after query expression ''a' + '
      "a'a"          # OK.
      'a"a'          # OK.
      '"a" + "a"'    # OK
      "'a' + 'a'"    # OK
    

    我們選擇此語法,是為了在大多數情況下不需要使用引號。(非典型) ".*test rule" 範例需要引號:以半形句號開頭且包含空格。輪詢 "cc_library" 並非必要,但也無害。

  • 標點符號,例如括號 ()、句號 . 和半形逗號 ,。含有標點符號的字詞 (上方列出的例外情況除外) 必須加上引號。

系統會忽略引用字詞以外的空白字元。

Bazel 查詢語言概念

Bazel 查詢語言就是運算式的語言。每個運算式都會評估一組目標的「部分排序」,或等同於目標的「圖形」 (DAG)。這是唯一的資料類型。

設定和圖表參照相同的資料類型,但強調這些資料的不同層面,例如:

  • 設定:指定目標的部分順序不有趣。
  • 圖表:目標的部分順序非常高。

相依關係圖中的週期

建構依附元件圖表應為非循環圖。

查詢語言使用的演算法僅供用於循環圖使用,但有助於防範循環。有關週期處理方式的詳細資料沒有指定,亦不應仰賴。

隱含依附元件

除了在 BUILD 檔案中明確定義的建構依附元件外,Bazel 也會將額外的「隱含」依附元件新增至規則。隱含依附元件可以用以下方式定義:

根據預設,bazel query 在計算查詢結果時,會將隱含依附元件納入考量。您可以使用 --[no]implicit_deps 選項變更這個行為。

請注意,由於查詢不會考量設定,因此潛在的工具鍊實作並非依附元件,只會視為必要的工具鍊類型。請參閱工具鍊說明文件

音質

Bazel 查詢語言運算式透過建構依附元件圖表運作,這是由所有 BUILD 檔案中所有規則宣告隱含定義的圖表。請務必瞭解,這張圖表略為抽象,不構成如何執行建構所有步驟的完整說明。如要執行建構,也必須提供設定,詳情請參閱使用者指南的設定一節。

針對「所有設定」,在 Bazel 查詢語言中評估運算式的結果為 true,這代表該運算式可能是保守的近似值,而非精確。如果您使用查詢工具來計算建構期間所需的所有來源檔案集,則可能會回報需要更多必要檔案,因為舉例來說,查詢工具會包含支援訊息翻譯所需的所有檔案,即使您並不打算在建構作業中使用該功能。

保存圖表順序

作業會保留從其子運算式繼承的所有排序限制。這就像是「部分命令的保護法」。請設想一個範例:如果您發出查詢,用於判斷特定目標的依附元件轉換關閉,結果集會根據依附元件圖表排序。如果將篩選器設為只包含 file 種類的目標,則在產生的子集中,每對目標組合之間仍會使用相同的遞移部分排序關係保留,即使原始圖形中沒有任何這些組合實際上是直接連結也一樣。(建構依附元件圖中沒有檔案檔案邊緣)。

不過,雖然所有運算子都會「保留」順序,但某些作業 (例如設定作業) 不會「導入」自身的任何排序限制。請考慮以下運算式:

deps(x) union y

最終結果集的順序保證會保留其子運算式的所有排序限制,換句話說,x 的所有遞移依附元件都會依彼此正確排序。然而,查詢無法保證 y 中的目標排序,也無法保證 deps(x) 中的目標排序 (相對於 y 中的目標順序除外),但 y 中的目標也會出現在 deps(x) 中。

引進排序限制的運算子包括:allpathsdepsrdepssomepath,以及目標模式萬用字元 package:*dir/... 等。

天空查詢

Sky Query 是一種查詢模式,會針對特定範圍執行。

特殊函式僅適用於 SkyQuery

天空查詢模式具有額外的查詢函式 allrdepsrbuildfiles。這些函式適用於整個宇宙範圍,因此不適合一般查詢使用。

指定宇宙範圍

透過傳遞下列兩個標記 (--universe_scope--infer_universe_scope) 和 --order_output=no 來啟用天空查詢模式。--universe_scope=<target_pattern1>,...,<target_patternN> 會指示查詢針對目標模式指定的目標模式轉換閉包,不論是加法還是減法都沒問題。然後在這個「範圍」中評估所有查詢。具體來說,allrdepsrbuildfiles 運算子只會傳回這個範圍的結果。--infer_universe_scope 會指示 Bazel 從查詢運算式推論出 --universe_scope 的值。這個推論值是查詢運算式中的不重複目標模式清單,但這可能不是您想要的結果。例如:

bazel query --infer_universe_scope --order_output=no "allrdeps(//my:target)"

這個查詢運算式中的不重複目標模式清單為 ["//my:target"],因此 Bazel 會將此項目視為叫用:

bazel query --universe_scope=//my:target --order_output=no "allrdeps(//my:target)"

不過,使用 --universe_scope 的查詢結果只會是 //my:target;透過建構,//my:target 的反向依附元件不在宇宙中!另一方面,請考慮以下事項:

bazel query --infer_universe_scope --order_output=no "tests(//a/... + b/...) intersect allrdeps(siblings(rbuildfiles(my/starlark/file.bzl)))"

這是有意義的查詢叫用,目的是在部分目錄的 tests 擴充中計算測試目標,這類目錄會連帶依附定義使用特定 .bzl 檔案的目標。這裡使用 --infer_universe_scope 是方便的做法,特別是在選擇 --universe_scope 時需要自行剖析查詢運算式的情況下。

因此,如果查詢運算式使用 allrdepsrbuildfiles 等世界範圍運算子,請務必只在其行為符合需求的情況下,才使用 --infer_universe_scope

與預設查詢相比,Sky Query 具備一些優點和缺點。主要缺點是無法依據圖形順序排列輸出內容,因此禁止特定輸出格式。這種策略可提供預設查詢未提供的兩種運算子 (allrdepsrbuildfiles)。同樣,Sky Query 的運作方式是引入 Skyframe 圖表,而不是建立新圖表 (這是預設實作的功能)。因此在某些情況下,速度較快,記憶體用量也較少。

運算式:文法的語法和語意

以下是 Bazel 查詢語言的文法,以 EBNF 標記法表示:

expr ::= word
       | let name = expr in expr
       | (expr)
       | expr intersect expr
       | expr ^ expr
       | expr union expr
       | expr + expr
       | expr except expr
       | expr - expr
       | set(word *)
       | word '(' int | word | expr ... ')'

以下各節會依序說明這個文法的各個製作項目。

目標模式

expr ::= word

就語法而言,目標模式只是一個字詞。被解讀為一組 (未排序) 目標。最簡單的目標模式是識別單一目標 (檔案或規則) 的標籤。例如,目標模式 //foo:bar 會評估為包含一個元素的集合,也就是目標 bar 規則。

目標模式會將標籤一般化,納入套件和目標上的萬用字元。舉例來說,foo/...:all (或僅限 foo/...) 目標模式會評估為包含 foo 目錄下每個套件中所有規則的集合;bar/baz:all 是目標模式,評估為包含 bar/baz 套件中的所有規則,但不包含其子套件的集合。

同樣地,foo/...:* 是一種目標模式,會評估成一個組合,其中包含 foo 目錄底下每個套件中所有「目標」 (規則「和」檔案);bar/baz:* 會評估一個組合,內含 bar/baz 套件中的所有目標,但不包含其子套件。

:* 萬用字元會比對檔案和規則,因此通常比 :all 查詢更實用。反之,:all 萬用字元 (隱含在 foo/... 等目標模式中) 在建構方面通常更實用。

bazel query 目標模式的運作方式與 bazel build 建構目標相同。詳情請參閱目標模式bazel help target-syntax 類型。

如果目標模式不符合任何目標,目標模式可能會評估為包含許多元素的單例模式集 (例如在 foo/... 的情況下,這當中會有數千個元素) 或空白組合。

目標模式運算式結果中的所有節點會根據依附元件關係,正確排列每個節點的相對順序。因此,foo:* 的結果不僅是 foo 套件中的目標組合,也會涵蓋這些目標的圖表。(無法保證結果節點與其他節點的相對排序)。詳情請參閱圖表順序一節。

變數

expr ::= let name = expr1 in expr2
       | $name

Bazel 查詢語言可讓您定義和參照變數。let 運算式的評估結果與 expr2 相同,而且所有出現的變數 name 會以 expr1 的值取代。

例如,let v = foo/... in allpaths($v, //common) intersect $v 等同於 allpaths(foo/...,//common) intersect foo/...

如果變數參照 name 發生在內含的 let name = ... 運算式以外的其他變數,就會發生錯誤。換句話說,頂層查詢運算式不能有免費變數。

在上述文法產生中,nameword 類似,但具有額外限制,它是 C 程式設計語言中的法律 ID。變數參照的前面必須加上「$」字元。

每個 let 運算式都只定義單一變數,但您可以建立巢狀結構。

目標模式和變數參照都僅由單一符記 (字詞) 組成,可能會造成語法模糊不清。不過,由於合法變數名稱的字詞中的子集與合法目標模式的字詞不同,因此沒有語意模糊不清。

就技術上來說,let 運算式不會提高查詢語言的表達能力,也就是說,任何以語言表達的查詢都可以表示不需要該語言。不過,這類查詢可以提升許多查詢的簡潔性,或許也能提升查詢評估的效率。

將運算式置於括號

expr ::= (expr)

括號的作用是與子運算式建立關聯,藉此強制執行評估順序。括號括住的運算式會評估其引數的值。

代數集合運算:交集、聯集、設定差異

expr ::= expr intersect expr
       | expr ^ expr
       | expr union expr
       | expr + expr
       | expr except expr
       | expr - expr

這三個運算子會計算其引數的一般集合運算。每個運算子都有兩種形式:名詞形式 (例如 intersect) 和符號形式 (例如 ^)。這兩種形式相等,符號形式的輸入速度也更快。(為求明確,本頁的其他內容會使用名詞形式)。

比如

foo/... except foo/bar/...

計算結果是符合 foo/... 但不含 foo/bar/... 的一組目標。

編寫相同的查詢即可:

foo/... - foo/bar/...

intersect (^) 和 union (+) 作業是可交換 (對稱);except (-) 是不對稱。剖析器會將這三個運算子都視為左關聯且優先順序相等,因此您可能需要使用括號。例如,前兩個運算式的效果相同,但第三個不是:

x intersect y union z
(x intersect y) union z
x intersect (y union z)

從外部來源讀取目標:已設定

expr ::= set(word *)

set(a b c ...) 運算子會計算一組零或多個「目標模式」的聯集,這些聯集以空白字元 (無逗號) 分隔。

結合 Bourne shell 的 $(...) 功能,set()可將一項查詢結果儲存在一般文字檔中,使用其他程式 (例如標準 UNIX 殼層工具) 操控該文字檔案,然後將結果傳回查詢工具,做為進一步處理的值。例如:

bazel query deps(//my:target) --output=label | grep ... | sed ... | awk ... > foo
bazel query "kind(cc_binary, set($(<foo)))"

在下一個範例中,kind(cc_library, deps(//some_dir/foo:main, 5)) 是使用 awk 程式篩選 maxrank 值來進行運算。

bazel query 'deps(//some_dir/foo:main)' --output maxrank | awk '($1 < 5) { print $2;} ' > foo
bazel query "kind(cc_library, set($(<foo)))"

在這些範例中,$(<foo)$(cat foo) 的簡寫,但也可能使用 cat 以外的殼層指令,例如先前的 awk 指令。

函式

expr ::= word '(' int | word | expr ... ')'

查詢語言定義了多個函式。而函式的名稱會決定其需要的引數數量和類型。以下為可用的函式:

依附元件的遞移封閉:依附元件

expr ::= deps(expr)
       | deps(expr, depth)

deps(x) 運算子會評估圖形 (因其引數集 x 的依附元件轉換性閉合而形成)。例如,deps(//foo) 的值是位於單一節點 foo 的依附元件圖表,包括其所有依附元件。deps(foo/...) 的值是依附元件圖表,其根層級為 foo 目錄下每個套件中的所有規則。在這種情況下,「依附元件」意味著規則和檔案目標,因此建立這些目標所需的 BUILD 和 Starlark 檔案不包含在此處。為此,請使用 buildfiles 運算子。

結果圖表會根據相依性關係排序。詳情請參閱「圖表順序」一節。

deps 運算子可接受選用的第二個引數,這是指定搜尋深度上限的整數常值。因此,deps(foo:*, 0) 會傳回 foo 套件中的所有目標,而 deps(foo:*, 1) 進一步包含 foo 套件中任何目標的直接必要條件,deps(foo:*, 2) 則進一步包含直接從 deps(foo:*, 1) 中節點連接的節點,依此類推。(這些數字與 minrank 輸出格式中的排名相對應)。如果省略 depth 參數,搜尋就不會受限:系統會計算先進的彈性遞迴關閉。

反向依附元件的遞移性閉包:要素

expr ::= rdeps(expr, expr)
       | rdeps(expr, expr, depth)

rdeps(u, x) 運算子會評估引數集 x 的反向依附元件 (位於宇宙集 u 的遞移封閉中)。

結果圖表會根據相依性關係排序。詳情請參閱圖表順序一節。

rdeps 運算子可接受選用的第三個引數,這是指定搜尋深度上限的整數常值。結果圖表只會包含與引數集內任何節點相距指定深度距離內的節點。因此rdeps(//foo, //common, 1) 會評估直接依附於 //foo 轉換性閉包的所有節點//common。(這些數字與 minrank 輸出格式中的排名相對應)。如果省略 depth 參數,搜尋就不受限制。

所有反向依附元件的過渡性閉合:Allrdeps

expr ::= allrdeps(expr)
       | allrdeps(expr, depth)

allrdeps 運算子的運作方式與 rdeps 運算子類似,但「宇宙集」是評估的任意 --universe_scope 旗標,而非另外指定。因此,如果傳遞了 --universe_scope=//foo/...,則 allrdeps(//bar) 等同於 rdeps(//foo/..., //bar)

同一個套件中的直接反向依附元件:same_pkg_direct_rdeps

expr ::= same_pkg_direct_rdeps(expr)

same_pkg_direct_rdeps(x) 運算子會評估位於相同套件中的一組目標,這些目標與引數集內的目標位於同一套件中,且直接相依。

處理目標套件:同層級

expr ::= siblings(expr)

siblings(x) 運算子會評估與引數集目標位於相同套件中的一組目標。

任意選擇:部分

expr ::= some(expr)
       | some(expr, count )

some(x, k) 運算子會從其引數集 x 任意選取 k 目標,並評估為只包含這些目標的集合。參數 k 為選用項目。如未提供,結果會是單例模式組合,其中僅含任意一個目標。如果引數集 x 的大小小於 k,會傳回整個引數集 x

例如,運算式 some(//foo:main union //bar:baz) 會評估為包含 //foo:main//bar:baz 的單例集,但您並未定義該集合。運算式 some(//foo:main union //bar:baz, 2)some(//foo:main union //bar:baz, 3) 會同時傳回 //foo:main//bar:baz

如果引數是單例模式,some 會計算識別函式:some(//foo:main) 等於 //foo:main

如果指定的引數集為空白 (與運算式 some(//foo:main intersect //bar:baz) 相同),就會發生錯誤。

路徑運算子:somepath、allpaths

expr ::= somepath(expr, expr)
       | allpaths(expr, expr)

somepath(S, E)allpaths(S, E) 運算子會計算兩組目標之間的路徑。這兩個查詢都接受兩個引數:一組起點的 S,以及一組終點的 Esomepath 會將「部分」任意路徑的節點圖表從 S 中的目標傳回到 E 中的目標;allpaths 會將 S 中任何目標的所有路徑上節點的圖形傳回至 E 中的任何目標。

產生的圖表會根據依附元件關係排序。詳情請參閱「圖表順序」一節。

一點小路
somepath(S1 + S2, E),一個可能的結果。
一點小路
somepath(S1 + S2, E),這是另一個可能的結果。
所有路徑
allpaths(S1 + S2, E)

目標種類篩選:Kind

expr ::= kind(word, expr)

kind(pattern, input) 運算子會對一組目標套用篩選器,並捨棄不屬於預期種類的目標。pattern 參數會指定要比對的目標類型。

舉例來說,BUILD 檔案 (適用於套件 p) 定義的四個目標種類,如下表所示:

程式碼 目標 種類
        genrule(
            name = "a",
            srcs = ["a.in"],
            outs = ["a.out"],
            cmd = "...",
        )
      
//p:a Genrule 規則
//p:a.in 來源檔案
//p:a.out 已產生的檔案
//p:BUILD 來源檔案

因此,kind("cc_.* rule", foo/...) 會評估 foo 底下的所有 cc_librarycc_binary 等規則目標,而 kind("source file", deps(//foo)) 會評估 //foo 目標依附元件連帶關閉中的所有來源檔案集。

pattern 引數經常需要引號,因為如果沒有該引數,許多規則運算式 (例如 source file.*_test) 不會被剖析器視為字詞。

比對 package group 時,結尾為 :all 的目標可能無法產生任何結果。請改用 :all-targets

目標名稱篩選:篩選器

expr ::= filter(word, expr)

filter(pattern, input) 運算子會為一組目標套用篩選器,並捨棄標籤 (絕對格式) 不符合模式的目標;這個運算子會評估其輸入的子集。

第一個引數 pattern 是包含針對目標名稱使用規則運算式的字詞。filter 運算式會評估包含所有目標的組合,確保 x 是集合 input 的成員,而 x 的標籤 (例如 //foo:bar 等絕對格式) 包含與規則運算式 pattern 相符的 (非錨定) 相符項目。x由於所有目標名稱的開頭都是 //,因此可用做 ^ 規則運算式錨點的替代方案。

這個運算子通常會為 intersect 運算子提供更快速、更可靠的替代方案。舉例來說,如要查看 //foo:foo 目標的所有 bar 依附元件,您可以評估依附元件

deps(//foo) intersect //bar/...

不過,這個陳述式必須剖析 bar 樹狀結構中的所有 BUILD 檔案,速度較慢,且容易在不相關的 BUILD 檔案中發生錯誤。替代結果如下:

filter(//bar, deps(//foo))

此方法會先計算 //foo 依附元件組合,然後只篩選符合所提供模式的目標,也就是篩選出名稱含有 //bar 做為子字串的目標。

filter(pattern, expr) 運算子的另一個常見用途是按照名稱或副檔名篩選特定檔案。比如

filter("\.cc$", deps(//foo))

會提供一份清單,列出用於建構 //foo 的所有 .cc 檔案。

規則屬性篩選: attr

expr ::= attr(word, word, expr)

attr(name, pattern, input) 運算子會對一組目標套用篩選條件,並捨棄不屬於規則的目標、未定義 name 屬性的規則目標,或是屬性值與提供的規則運算式 pattern 不符的規則目標,並評估其輸入的子集。

第一個引數 name 是應與提供的規則運算式模式相符的規則屬性名稱。第二個引數 pattern 是對應屬性值的規則運算式。attr 運算式會評估包含所有目標 x 的集合,確保 x 是集合 input 的成員、具有已定義屬性 name 的規則,且屬性值包含與規則運算式 pattern 相符的 (非錨定) 相符項目。如果 name 是選用屬性,且規則未明確指定,系統會使用預設屬性值進行比較。比如

attr(linkshared, 0, deps(//foo))

將會選取可擁有連結共用屬性 (例如 cc_binary 規則) 的所有 //foo 依附元件,並明確設為 0 或完全不設定,但預設值為 0 (例如 cc_binary 規則)。

清單類型屬性 (例如 srcsdata 等) 會轉換為 [value<sub>1</sub>, ..., value<sub>n</sub>] 格式的字串,開頭為 [ 括號、結尾為 ] 括號,並使用「,」(半形逗號、空格) 分隔多個值。系統會使用標籤的絕對格式將標籤轉換為字串。舉例來說,deps=[":foo", "//otherpkg:bar", "wiz"] 屬性會轉換為 [//thispkg:foo, //otherpkg:bar, //thispkg:wiz] 字串。括號一律存在,因此空白清單會使用字串值 [] 進行比對。比如

attr("srcs", "\[\]", deps(//foo))

將選取 srcs 屬性空白的 //foo 依附元件中的所有規則,

attr("data", ".{3,}", deps(//foo))

系統將從 //foo 依附元件中選取所有在 data 屬性中指定至少一個值的規則 (每個標籤可能因為 //:,長度至少為 3 個字元)。

如要在清單類型屬性中,選取具有特定 value//foo 依附元件中的所有規則,請使用

attr("tags", "[\[ ]value[,\]]", deps(//foo))

這是因為 value 之前的字元是 [ 或空格,value 之後的字元則是半形逗號或 ]

規則瀏覽權限篩選:可見

expr ::= visible(expr, expr)

visible(predicate, input) 運算子會對一組目標套用篩選器,並在沒有必要瀏覽權限的情況下捨棄目標。

第一個引數 predicate 是一組目標,輸出中的所有目標都必須可見。visible 運算式會評估包含所有目標 x 的集合,確保 x 是集合 input 的成員,predicate x 中的所有目標 y 都可以查看。y例如:

visible(//foo, //bar:*)

系統會在 //bar 套件中選取 //foo 可依附的所有目標,而不違反瀏覽權限限制。

以下類型規則屬性的評估:標籤

expr ::= labels(word, expr)

labels(attr_name, inputs) 運算子會在部分已設定的 inputs 規則中,傳回類型為「label」或「標籤清單」屬性 attr_name 中指定的目標組合。

舉例來說,labels(srcs, //foo) 會傳回 //foo 規則 srcs 屬性中的目標組合。如果 inputs 設定中有多個包含 srcs 屬性的規則,系統會傳回其 srcs 的聯集。

展開及篩選 test_suite:測試

expr ::= tests(expr)

tests(x) 運算子會傳回 x 集中的所有測試規則組合、將任何 test_suite 規則擴充至其參照的個別測試組合,並依 tagsize 套用篩選條件。

根據預設,查詢評估作業會忽略所有 test_suite 規則中的任何非測試目標。您可以使用 --strict_test_suite 選項,變更為錯誤。

舉例來說,查詢 kind(test, foo:*) 會列出 foo 套件中的所有 *_testtest_suite 規則。所有結果都是 foo 套件的成員 (依定義)。相反地,查詢 tests(foo:*) 會傳回 bazel test foo:* 執行的所有個別測試:這可能包含屬於其他套件的測試,這些測試可透過 test_suite 規則直接或間接參照。

套件定義檔案:buildfiles

expr ::= buildfiles(expr)

buildfiles(x) 運算子會傳回一組檔案,用於在 x 中設定定義每個目標的套件;換句話說,每個套件及其 BUILD 檔案,以及透過 load 參照的任何 .bzl 檔案。請注意,這樣也會傳回包含這些 load 檔案的套件的 BUILD 檔案。

這個運算子通常用於判斷建構指定目標所需的檔案或套件時,通常會與下方的 --output package 選項搭配使用。比如

bazel query 'buildfiles(deps(//foo))' --output package

會傳回 //foo 連帶依附的所有套件組合。

套件定義檔案:rbuildfiles

expr ::= rbuildfiles(word, ...)

rbuildfiles 運算子會取得以半形逗號分隔的路徑片段清單,並傳回一組 BUILD 檔案,此檔案間接依附這些路徑片段。舉例來說,如果 //foo 是套件,則 rbuildfiles(foo/BUILD) 會傳回 //foo:BUILD 目標。如果 foo/BUILD 檔案中的 load('//bar:file.bzl'...rbuildfiles(bar/file.bzl) 會傳回 //foo:BUILD 目標,以及其他載入 //bar:file.bzlBUILD 檔案的目標

rbuildfiles 運算子的範圍是 --universe_scope 旗標指定的宇宙。沒有直接對應至 BUILD 檔案和 .bzl 檔案的檔案不會影響結果。舉例來說,即使 BUILD 檔案明確提及來源檔案 (例如 foo.cc),系統也會予以忽略。不過,系統會遵循符號連結,因此如果 foo/BUILDbar/BUILD 的符號連結,則 rbuildfiles(bar/BUILD) 會在結果中加入 //foo:BUILD

rbuildfiles 運算子幾乎是與 buildfiles 運算子的相反。不過,這種道式反轉朝一個方向更強:rbuildfiles 的輸出與 buildfiles 的輸入類似;前者只會包含套件中的 BUILD 檔案目標,後者可能包含這類目標。反過來則通訊強度較低。buildfiles 運算子的輸出內容是對應至所有套件和 .bzl 檔案。不過,rbuildfiles 運算子的輸入內容不是這些目標,而是與這些目標對應的路徑片段。

套件定義檔:loadfiles

expr ::= loadfiles(expr)

loadfiles(x) 運算子會傳回一組 Starlark 檔案,在 x 集中載入每個目標的套件。也就是說,每個套件都會傳回從 BUILD 檔案參照的 .bzl 檔案。

輸出格式

bazel query 會產生圖表。您可以使用 --output 指令列選項,指定 bazel query 顯示這張圖表的內容、格式和順序。

搭配 Sky Query 執行時,只能使用與未排序的輸出內容相容的輸出格式。具體來說,我們不允許 graphminrankmaxrank 輸出格式。

部分輸出格式接受其他選項。每個輸出選項的名稱都會以適用的輸出格式前置字串,因此 --graph:factored 僅適用於使用 --output=graph 的情況;如果使用 graph 以外的輸出格式則不會產生任何影響。同樣地,只有在使用 --output=xml 時才適用 --xml:line_numbers

按結果排序

雖然查詢運算式一律遵循「圖表順序守則」的規定,但呈現結果可能會以依附元件排序或未排序的方式完成。這不會影響結果集中的目標或查詢運算方式。這只會影響 stdout 的輸出結果。此外,在依附元件順序中對等的節點不一定會按照字母順序排列。--order_output 標記可用來控制這個行為。(--[no]order_results 旗標具有 --order_output 旗標的部分功能,且已淘汰)。

此標記的預設值是 auto,會以字母順序顯示結果。不過,使用 somepath(a,b) 時,結果會改以 deps 順序列印。

如果此旗標為 no,且 --outputbuildlabellabel_kindlocationpackageprotoxml 其中之一,則會以任意順序顯示輸出內容。這通常是最快的選項。不過,如果 --outputgraphminrankmaxrank 的其中一種格式,則不支援這項操作:如果使用這些格式,Bazel 一律會以依附元件順序或排名排序結果。

當這個標記為 deps 時,Bazel 會以某種方式排序結果,也就是後續順序取決於優先度和依附元件。不過,未依依附元件順序排序的節點 (因為其中一個節點之間沒有路徑) 可能會按任何順序列印。

當這個標記為 full 時,Bazel 會以完全確定 (總計) 的順序輸出節點。首先,所有節點都按照字母順序排列。接著,清單中的每個節點都會做為在順序深度優先搜尋開始時使用,且按次序節點的外送邊緣到尚未造訪的節點之間會進行遍歷順序的掃遍。最後,節點會按照造訪的順序列印。

按照這個順序列印節點可能速度較慢,因此只有在確定性非常重要時,才使用此選項。

列印目標來源形式,如 BUILD 中顯示的

--output build

使用這個選項時,每個目標的表示法就像是使用 BUILD 語言手動編寫一樣。所有變數和函式呼叫 (例如 glob、巨集) 皆已展開,方便您查看 Starlark 巨集的效果。此外,每個有效的規則都會回報 generator_name 和/或 generator_function) 值,提供經評估可產生有效規則的巨集名稱。

雖然輸出使用的語法與 BUILD 檔案相同,但不保證會產生有效的 BUILD 檔案。

--output label

使用這個選項時,系統會列印結果圖表中每個目標的名稱 (或「標籤」),每行一個標籤,按順序排序 (除非指定 --noorder_results,請參閱結果排序注意事項)。(邏輯排序是指圖形節點比所有後續字串更早出現的位置)。當然,圖表可以有許多可能的邏輯順序 (反向 Postorder 只是一個),您不必指定這個順序。

列印 somepath 查詢的輸出內容時,節點的列印順序即為路徑順序。

注意:在某些極端情況下,可能會有兩個具有相同標籤的不同目標。舉例來說,sh_binary 規則及其個別 (隱含) 的 srcs 檔案也可以稱為 foo.sh。如果查詢結果同時包含這兩個目標,則輸出內容 (label 格式) 似乎包含重複。使用 label_kind (請見下方) 格式時,差異會清楚明瞭:兩個目標的名稱相同,但其中一個具有 sh_binary rule 種類,另一個為 source file

--output label_kind

label 一樣,這個輸出格式會依照邏輯順序,在結果圖表中列印每個目標的標籤,但額外放在目標的 Kind 標籤之前。

--output proto

將查詢輸出內容列印為 QueryResult 通訊協定緩衝區。

--output streamed_proto

列印 Target 通訊協定緩衝區的長度分隔資料流。當單一 QueryResult 的目標太多,無法納入單一 QueryResult(ii) 開始處理時,這可幫助 (i) 規避通訊協定緩衝區的大小限制,或在 Bazel 仍在輸出的情況下開始處理。

--output textproto

--output proto 類似,會以文字格式輸出 QueryResult 通訊協定緩衝區。

--output streamed_jsonproto

--output streamed_proto 類似,會輸出 Target 通訊協定緩衝區串流,但採用 ndjson 格式。

--output minrank --output maxrank

label 一樣,minrankmaxrank 輸出格式會列印結果圖表中每個目標的標籤,但這些標籤不會以拓撲順序顯示,且會顯示在排名之前。這不受結果排序 --[no]order_results 標記的影響 (請參閱結果排序注意事項)。

格式如下:minrank 會依照從根節點到其之間的最短路徑長度,對各個節點排名。「根」節點 (沒有傳入邊緣者) 的排名為 0,其後代為排名 1,以此類推 (一如往常,從目標的邊緣指向其先決條件:其依賴的目標)。

maxrank 會將每個節點按照根節點到其間最長路徑的長度來排名。同樣,「根項目」的排名是 0,其他節點的排名也是所有其他節點的排名 1 以上。

系統會將週期中的所有節點視為相等的排名。(大多數圖表都是循環,但循環只是因為 BUILD 檔案包含錯誤的循環而發生)。

如要瞭解圖表的深度,這些輸出格式就相當實用。如果用於 deps(x)rdeps(x)allpaths 查詢的結果,排名數字會等於從 x 到該排名中節點的最長路徑長度 (包含 minrank),或最長 (含 maxrank) 路徑。maxrank 可用於判斷建立目標所需的最長建構步驟序列。

舉例來說,當指定 --output minrank--output maxrank 時,左側圖表會在右側產生輸出。

排名勝出
      minrank

      0 //c:c
      1 //b:b
      1 //a:a
      2 //b:b.cc
      2 //a:a.cc
      
      maxrank

      0 //c:c
      1 //b:b
      2 //a:a
      2 //b:b.cc
      3 //a:a.cc
      
--output location

此選項和 label_kind 一樣,會針對結果中的每個目標輸出目標的種類和標籤,但前面會加上描述目標位置的字串,以檔案名稱和行數表示。格式與 grep 的輸出內容類似。因此,可剖析後者的工具 (例如 Emacs 或 vi) 也可以使用查詢輸出來逐步完成一系列比對作業,讓 Bazel 查詢工具能做為可感知依附元件的「grep for BUILD 檔案」使用 grep 指令。

位置資訊會因目標類型而異 (請參閱 Kind 運算子)。如為規則,系統會列印 BUILD 檔案中規則宣告的位置。至於來源檔案,則會列印實際檔案的第 1 行位置。系統會為產生的檔案,顯示產生該檔案的規則位置。(查詢工具的資訊不足,無法找出所產生檔案的實際位置,而且在任何情況下,如果尚未執行,就可能不存在)。

--output package

這個選項會輸出結果集中某些目標所屬的所有套件名稱。名稱會按照字母順序列印,系統會排除重複名稱。基本上,這是從標籤 (套件、目標) 發布至套件的「投影」

外部存放區中的套件會格式化為 @repo//foo/bar,而主要存放區中的套件則是採用 foo/bar 格式。

deps(...) 查詢搭配使用時,這項輸出選項可用來尋找必須勾選的套件組合,才能建構指定的目標組合。

顯示結果圖表

--output graph

這個選項會使查詢結果以熱門 AT&T GraphViz 格式的有向圖的形式列印。一般而言,結果會儲存到 .png.svg 等檔案。(如果工作站未安裝 dot 程式,您可以使用 sudo apt-get install graphviz 指令進行安裝)。如需叫用範例,請參閱下一節的範例。

此輸出格式特別適用於 allpathsdepsrdeps 查詢,因為結果包含的一組路徑,在以線性格式 (例如 --output label) 顯示時無法輕鬆視覺化。

根據預設,圖表是以「因式」的形式呈現。也就是說,性質相等的節點會合併成具有多個標籤的單一節點。這會讓圖表更簡潔且易讀,因為一般結果圖表包含高度重複的模式。舉例來說,java_library 規則可能會依附數百個 Java 來源檔案,這些檔案都由同一個 genrule 產生;在因式分解圖中,這些檔案全都以單一節點表示。您可以使用 --nograph:factored 選項停用這個行為。

--graph:node_limit n

這個選項會指定輸出中圖表節點的標籤字串長度上限。較長的標籤會遭到截斷;-1 則停用截斷功能。由於通常會輸出圖表的因式分解形式,節點標籤可能會很長。GraphViz 無法處理超過 1024 個字元的標籤 (此為這個選項的預設值)。除非使用 --output=graph,否則這個選項不會有任何作用。

--[no]graph:factored

根據預設,圖表會以因式分解的形式顯示,如上文所述。指定 --nograph:factored 時,系統會在不因因素數化的情況下列印圖表。這會使用 GraphViz 簡化視覺化內容,但較簡單的格式可能會簡化其他工具 (例如 grep) 的處理過程。除非使用 --output=graph,否則這個選項不會有任何作用。

XML

--output xml

這個選項會使產生的目標以 XML 表單輸出。輸出內容開頭是 XML 標頭,例如

  <?xml version="1.0" encoding="UTF-8"?>
  <query version="2">

然後,結果圖中的每個目標都有 XML 元素,按序序排列 (除非要求未排序的結果),然後再終止一個終止項目。

</query>

系統會針對 file 種類的目標發出簡易項目:

  <source-file name='//foo:foo_main.cc' .../>
  <generated-file name='//foo:libfoo.so' .../>

但對於規則,XML 是結構化,且包含規則所有屬性的定義,包括規則 BUILD 檔案中未明確指定值的屬性。

此外,結果包含 rule-inputrule-output 元素,因此即使不瞭解依附元件圖表的拓撲,也能重新建構依附元件。舉例來說,srcs 屬性的元素是前向依附元件 (必備條件),outs 屬性的內容則是回溯依附元件 (消費者)。

如果指定 --noimplicit_deps,系統會隱藏隱含依附元件rule-input 元素。

  <rule class='cc_binary rule' name='//foo:foo' ...>
    <list name='srcs'>
      <label value='//foo:foo_main.cc'/>
      <label value='//foo:bar.cc'/>
      ...
    </list>
    <list name='deps'>
      <label value='//common:common'/>
      <label value='//collections:collections'/>
      ...
    </list>
    <list name='data'>
      ...
    </list>
    <int name='linkstatic' value='0'/>
    <int name='linkshared' value='0'/>
    <list name='licenses'/>
    <list name='distribs'>
      <distribution value="INTERNAL" />
    </list>
    <rule-input name="//common:common" />
    <rule-input name="//collections:collections" />
    <rule-input name="//foo:foo_main.cc" />
    <rule-input name="//foo:bar.cc" />
    ...
  </rule>

目標的每個 XML 元素都包含一個 name 屬性 (值為目標標籤) 和 location 屬性,其值為目標位置 (如 --output location 顯示)。

--[no]xml:line_numbers

根據預設,XML 輸出內容顯示的地點會包含行號。指定 --noxml:line_numbers 時,系統不會列印行號。

--[no]xml:default_values

根據預設,XML 輸出內容不會包含屬性值是該種類屬性的預設值 (例如,未在 BUILD 檔案中指定,或明確提供預設值的規則屬性)。這個選項會使這類屬性值包含在 XML 輸出中。

規則運算式

查詢語言的規則運算式使用 Java 規則運算式程式庫,因此您可以使用 java.util.regex.Pattern 的完整語法。

使用外部存放區進行查詢

如果建構依附於外部存放區的規則,則查詢結果會包含這些依附元件。舉例來說,如果 //foo:bar 依附於 @other-repo//baz:lib,則 bazel query 'deps(//foo:bar)' 會將 @other-repo//baz:lib 列為依附元件。