Cómo crear una macro heredada

Denuncia un problema Ver fuente Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

IMPORTANTE: Este instructivo es para macros heredadas. Si solo necesitas admitir Bazel 8 o versiones posteriores, te recomendamos que uses macros simbólicas. Consulta Cómo crear una macro simbólica.

Imagina que necesitas ejecutar una herramienta como parte de tu compilación. Por ejemplo, es posible que desees generar o preprocesar un archivo fuente, o comprimir un archivo binario. En este instructivo, crearás una macro heredada que cambie el tamaño de una imagen.

Las macros son adecuadas para tareas simples. Si quieres hacer algo más completo, por ejemplo, agregar compatibilidad con un nuevo lenguaje de programación, considera crear una regla. Las reglas te brindan más control y flexibilidad.

La forma más sencilla de crear una macro que cambie el tamaño de una imagen es usar un 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"],
)

Si necesitas cambiar el tamaño de más imágenes, te recomendamos que vuelvas a usar el código. Para ello, define una función en un archivo .bzl independiente y llama al archivo 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
    )

Algunas observaciones:

  • De forma convencional, las macros heredadas tienen un argumento name, al igual que las reglas.

  • Para documentar el comportamiento de una macro heredada, usa una cadena de documentos como en Python.

  • Para llamar a una genrule o a cualquier otra regla nativa, agrega el prefijo native..

  • Usa **kwargs para reenviar los argumentos adicionales al genrule subyacente (funciona de la misma manera que en Python). Esto es útil para que un usuario pueda usar atributos estándar, como visibility o tags.

Ahora, usa la macro del archivo 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 último, una nota de advertencia: La macro supone que src es una cadena de nombre de archivo (de lo contrario, outs = ["small_" + src] fallará). Por lo tanto, src = "image.png" funciona, pero ¿qué sucede si el archivo BUILD usa src = "//other/package:image.png" o incluso src = select(...)?

Debes asegurarte de declarar esas suposiciones en la documentación de tu macro. Lamentablemente, las macros heredadas, en especial las grandes, tienden a ser frágiles porque puede ser difícil detectar y documentar todas esas suposiciones en tu código y, por supuesto, algunos usuarios de la macro no leerán la documentación. Si es posible, te recomendamos que uses macros simbólicas, que tienen verificaciones integradas en los tipos de atributos.