Como criar uma macro simbólica

Reportar um problema Ver código-fonte Nightly · 8.0 . 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

IMPORTANTE: este tutorial é para macros simbólicas, o novo sistema de macros introduzido no Bazel 8. Se você precisar oferecer suporte a versões mais antigas do Bazel, escreva uma macro legada. Confira como criar uma macro legada.

Imagine que você precisa executar uma ferramenta como parte do seu build. Por exemplo, você pode gerar ou pré-processar um arquivo de origem ou compactar um binário. Neste tutorial, você vai criar uma macro simbólica que redimensiona uma imagem.

As macros são adequadas para tarefas simples. Se você quiser fazer algo mais complicado, como adicionar suporte a uma nova linguagem de programação, considere criar uma regra. As regras oferecem mais controle e flexibilidade.

A maneira mais fácil de criar uma macro que redimensiona uma imagem é usar um 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"],
)

Se você precisar redimensionar mais imagens, use o código novamente. Para fazer isso, defina uma função de implementação e uma declaração de macro em um arquivo .bzl separado e chame o arquivo de 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,
    },
)

Algumas observações:

  • As funções de implementação de macros simbólicas precisam ter parâmetros name e visibility. Eles devem ser usados para o alvo principal da macro.

  • Para documentar o comportamento de uma macro simbólica, use parâmetros doc para macro() e os atributos dela.

  • Para chamar uma genrule ou qualquer outra regra nativa, use native..

  • Use **kwargs para encaminhar os argumentos herdados extras para o genrule (funciona exatamente como no Python). Isso é útil para que um usuário possa definir atributos padrão, como tags ou testonly.

Agora, use a macro do arquivo 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"],
)