Bazel 標籤是字串參照,參照的對象是來源檔案和 BUILD.bazel 檔案中定義的項目。一般格式如下:
@<repository_name>//<package_name>:<target_name>
其中:
@<repository_name>//會指定具名 Bazel 工作區的目錄。為方便起見,您可以簡寫為
//,代表目前的 Workspace (包含目前的BUILD.bazel檔案)。另請注意,@//用於指定專案的根工作區,即使是在外部存放區中使用也是如此。<package_name>是套件的目錄路徑,相對於工作區目錄。舉例來說,在標籤//src:main.cc或//src/lib:foo中,套件名稱分別為src和src/lib。這可以是空白,例如
//:BUILD.bazel指向目前工作區頂層目錄中的建構檔案。如果是來源檔案,
<target_name>是相對於上層套件目錄的檔案路徑,可能包含子目錄部分。舉例來說,如果是//src:main.cc或//src:extra/extra.cc,目標名稱分別為main.cc和extra/extra.cc。如果是其他項目,
<target_name>對應於BUILD.bazel檔案中定義的項目 (建構構件、建構設定、設定條件等)。按照慣例,其
name屬性不應包含目錄分隔符號 (極少數情況除外),以免與來源混淆。對於來自其他建構系統的開發人員來說,這可能會造成混淆,因為這些系統會區分建構圖中的項目類型 (例如
GN會使用「目標」、「設定」、「工具鍊」和「集區」來指定不同項目)。
此外,也支援標籤的縮寫:
如果標籤以存放區名稱開頭,且不含半形冒號,則為套件路徑,並指向名稱相同的項目。例如,
//src/foo等同於//src/foo:foo。如果標籤開頭為半形冒號,則為相對於目前套件的名稱。舉例來說,
src/foo/BUILD.bazel中出現的「:bar」和「:extra/bar.cc」分別等同於//src/foo:bar和//src/foo:extra/bar.cc。如果標籤沒有存放區名稱和冒號,一律是相對於目前套件的名稱,即使包含目錄分隔符號也一樣。例如,
src/foo/BUILD.bazel中的「bar/bar.cc」一律是指//src/foo:bar/bar.cc。請注意,這與
//src/foo/bar:bar.cc不同
相對標籤和套件擁有權
由於每個來源檔案只能屬於單一套件,因此相對標籤可能無效。舉例來說,在類似下列的專案中:
/home/user/project/
WORKSPACE.bazel
src/
BUILD.bazel
main.cc
extra/
extra.cc
lib/
BUILD.bazel
foo.cc
foo.h
foo.cc 檔案屬於 src/lib 套件,因此其標籤必須是
//src/lib:foo.cc。
在 src/BUILD.bazel 中使用 src:lib/foo.cc 等標籤會導致錯誤:
# From src/BUILD.bazel
cc_binary(
name = "program",
srcs = [
"extra/extra.cc",
"lib/foo.cc", # Error: Label '//src:lib/foo.cc' is invalid because 'src/lib' is a subpackage
"lib/foo.h" # Error: Label '//src:lib/foo.h' is invalid because 'src/lib' is a subpackage
"main.cc",
],
)
從其他套件存取來源檔案
根據預設,其他套件無法存取特定套件的來源檔案,且相對套件標籤無效,如下所示:
# From src/BUILD.bazel
cc_binary(
name = "program",
srcs = [
"extra/extra.cc",
"lib:foo.cc", # Error: invalid label 'lib:foo.cc': absolute label must begin with '@' or '//'
"lib:foo.h" # Error: invalid label 'lib:foo.h': absolute label must begin with '@' or '//'
"main.cc",
],
)
即使使用正確的絕對標籤,仍會發生錯誤:
# From src/BUILD.bazel
cc_binary(
name = "program",
srcs = [
"extra/extra.cc",
"//src/lib:foo.cc", # Error: no such target '//src/lib:foo.cc': target 'foo.h' not declared in package 'src/lib'
"//src/lib:foo.h" # Error: no such target '//src/lib:foo.h': target 'foo.h' not declared in package 'src/lib'
"main.cc",
],
)
您可以透過下列方式,直接存取套件界線以外的檔案:export_files()
# From src/lib/BUILD.bazel
export_files([
"foo.cc" ,
"foo.h" ,
])
# From src/BUILD.bazel
cc_binary(
name = "program",
srcs = [
"extra/extra.cc",
"//src/lib:foo.cc", # OK
"//src/lib:foo.h" # OK
"main.cc",
],
)
其他套件的目標存取權
BUILD.bazel 檔案中定義的標籤項目如非來源檔案,則不需要匯出,但其 visibility 屬性必須允許在自有套件外使用:
# From src/lib/BUILD.bazel
cc_library(
name = " lib" ,
srcs = [ " foo.cc" ],
hdrs = [ " foo.h" ],
visibility = [ " //visibility:public" ], # Anyone can reference this directly!
)
# From src/BUILD.bazel
cc_binary(
name = "program",
srcs = [
"extra/extra.cc",
"main.cc",
],
deps = [ "lib" ], # OK!
)
根據預設,項目只會對同一個套件中的其他項目顯示。
如要變更這項設定,請使用 package() 指令,變更套件中定義的所有項目的預設顯示設定:
# From src/lib/BUILD.bazel
# Ensure that all items defined in this file are visible to anyone
package(default_visibility = ["//visibility:public"])
cc_library(
name = " lib" ,
srcs = [ "foo.cc" ],
hdrs = [ "foo.h" ],
)
# From src/BUILD.bazel
cc_binary(
name = "program",
srcs = [
"extra/extra.cc",
"main.cc",
],
deps = [ "lib" ], # OK!
)
虛擬套件警告
請避免在專案中建立下列名稱的頂層目錄:
conditionscommand_line_optionexternalvisibility
因為 Bazel 會在 BUILD.bazel 檔案的標籤中使用多個硬式編碼的「虛擬套件」。例如:
//visibility:public
//conditions:default
//command_line_option:copt
external 的情況有點不同:它不會出現在 BUILD.bazel 檔案中,但用於內部管理外部存放區。如果將這個目錄當做專案目錄使用,會讓 Bazel 感到困惑
標準存放區名稱
自 Bazel 6.0 起,標籤中的存放區名稱也可以 @@ 開頭。
啟用選用的 BzlMod 功能後,這些標籤會做為外部存放區的替代標籤名稱,但必須是專屬名稱。在專案中使用複雜的遞移依附元件樹狀結構時,這點就非常重要。
舉例來說,@@com_acme_anvil.1.0.3 可能是專案自有 BUILD.bazel 檔案中以 @anvil 識別的工作區目錄的標準名稱,也可能是出現在外部存放區 (例如 @foo//:BUILD.bazel 內) 時的 @acme_anvil。這三個標籤都會參照相同目錄的內容。
標準存放區名稱不會顯示在 BUILD.bazel 檔案中,但會在分析階段 (執行查看標籤值的 Starlark 函式時) 或查看 Bazel 查詢結果時顯示。