我有两个宏/目标:组件和捆绑包(打包了几个组件)。我想扩展bundle宏,以接受除了组件列表之外的一系列bundle,并将所有直接包含或包含在其包含的bundle中的所有组件打包。
例如,如果我有以下BUILD
文件:
component(name = 'a')
component(name = 'b')
component(name = 'c')
component(name = 'd')
bundle(name = 'x', components = ['a'])
bundle(name = 'y', components = ['b', 'c'], bundles = ['x'])
bundle(name = 'z', components = ['d'], bundles = ['y'])
bundle z应该包含分量a,b,c和d
.bzl
文件现在是这样的:
def component(name):
# implementation (it uses other args but they aren't relevant)
def bundle(name, components = []):
# complex logic on components
我想要的是:
def bundle(name, components = [], bundles = []):
for bundle in bundles:
for component in TODO_get_components_in_bundle(bundle):
if component not in components:
components.append(component)
# complex logic on components
如何实现TODO_get_components_in_bundle
或达到相同的效果?
答案 0 :(得分:1)
您不能单独使用macro来做到这一点:
宏是从BUILD文件中调用的可以实例化规则的函数。宏并没有提供其他功能,它们仅用于封装和代码重用。在加载阶段结束时,宏不再存在,Bazel仅看到它们创建的规则集。
换句话说,您将需要(自定义)rule(s),您可以将输入传递给它们并使用它们,因为您需要在分析阶段和执行阶段建立它们之间的关系。这是宏无法帮助的。
我将这个例子放在一起,只要必要的load
就位,并且可以与您在问题中使用的BUILD
文件一起使用(这些规则已写入该接口): / p>
ComponentInfo = provider(fields = ["files", "name"])
BundleInfo = provider(fields = ["files", "name", "components"])
def _component_impl(ctx):
ctx.actions.write(
output = ctx.outputs.out,
content = "NAME: {}\n".format(ctx.attr.name),
)
return ComponentInfo(
files = depset([ctx.outputs.out]),
name = ctx.attr.name,
)
component = rule(
implementation = _component_impl,
outputs = {"out": "%{name}.txt"},
)
def _bundle_impl(ctx):
deps = depset(
[c[ComponentInfo] for c in ctx.attr.components] +
[c for b in ctx.attr.bundles for c in b[BundleInfo].components.to_list()],
)
content = "NAME: {}\n".format(ctx.attr.name)
for comp in deps.to_list():
content += "CONTAINS: {}\n".format(comp.name)
ctx.actions.write(
output = ctx.outputs.out,
content = content,
)
return BundleInfo(
files = depset([ctx.outputs.out]),
name = ctx.attr.name,
components = deps,
)
bundle = rule(
implementation = _bundle_impl,
attrs = {
"components": attr.label_list(),
"bundles": attr.label_list(),
},
outputs = {"out": "%{name}.txt"},
)
它没有任何用处。它只会创建一个文本文件,其中所有组件目标的组件名称都与捆绑目标相同,在这种情况下,它还会列出捆绑的所有组件。
我已经使用自定义提供程序来传递诸如组件信息之类的信息(假设它很重要),而不必借助某种魔术手段将其与生成的文件或标签名称区分开。