En esta página, se describe cómo extender el lenguaje BUILD con macros y reglas.
Las extensiones de Bazel son archivos que terminan en .bzl
. Usa una instrucción de carga para importar un símbolo desde una extensión.
Antes de aprender los conceptos más avanzados, primero debes hacer lo siguiente:
Obtén información sobre el lenguaje Starlark, que se usa en los archivos
BUILD
y.bzl
.Obtén información sobre cómo compartir variables entre dos archivos
BUILD
.
Macros y reglas
Una macro es una función que crea instancias de reglas. Hay dos tipos de macros: macros simbólicas (novedad de Bazel 8) y macros heredadas. Los dos tipos de macros se definen de manera diferente, pero se comportan casi de la misma manera desde el punto de vista del usuario. Una macro es útil cuando un archivo BUILD
se vuelve demasiado repetitivo o complejo, ya que te permite reutilizar parte del código. La función se evalúa en cuanto se lee el archivo BUILD
. Después de la evaluación del archivo BUILD
, Bazel tiene poca información sobre las macros. Si tu macro genera un genrule
, Bazel se comportará casi como si hubieras declarado ese genrule
en el archivo BUILD
. (La única excepción es que los destinos declarados en una macro simbólica tienen una semántica de visibilidad especial: una macro simbólica puede ocultar sus destinos internos del resto del paquete).
Una regla es más potente que una macro. Puede acceder a los elementos internos de Bazel y tener control total sobre lo que sucede. Por ejemplo, puede pasar información a otras reglas.
Si deseas reutilizar una lógica simple, comienza con una macro. Te recomendamos una macro simbólica, a menos que necesites admitir versiones anteriores de Bazel. Si una macro se vuelve compleja, suele ser una buena idea convertirla en una regla. Por lo general, la compatibilidad con un idioma nuevo se realiza con una regla. Las reglas son para usuarios avanzados, y la mayoría de los usuarios nunca tendrán que escribir una; solo cargarán y llamarán a las reglas existentes.
Modelo de evaluación
Una compilación consta de tres fases.
Fase de carga. Primero, carga y evalúa todas las extensiones y todos los archivos
BUILD
que se necesitan para la compilación. La ejecución de los archivosBUILD
simplemente crea instancias de reglas (cada vez que se llama a una regla, se agrega a un gráfico). Aquí es donde se evalúan las macros.Fase de análisis. Se ejecuta el código de las reglas (su función
implementation
) y se crean instancias de las acciones. Una acción describe cómo generar un conjunto de resultados a partir de un conjunto de entradas, como "ejecuta gcc en hello.c y obtén hello.o". Debes enumerar de forma explícita los archivos que se generarán antes de ejecutar los comandos reales. En otras palabras, la fase de análisis toma el grafo generado por la fase de carga y genera un grafo de acción.Fase de ejecución. Las acciones se ejecutan cuando se requiere al menos uno de sus resultados. Si falta un archivo o si un comando no genera un resultado, la compilación falla. También se ejecutan pruebas durante esta fase.
Bazel usa el paralelismo para leer, analizar y evaluar los archivos .bzl
y BUILD
. Un archivo se lee como máximo una vez por compilación, y el resultado de la evaluación se almacena en caché y se reutiliza. Un archivo se evalúa solo una vez que se resuelven todas sus dependencias (sentencias load()
). Por diseño, cargar un archivo .bzl
no tiene efectos secundarios visibles, solo define valores y funciones.
Bazel intenta ser inteligente: usa el análisis de dependencias para saber qué archivos se deben cargar, qué reglas se deben analizar y qué acciones se deben ejecutar. Por ejemplo, si una regla genera acciones que no necesitas para la compilación actual, no se ejecutarán.
Cómo crear extensiones
Crea tu primera macro para reutilizar código. Luego, obtén más información sobre las macros y cómo usarlas para crear "verbos personalizados".
Sigue el instructivo sobre las reglas para comenzar a usarlas. A continuación, puedes obtener más información sobre los conceptos de reglas.
Los dos vínculos que se incluyen a continuación serán muy útiles cuando escribas tus propias extensiones. Mantén los dispositivos al alcance:
Más allá
Además de las macros y las reglas, es posible que desees escribir aspectos y reglas de repositorio.
Usa Buildifier de forma coherente para dar formato a tu código y realizar un análisis de lint.
Sigue la guía de estilo de
.bzl
.Prueba tu código.
Genera documentación para ayudar a los usuarios.
Optimiza el rendimiento de tu código.
Implementa tus extensiones para otras personas.