创建符号宏

报告问题 查看源代码 每夜 build · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

重要提示:本教程介绍了 符号宏,即 Bazel 8 中引入的新宏系统。如果您需要支持较低版本的 Bazel,则需要改为编写旧版宏;请参阅创建旧版宏

假设您需要在构建过程中运行某个工具。例如,您可能需要生成或预处理源文件,或者压缩二进制文件。在本教程中,您将创建一个用于调整图片大小的符号宏。

宏适用于简单的任务。如果您想执行更复杂的操作(例如添加对新编程语言的支持),不妨考虑创建规则。规则可让您拥有更大的控制力和灵活性。

若要创建用于调整图片大小的宏,最简单的方法是使用 genrule

genrule(
    name = "logo_miniature",
    srcs = ["logo.png"],
    outs = ["small_logo.png"],
    cmd = "convert $< -resize 100x100 $@",
)

cc_binary(
    name = "my_app",
    srcs = ["my_app.cc"],
    data = [":logo_miniature"],
)

如果您需要调整更多图片的大小,则可以重复使用该代码。为此,请在单独的 .bzl 文件中定义实现函数宏声明,并调用文件 miniature.bzl

# Implementation function
def _miniature_impl(name, visibility, src, size, **kwargs):
    native.genrule(
        name = name,
        visibility = visibility,
        srcs = [src],
        outs = [name + "_small_" + src.name],
        cmd = "convert $< -resize " + size + " $@",
        **kwargs,
    )

# Macro declaration
miniature = macro(
    doc = """Create a miniature of the src image.

    The generated file name will be prefixed with `name + "_small_"`.
    """,
    implementation = _miniature_impl,
    # Inherit most of genrule's attributes (such as tags and testonly)
    inherit_attrs = native.genrule,
    attrs = {
        "src": attr.label(
            doc = "Image file",
            allow_single_file = True,
            # Non-configurable because our genrule's output filename is
            # suffixed with src's name. (We want to suffix the output file with
            # srcs's name because some tools that operate on image files expect
            # the files to have the right file extension.)
            configurable = False,
        ),
        "size": attr.string(
            doc = "Output size in WxH format",
            default = "100x100",
        ),
        # Do not allow callers of miniature() to set srcs, cmd, or outs -
        # _miniature_impl overrides their values when calling native.genrule()
        "srcs": None,
        "cmd": None,
        "outs": None,
    },
)

以下是一些注意事项:

  • 符号宏实现函数必须具有 namevisibility 参数。它们应用于宏的主要目标。

  • 如需记录符号宏的行为,请为 macro() 及其属性使用 doc 参数。

  • 如需调用 genrule 或任何其他原生规则,请使用 native.

  • 使用 **kwargs 将额外的继承参数转发到底层 genrule(其运作方式与 Python 中完全相同)。这很有用,因为用户可以设置 tagstestonly 等标准属性。

现在,使用 BUILD 文件中的宏:

load("//path/to:miniature.bzl", "miniature")

miniature(
    name = "logo_miniature",
    src = "image.png",
)

cc_binary(
    name = "my_app",
    srcs = ["my_app.cc"],
    data = [":logo_miniature"],
)