Criar uma macro legada

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

IMPORTANTE: este tutorial é para macros legadas. Se você só precisar oferecer suporte ao Bazel 8 ou mais recente, recomendamos o uso de macros simbólicas. Confira Como criar uma macro simbólica.

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 legada 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 em um arquivo .bzl separado e chame o arquivo de miniature.bzl:

def miniature(name, src, size = "100x100", **kwargs):
    """Create a miniature of the src image.

    The generated file is prefixed with 'small_'.
    """
    native.genrule(
        name = name,
        srcs = [src],
        # Note that the line below will fail if `src` is not a filename string
        outs = ["small_" + src],
        cmd = "convert $< -resize " + size + " $@",
        **kwargs
    )

Algumas observações:

  • Por convenção, as macros legadas têm um argumento name, assim como as regras.

  • Para documentar o comportamento de uma macro legada, use docstring, como no Python.

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

  • Use **kwargs para encaminhar os argumentos extras para o genrule subjacente. Ele funciona da mesma forma que no Python. Isso é útil para que um usuário possa usar atributos padrão, como visibility ou tags.

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

Por fim, um aviso: a macro pressupõe que src é uma string de nome de arquivo. Caso contrário, outs = ["small_" + src] vai falhar. O src = "image.png" funciona, mas o que acontece se o arquivo BUILD usar src = "//other/package:image.png" ou até mesmo src = select(...)?

É necessário declarar essas suposições na documentação da macro. Infelizmente, as macros legadas, especialmente as grandes, tendem a ser frágeis porque pode ser difícil notar e documentar todas essas suposições no código. Além disso, alguns usuários da macro não vão ler a documentação. Recomendamos, se possível, usar macros simbólicas, que têm verificações integradas em tipos de atributos.