在 Bazel 的 macro 中调用的规则(比如 native.cc_library
、native.genrule
等)在语义上并不是“顺序执行”的,因为 Bazel 本身是一个 声明式的构建系统,构建规则的执行顺序是由 依赖图(DAG) 决定的,而不是宏中代码的书写顺序。
🔍 具体来说:
✅ 宏中的语句是“顺序执行”的(在解释阶段)
宏是用 Starlark 写的普通函数,在 Bazel 解析 BUILD 文件的时候,宏会被调用执行,在这个阶段,它们确实是从上到下按顺序执行的。
也就是说:
def my_macro(name):
native.genrule(
name = name + "_a",
outs = ["a.txt"],
cmd = "echo A > $@",
)
native.genrule(
name = name + "_b",
outs = ["b.txt"],
cmd = "echo B > $@",
)
-
_a
规则和_b
规则都会被创建。 -
它们的定义顺序是
_a
然后_b
,这个顺序是解析顺序。
🚫 但执行顺序(build 时)不一定按这个顺序
除非你显式地在规则之间加上依赖:
def my_macro(name):
native.genrule(
name = name + "_a",
outs = ["a.txt"],
cmd = "echo A > $@",
)
native.genrule(
name = name + "_b",
outs = ["b.txt"],
srcs = [":" + name + "_a"], # 依赖 _a 的输出
cmd = "cat $(SRCS) > $@ && echo B >> $@",
)
这样 Bazel 才知道 _b
依赖 _a
,执行时会先构建 _a
再构建 _b
。
✳️ 总结
层面 | 是否顺序执行 | 说明 |
---|---|---|
宏定义阶段(BUILD 解析时) | ✅ 是 | Starlark 本身是顺序执行的语言 |
构建执行阶段(bazel build) | ❌ 否 | Bazel 按依赖图决定执行顺序,宏中定义顺序无效 |
如何控制顺序 | ➕ 添加 deps= 、srcs= 、data= 明确依赖关系 |