目錄
套件
package(default_deprecation, default_testonly, default_visibility, features)
這個函式會宣告適用於套件中每個後續規則的中繼資料。在套件 (BUILD 檔案) 中最多使用一次。
請務必在檔案頂端的所有 load() 陳述式之後,在任何規則之前呼叫 package() 函式。
引數
屬性 | 說明 |
---|---|
default_visibility |
這個套件中的規則預設瀏覽權限。 除非規則的 |
default_deprecation |
為這個套件中的所有規則設定預設的
|
default_testonly |
為這個套件中的所有規則設定預設的
在 |
features |
設定會影響這個 BUILD 檔案語意的各種標記。 這項功能主要供建構系統的人員使用,藉此標記需要某些特殊處理的套件。除非建構系統的工作人員明確要求,否則請勿使用。 |
範例
下列宣告表示只有套件群組//foo:target
的成員才能看到這個套件中的規則。針對規則中的個別瀏覽權限宣告 (如有),會覆寫此規格。package(default_visibility = ["//foo:target"])
package_group
package_group(name, packages, includes)
這個函式會定義一組套件,並將標籤與這組組合建立關聯。您可以在 visibility
屬性中參照這個標籤。
套件群組主要用於控管瀏覽權限。公開可見的目標可以從來源樹狀結構中的每個套件參照。不公開可見的目標只能在自己的套件中參照 (而非子套件)。在極端的期間,目標可能會允許存取其自身套件,以及一或多個套件群組所描述的任何套件。如需瀏覽權限系統的詳細說明,請參閱瀏覽權限屬性。
如果特定套件與 packages
屬性相符,或已包含在 includes
屬性中提及的另一個套件群組中,系統就會將特定套件視為群組。
套件群組在技術上屬於目標,但不是由規則建立,也沒有任何瀏覽權限設定。
引數
屬性 | 說明 |
---|---|
name |
此目標的專屬名稱。 |
packages |
零或多個套件規格的清單。 每個套件規格字串都可以使用下列其中一種格式:
此外,前兩種套件規格也可以加上 套件群組包含任何符合至少一個正規格,且沒有任何排除規格的套件。例如, 除了公開瀏覽權限,您無法直接在目前存放區外指定套件。 如果缺少這項屬性,其會與設為空白清單相同,效果等同於將這項屬性設為只包含 注意:在 Bazel 6.0 之前,規格 注意:在 Bazel 6.0 之前,當此屬性在 |
includes |
這個檔案中的其他套件群組。 這項屬性中的標籤必須參照其他套件群組。參照套件群組中的套件會納入這個套件群組中。這屬於遞移性,如果套件群組 與否定的套件規格搭配使用時,請注意,系統會先獨立計算每個群組的套件組合,然後將結果聯集在一起。也就是說,其中一個群組中的否定規格不會影響另一個群組中的規格。 |
範例
以下 package_group
宣告指定名為「熱帶」的套件群組,且包含熱帶水果。
package_group( name = "tropical", packages = [ "//fruits/mango", "//fruits/orange", "//fruits/papaya/...", ], )
下列宣告會指定虛構應用程式的套件群組:
package_group( name = "fooapp", includes = [ ":controller", ":model", ":view", ], ) package_group( name = "model", packages = ["//fooapp/database"], ) package_group( name = "view", packages = [ "//fooapp/swingui", "//fooapp/webui", ], ) package_group( name = "controller", packages = ["//fooapp/algorithm"], )
exports_files
exports_files([label, ...], visibility, licenses)
exports_files()
會指定屬於這個套件的檔案清單,且這些檔案會匯出至其他套件。
如果套件的 BUILD 檔案是以 exports_files()
陳述式明確匯出,則只能直接參照屬於其他套件的來源檔案。進一步瞭解檔案瀏覽權限。
做為舊版行為時,如果內容提及規則的輸入資料,在匯出標記 --incompatible_no_implicit_file_export
之前,系統會以預設瀏覽權限匯出。不過,您不應仰賴這個行為,並主動遷離。
引數
引數是目前套件中的檔案名稱清單。您也可以指定瀏覽權限宣告;在這種情況下,指定檔案可以查看檔案。如未指定瀏覽權限,即使已在 package
函式中指定套件預設瀏覽權限,每個套件都會顯示檔案。您也可以指定授權。
範例
下列範例會從 test_data
套件匯出文字檔案 golden.txt
,因此其他套件可能會使用此檔案,例如在測試的 data
屬性中使用該檔案。
# from //test_data/BUILD exports_files(["golden.txt"])
glob
glob(include, exclude=[], exclude_directories=1, allow_empty=True)
Glob 是一種輔助函式,可找出符合特定路徑模式的所有檔案,並傳回新的、可變動且排序的路徑清單。Glob 只會搜尋專屬套件中的檔案,而且只會尋找來源檔案 (不會產生檔案或其他目標)。
如果檔案的套件相對路徑符合任何 include
模式,且沒有任何 exclude
模式,結果中會包含來源檔案的標籤。
include
和 exclude
清單包含與目前套件相關的路徑模式。每個模式都包含一或多個路徑片段。和 Unix 路徑一樣,這些區段會以 /
分隔。區隔可包含 *
萬用字元:這會與路徑片段中的任何子字串 (甚至是空白子字串) 相符,但排除目錄分隔符 /
。這個萬用字元可以在一個路徑片段中多次使用。此外,**
萬用字元可比對零或更完整的路徑區段,但必須宣告為獨立路徑片段。
foo/bar.txt
與這個套件中的foo/bar.txt
檔案完全相符- 如果檔案結尾為
.txt
,foo/*.txt
會比對foo/
目錄中的每個檔案 (除非foo/
是子套件) foo/a*.htm*
會比對foo/
目錄中以a
開頭的每個檔案,接著含有任意字串 (可以是空白),然後有.htm
,並以另一個任意字串結尾,例如foo/axx.htm
、foo/a.html
或foo/axxx.html
。**/a.txt
會比對這個套件中每個子目錄中的每個a.txt
檔案- 如果產生的路徑上至少有一個目錄呼叫
bar
(例如xxx/bar/yyy/zzz/a.txt
或bar/a.txt
,**
也與零部分相符),**/bar/**/*.txt
會比對這個套件中的每個子目錄中的每個.txt
檔案bar/zzz/a.txt
**
會比對這個套件中每個子目錄中的所有檔案foo**/a.txt
是無效模式,因為**
必須本身視為片段
如果啟用 exclude_directories
引數 (設為 1),結果中會省略類型目錄的檔案 (預設 1)。
如果將 allow_empty
引數設為 False
,如果結果會是空白清單,glob
函式就會發生錯誤。
有幾個重要的限制和注意事項:
-
由於
glob()
會在 BUILD 檔案評估期間執行,因此glob()
只會比對來源樹狀結構中的檔案,永不產生檔案。如果您要建構的目標同時需要來源和產生的檔案,則必須在 glob 中附加明確產生的檔案清單。請參閱下方有關:mylib
和:gen_java_srcs
的範例。 -
如果規則的名稱與相符的來源檔案相同,規則就會「覆蓋」檔案。
請注意,
glob()
會傳迴路徑清單,因此在其他規則屬性 (例如srcs = glob(["*.cc"])
) 中使用glob()
的效果,與明確列出相符路徑的效果相同。如果範例glob()
產生["Foo.java", "bar/Baz.java"]
,但套件中還有名為「Foo.java」的規則 (雖然系統允許,但有 Bazel 為此警告),則glob()
的取用端會使用「Foo.java」規則 (其輸出內容),而不是「Foo.java」檔案。詳情請參閱 GitHub 問題 #10395。 - Globs 可能會比對子目錄中的檔案。子目錄名稱也可加入萬用字元。不過...
-
標籤不得跨越套件邊界,且 glob 與子套件中的檔案不相符。
舉例來說,如果
x/y
是套件 (為x/y/BUILD
或套件路徑中的其他位置) 存在,則x
套件中的 glob 運算式**/*.cc
不包含x/y/z.cc
。這表示 glob 運算式的結果實際上取決於 BUILD 檔案;也就是說,如果沒有呼叫x/y
的套件,則相同的 glob 運算式會包含x/y/z.cc
,或者使用 --deleted_packages 標記將其標示為已刪除。 - 上述限制適用於所有 glob 運算式 (無論其使用何種萬用字元)。
-
檔案名稱開頭為
.
的隱藏檔案,會完全與**
和*
萬用字元進行比對。如要比對隱藏檔案與複合模式,模式的開頭必須是.
。舉例來說,*
和.*.txt
會與.foo.txt
相符,但*.txt
不會。此外,系統也會以相同方式比對隱藏的目錄。隱藏的目錄可能包含輸入不需要的檔案,也可能增加無謂的檔案和記憶體使用量。如要排除隱藏的目錄,請將這些目錄新增至「排除」清單引數。 -
「**」萬用字元有一個邊角大小寫:
"**"
模式與套件的目錄路徑不符。也就是說,glob(["**"], exclude_directories = 0)
會間接比對目前套件目錄中的所有檔案和目錄 (但絕不會前往子套件的目錄,請參閱先前的注意事項)。
一般來說,針對 glob 模式,您應嘗試提供適當的副檔名 (例如 *.html),而非使用裸機「*」。較明確的名稱是自行記錄,可確保不會意外比對備份檔案,或自動儲存 emacs/vi/... 檔案。
編寫建構規則時,您可以列舉 glob 的元素。進而為每個輸入內容產生個別規則,例如。請參閱下方的展開的 glob 範例一節。
Glob 範例
建立根據這個目錄中的所有 Java 檔案,以及 :gen_java_srcs
規則產生的所有檔案所建構的 Java 程式庫。
java_library( name = "mylib", srcs = glob(["*.java"]) + [":gen_java_srcs"], deps = "...", ) genrule( name = "gen_java_srcs", outs = [ "Foo.java", "Bar.java", ], ... )
在目錄 testdata 中加入所有 txt 檔案 (Experimental.txt 除外)。 請注意,測試資料子目錄中的檔案不會納入。如要納入這些檔案,請使用遞迴 glob (**)。
sh_test( name = "mytest", srcs = ["mytest.sh"], data = glob( ["testdata/*.txt"], exclude = ["testdata/experimental.txt"], ), )
遞迴 Glob 範例
確保測試取決於 testdata 目錄和其子目錄中的所有 txt 檔案 (及其子目錄等)。系統會忽略包含 BUILD 檔案的子目錄。(請參閱上方的限制和注意事項)。
sh_test( name = "mytest", srcs = ["mytest.sh"], data = glob(["testdata/**/*.txt"]), )
建立根據這個目錄和所有子目錄建構的程式庫,但路徑包含具名測試的目錄除外。請盡量避免這個模式,因為這麼做可以減少建構增量,進而增加建構時間。
java_library( name = "mylib", srcs = glob( ["**/*.java"], exclude = ["**/testing/**"], ), )
展開的 Glob 範例
在目前的目錄中為 *_test.cc 建立個別的 genrule,藉此計算檔案中的行數。
# Conveniently, the build language supports list comprehensions. [genrule( name = "count_lines_" + f[:-3], # strip ".cc" srcs = [f], outs = ["%s-linecount.txt" % f[:-3]], cmd = "wc -l $< >$@", ) for f in glob(["*_test.cc"])]
如果上述 BUILD 檔案位於套件 //foo 中,且套件包含三個比對檔案,a_test.cc、b_test.cc 和 c_test.cc,則執行 bazel query '//foo:all'
就會列出產生的所有規則:
$ bazel query '//foo:all' | sort //foo:count_lines_a_test //foo:count_lines_b_test //foo:count_lines_c_test
選取
select( {conditionA: valuesA, conditionB: valuesB, ...}, no_match_error = "custom message" )
select()
是輔助函式,使規則屬性「可設定」。這項設定可取代「幾乎」所有屬性指派作業的右側,因此這個值取決於指令列 Bazel 標記。例如,您可以藉此定義平台專屬的依附元件,或根據規則是在「開發人員」模式和「發布」模式建構不同資源。
基本用途如下:
sh_binary( name = "mytarget", srcs = select({ ":conditionA": ["mytarget_a.sh"], ":conditionB": ["mytarget_b.sh"], "//conditions:default": ["mytarget_default.sh"] }) )
這樣就能設定 sh_binary
的 srcs
屬性,方法是將其一般標籤清單指派作業替換為可將設定條件對應至相符值的 select
呼叫。每個條件都是指向 config_setting
或 constraint_value
的標籤參照。如果目標的設定符合一組預期的值,就會「相符」。mytarget#srcs
的值會成為與目前叫用相符的標籤清單。
注意:
- 每次叫用只會選取一個條件。
- 如果有多個條件相符,其中一個條件是其他條件的一種,則優先採用專家認證。如果 B 的標記和限制值與 A 全都相同,再加上一些額外的標記或限制值,則條件 B 就會視為條件 A 的特殊化。這也表示專業解決方案並非設計為建立排序,如下方範例 2 所示。
- 如果有多個條件相符,而其中一個條件並非其他所有條件,Bazel 就會發生錯誤,除非所有條件都解析相同的值。
- 如果沒有其他條件相符,則特殊虛擬標籤
//conditions:default
會視為相符。如果沒有這項條件,其他規則必須相符才能避免發生錯誤。 select
可嵌入大型屬性指派「內部」。因此,srcs = ["common.sh"] + select({ ":conditionA": ["myrule_a.sh"], ...})
和srcs = select({ ":conditionA": ["a.sh"]}) + select({ ":conditionB": ["b.sh"]})
是有效的運算式。select
適用於大多數 (而非全部) 屬性。在說明文件中,系統會將不相容的屬性標示為nonconfigurable
。子套件
subpackages(include, exclude=[], allow_empty=True)
subpackages()
是與glob()
類似的輔助函式,這類函式會列出子套件,而不是檔案和目錄。它會使用與glob()
相同的路徑模式,且能比對目前載入 BUILD 檔案的直接子系任何子套件。如需納入和排除模式的詳細說明與範例,請參閱 glob。傳回的子套件清單會以排序順序列出,其中包含的相對於目前載入套件的路徑,且該套件符合
include
中的指定模式,而非exclude
中的模式。範例
以下範例會列出套件
foo/BUILD
的所有直接子套件# The following BUILD files exist: # foo/BUILD # foo/bar/baz/BUILD # foo/sub/BUILD # foo/sub/deeper/BUILD # # In foo/BUILD a call to subs = subpackages(include = ["**"]) # results in subs == ["sub", "bar/baz"] # # 'sub/deeper' is not included because it is a subpackage of 'foo/sub' not of # 'foo'
一般來說,我們建議使用者不要直接呼叫此函式,而是使用 skylib 的「subpackages」模組。