【问题标题】:Bazel -- get arguments to another target macroBazel -- 获取另一个目标宏的参数
【发布时间】:2019-08-26 17:28:06
【问题描述】:

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

【问题讨论】:

  • componentsbundle 中是如何使用的?它们最终会出现在原生规则的领域吗?

标签: bazel


【解决方案1】:

macro(单独)无法做到这一点:

宏是从 BUILD 文件调用的函数,可以实例化规则。宏不会提供额外的功能,它们只是用于封装和代码重用。在加载阶段结束时,宏不再存在,Bazel 只能看到它们创建的规则集。

换句话说,您需要(自定义)rule(s),您可以将输入传递给并使用它,因为您需要在分析阶段和执行阶段建立它们的关系。这是宏无法解决的问题。

我已经把这个例子放在一起,提供必要的load,它适用于你在问题中使用的BUILD文件(这些规则被写入该接口):

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

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

我使用自定义提供程序来传递诸如组件信息之类的信息(假设它很重要),而无需借助某种魔法从生成的文件或标签名称中进行预测。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-28
    • 1970-01-01
    相关资源
    最近更新 更多