首页 > 解决方案 > 构建目标后,我可以让 bazel 触发额外的操作吗?

问题描述

我有一个产生工件的 bazel 规则。我应该如何添加一个后处理步骤,并将生成的工件作为依赖项?

我们有一个大型构建系统,其中我们的宏用于多个 BUILD 文件。因此,现在我需要添加另一个步骤,该步骤将使用特定宏生成的工件来创建另一个工件,并且希望无需更新所有 BUILD 文件。

在非 bazel 上下文中,我可能会使用触发额外步骤的东西,但在 bazel 上下文中,我想出的最好的方法是添加一个新宏,它使用另一个宏创建的规则作为依赖。

今天是这样的:
宏 M1 生成规则 R1 - 生成工件 A。构建文件
B 使用宏 M1,并且在构建该目标时生成工件 A。

所以我现在可以添加一个生成规则 R2 的宏 M2,它产生工件 B。
工件 A 是此规则的依赖项。
用户将改用宏 M2。

但我可以用其他方式做到这一点吗?

一个用例的例子可能是我有一个生成二进制文件的宏,我现在想添加例如签名。“用户”仍然希望构建该二进制文件,并且已签名的工件被创建为用户不太感兴趣的副产品。

标签: bazel

解决方案


您可以更新 M1 以调用 M2。

M1 调用 M2 只是声明规则。通常宏看起来像这样:

def M1(name, arg1, ...):
    R1(name=name, arg1=arg1, ...)

当您构建 M1 规则“//foo:bar”时,您实际上构建了名为“//foo:bar”的 R1。因此,您必须更新 M1 以使用名称以外的其他名称调用 R1,例如name + "dep",并使用 调用 M2name并将 R1name作为依赖项传递。因此,如果您构建“//foo:bar”,您将构建 M2 的底层规则 (R2),它依赖于 R1,因此 Bazel 首先构建 R1(并生成 A),然后是 R2(消耗 A)..

还有一件事:Bazel 在将规则加载到 BUILD 文件中之前,会将宏预处理为实际规则。您可以检查此预处理的结果,以查看您在包中实际拥有哪些规则,如下所示:

bazel query --output=build //foo:*

推荐阅读