本頁將介紹巨集使用基本概念,並涵蓋常見用途。 偵錯和慣例
巨集是從 BUILD
檔案呼叫的函式,可用來建立規則例項。
巨集主要用於封裝和重複使用現有規則的程式碼
和其他巨集結尾
載入階段,巨集已不存在
而 Bazel 只會看到具體的例項化規則組合。
用量
巨集的常見用途是重複使用規則。
例如,BUILD
檔案中的 genrule 會使用
//:generator
,其中含有硬式編碼的 some_arg
引數:
genrule(
name = "file",
outs = ["file.txt"],
cmd = "$(location //:generator) some_arg > $@",
tools = ["//:generator"],
)
如要產生更多使用不同引數的檔案,建議您
將這段程式碼擷取至巨集函式假設巨集 file_generator
包含 name
和 arg
參數將 genrule 替換為下列內容:
load("//path:generator.bzl", "file_generator")
file_generator(
name = "file",
arg = "some_arg",
)
file_generator(
name = "file-two",
arg = "some_arg_two",
)
file_generator(
name = "file-three",
arg = "some_arg_three",
)
您可以從這裡的 .bzl
檔案載入 file_generator
符號。
//path
套件中。將巨集函式定義放在獨立的
.bzl
檔案,讓 BUILD
檔案保持清理及宣告式「.bzl
」
可以從工作區中的任何套件載入。
最後,在 path/generator.bzl
中,將巨集的定義寫入
封裝原始 genrule 定義並參數化:
def file_generator(name, arg, visibility=None):
native.genrule(
name = name,
outs = [name + ".txt"],
cmd = "$(location //:generator) %s > $@" % arg,
tools = ["//:generator"],
visibility = visibility,
)
您也可以使用巨集將規則鏈結在一起。這個範例顯示鏈結 genrules,其中 Genrule 使用前一個 Genrule 的輸出內容做為輸入內容:
def chained_genrules(name, visibility=None):
native.genrule(
name = name + "-one",
outs = [name + ".one"],
cmd = "$(location :tool-one) $@",
tools = [":tool-one"],
visibility = ["//visibility:private"],
)
native.genrule(
name = name + "-two",
srcs = [name + ".one"],
outs = [name + ".two"],
cmd = "$(location :tool-two) $< $@",
tools = [":tool-two"],
visibility = visibility,
)
這個範例只會將瀏覽權限值指派給第二個 Genrule。這樣一來, 巨集作者可以隱藏中繼規則的輸出內容 工作區內其他目標。
展開巨集
如要調查巨集的用途,請使用 query
指令,並加上
--output=build
,即可查看展開的表單:
$ bazel query --output=build :file
# /absolute/path/test/ext.bzl:42:3
genrule(
name = "file",
tools = ["//:generator"],
outs = ["//test:file.txt"],
cmd = "$(location //:generator) some_arg > $@",
)
將原生規則例項化
原生規則 (不需要 load()
陳述式的規則) 可以是
從 native 模組例項化:
def my_macro(name, visibility=None):
native.cc_library(
name = name,
srcs = ["main.cc"],
visibility = visibility,
)
如果您需要知道套件名稱 (例如,BUILD
檔案
巨集),請使用 native.package_name() 函式。
請注意,native
只能用於 .bzl
檔案,無法用於 BUILD
檔案。
巨集中的標籤解析度
由於巨集是在載入階段接受評估,
系統會解讀在巨集中發生的標籤字串,例如 "//foo:bar"
相對於使用巨集的 BUILD
檔案
在其中定義的 .bzl
檔案。這種行為通常不適合
以便用於其他存放區中的巨集
隸屬於已發布的 Starlark 規則集。
如要取得與 Starlark 規則相同的行為,請使用
Label
建構函式:
# @my_ruleset//rules:defs.bzl
def my_cc_wrapper(name, deps = [], **kwargs):
native.cc_library(
name = name,
deps = deps + select({
# Due to the use of Label, this label is resolved within @my_ruleset,
# regardless of its site of use.
Label("//config:needs_foo"): [
# Due to the use of Label, this label will resolve to the correct target
# even if the canonical name of @dep_of_my_ruleset should be different
# in the main repo, such as due to repo mappings.
Label("@dep_of_my_ruleset//tools:foo"),
],
"//conditions:default": [],
}),
**kwargs,
)
偵錯
bazel query --output=build //my/path:all
會向你說明BUILD
檔案的方式 外觀所有巨集、glob、迴圈已展開。已知 限制:select
運算式目前未顯示在輸出內容中。您可以根據
generator_function
(哪個函式) 篩選輸出內容 產生的規則) 或generator_name
(巨集的名稱屬性):bash $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)'
如要找出
foo
規則在BUILD
檔案中的確切產生位置,您必須 可以試試以下技巧在BUILD
頂端附近插入這一行 檔案:cc_library(name = "foo")
。執行 Bazel。如遇此情況, 由於名稱衝突,系統建立「foo
」規則,會顯示 或完整的堆疊追蹤您也可以使用 print 進行偵錯。顯示 在載入階段,將訊息顯示為
DEBUG
記錄行。例外情況 請移除print
呼叫,或是在debugging
參數在提交程式碼給False
開始訓練
錯誤
如要擲回錯誤,請使用 fail 函式。
向使用者清楚說明發生錯誤的原因,以及如何修正 BUILD
檔案。
無法擷取錯誤。
def my_macro(name, deps, visibility=None):
if len(deps) < 2:
fail("Expected at least two values in deps")
# ...
慣例
所有未以底線開頭的公開函式, 例項化規則必須具備
name
引數。這個引數不應 選填 (不指定預設值)。公開函式應在 Python 後面使用 docstring 慣例。
在
BUILD
檔案中,巨集的name
引數必須是關鍵字 引數 (並非位置引數)。巨集產生的規則的
name
屬性應包含名稱 做為前置字串舉例來說,macro(name = "foo")
可以產生cc_library
foo
和 genrulefoo_gen
。在大多數情況下,選用參數應有預設值
None
。None
可以直接傳遞至原生規則,其視為與 輸入的值。因此您不需要更換 搭配0
、False
或[]
使用。相反地 因為預設值可能很複雜,也可能發生在 讓應用程式從可以最快做出回應的位置 回應使用者要求此外,還有一個明確設定為其預設值的參數 看起來與存取時從未設定 (或設為None
) 的值不同 查詢語言或建構系統內部資訊巨集應有選用的
visibility
引數。