Bazel-获取另一个目标宏的参数

时间:2019-08-26 17:28:06

标签: bazel

我有两个宏/目标:组件和捆绑包(打包了几个组件)。我想扩展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或达到相同的效果?

1 个答案:

答案 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"},
)

它没有任何用处。它只会创建一个文本文件,其中所有组件目标的组件名称都与捆绑目标相同,在这种情况下,它还会列出捆绑的所有组件。

我已经使用自定义提供程序来传递诸如组件信息之类的信息(假设它很重要),而不必借助某种魔术手段将其与生成的文件或标签名称区分开。