Cómo crear una macro simbólica

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

IMPORTANTE: Este instructivo es para las macros simbólicas, el nuevo sistema de macros que se introdujo en Bazel 8. Si necesitas admitir versiones anteriores de Bazel, te recomendamos que escribas una macro heredada. Consulta Cómo crear una macro heredada.

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 simbólica 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 de implementación y una declaración de macro en un archivo .bzl independiente y llama al archivo 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,
    },
)

Algunas observaciones:

  • Las funciones de implementación de macros simbólicas deben tener parámetros name y visibility. Se deben usar para el objetivo principal de la macro.

  • Para documentar el comportamiento de una macro simbólica, usa los parámetros doc para macro() y sus atributos.

  • Para llamar a un genrule o a cualquier otra regla nativa, usa native..

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

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