Introducción
¿Es la primera vez que usas Bazel? Estás en el lugar correcto. Sigue este instructivo de First Build para obtener una introducción simplificada sobre el uso de Bazel. En este instructivo, se definen los términos clave tal como se usan en el contexto de Bazel y se explican los conceptos básicos del flujo de trabajo de Bazel. Comenzarás con las herramientas que necesitas, y luego compilarás y ejecutarás tres proyectos con una complejidad cada vez mayor, y aprenderás cómo y por qué se vuelven más complejos.
Si bien Bazel es un sistema de compilación que admite compilaciones en varios lenguajes, este instructivo usa un proyecto de C++ como ejemplo y proporciona los lineamientos y el flujo generales que se aplican a la mayoría de los lenguajes.
Tiempo estimado de finalización: 30 minutos.
Requisitos previos
Comienza por instalar Bazel, si aún no lo hiciste. En este instructivo, se usa Git para el control de código fuente, por lo que, para obtener mejores resultados, instala Git también.
A continuación, recupera el proyecto de muestra del repositorio de GitHub de Bazel ejecutando lo siguiente en la herramienta de línea de comandos que prefieras:
git clone https://github.com/bazelbuild/examplesEl proyecto de muestra para este instructivo se encuentra en el examples/cpp-tutorial
directorio.
Observa cómo está estructurado:
examples
└── cpp-tutorial
├──stage1
│ ├── main
│ │ ├── BUILD
│ │ └── hello-world.cc
│ └── MODULE.bazel
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── MODULE.bazel
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── MODULE.bazel
Hay tres conjuntos de archivos, y cada uno representa una etapa de este instructivo. En la primera etapa, compilarás un solo destino que reside en un solo paquete. En la segunda etapa, compilarás un objeto binario y una biblioteca a partir de un solo paquete. En la tercera y última etapa, compilarás un proyecto con varios paquetes y lo compilarás con varios destinos.
Resumen: Introducción
Al instalar Bazel (y Git) y clonar el repositorio para este instructivo, sentaste las bases para tu primera compilación con Bazel. Continúa con la siguiente sección para definir algunos términos y configurar tu espacio de trabajo.
Cómo comenzar
Antes de compilar un proyecto, debes configurar su espacio de trabajo. Un espacio de trabajo es un directorio que contiene los archivos fuente de tu proyecto y los resultados de la compilación de Bazel. También contiene estos archivos importantes:
- El archivo
MODULE.bazel, que identifica el directorio y su contenido como un espacio de trabajo de Bazel y se encuentra en la raíz de la estructura de directorios del proyecto. También es donde especificas tus dependencias externas. - Contiene, además, uno o más
BUILDarchivos, que le indican a Bazel cómo compilar diferentes partes del proyecto. Un directorio dentro del espacio de trabajo que contiene unBUILDarchivo es un paquete. (Más información sobre los paquetes más adelante en este instructivo).
En proyectos futuros, para designar un directorio como un espacio de trabajo de Bazel, crea un
archivo vacío llamado MODULE.bazel en ese directorio. Para los fines de este
instructivo, ya hay un archivo MODULE.bazel en cada etapa.
Conceptos básicos sobre el archivo BUILD
Un BUILD archivo contiene varios tipos diferentes de instrucciones para Bazel. Cada
BUILD archivo requiere al menos una
regla como un conjunto de instrucciones,
que le indica a Bazel cómo compilar los resultados deseados, como objetos binarios
o bibliotecas ejecutables. Cada instancia de una regla de compilación en el archivo BUILD se denomina
destino y apunta a un conjunto
específico de archivos fuente y
dependencias. Un destino también puede
apuntar a otros destinos.
Observa el BUILD archivo en el cpp-tutorial/stage1/main directorio:
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
)
En nuestro ejemplo, el destino hello-world crea una instancia de regla
cc_binary integrada de Bazel. La regla
le indica a Bazel que compile un objeto binario ejecutable independiente a partir del
hello-world.cc> archivo fuente sin dependencias.
Resumen: cómo comenzar
Ahora estás familiarizado con algunos términos clave y lo que significan en el contexto de este proyecto y Bazel en general. En la siguiente sección, compilarás y probarás la etapa 1 del proyecto.
Etapa 1: un solo destino, un solo paquete
Es hora de compilar la primera parte del proyecto. A modo de referencia visual, la estructura de la sección de la etapa 1 del proyecto es la siguiente:
examples
└── cpp-tutorial
└──stage1
├── main
│ ├── BUILD
│ └── hello-world.cc
└── MODULE.bazel
Ejecuta lo siguiente para moverte al directorio cpp-tutorial/stage1:
cd cpp-tutorial/stage1Luego, ejecuta el siguiente comando:
bazel build //main:hello-worldEn la etiqueta de destino, la parte //main: es la ubicación del archivo BUILD
en relación con la raíz del espacio de trabajo, y hello-world es el nombre de destino en
el archivo BUILD.
Bazel produce algo como lo siguiente:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 2.267s, Critical Path: 0.25s
Acabas de compilar tu primer destino de Bazel. Bazel coloca los resultados de la compilación en el
bazel-bin directorio en la raíz del espacio de trabajo.
Ahora, prueba el objeto binario que acabas de compilar:
bazel-bin/main/hello-worldEsto genera un mensaje "Hello world" impreso.
Este es el gráfico de dependencias de la etapa 1:

Resumen: etapa 1
Ahora que completaste tu primera compilación, tienes una idea básica de cómo se estructura un a compilación. En la siguiente etapa, agregarás otro objetivo para aumentar la complejidad.
Etapa 2: varios objetivos de compilación
Si bien un solo destino es suficiente para proyectos pequeños, es posible que quieras dividir proyectos más grandes en varios destinos y paquetes. Esto permite compilaciones incrementales rápidas , es decir, Bazel solo vuelve a compilar lo que cambió, y acelera tus compilaciones mediante la compilación de varias partes de un proyecto a la vez. En esta etapa del instructivo, se agrega un destino, y en la siguiente, un paquete.
Este es el directorio con el que trabajarás para la etapa 2:
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── MODULE.bazel
Observa el BUILD archivo en el cpp-tutorial/stage2/main directorio:
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [
":hello-greet",
],
)
Con este archivo BUILD, Bazel primero compila la biblioteca hello-greet (con la regla cc_library
integrada de Bazel) y, luego, el objeto binario hello-world. El atributo deps en el destino hello-world le indica
a Bazel que se requiere la biblioteca hello-greet para compilar el objeto binario hello-world.
Antes de compilar esta nueva versión del proyecto, debes cambiar
los directorios y cambiar al directorio cpp-tutorial/stage2 ejecutando lo siguiente:
cd ../stage2Ahora puedes compilar el nuevo objeto binario con el siguiente comando conocido:
bazel build //main:hello-worldUna vez más, Bazel produce algo como lo siguiente:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 2.399s, Critical Path: 0.30s
Ahora puedes probar el objeto binario que acabas de compilar, que muestra otro "Hello
world":
bazel-bin/main/hello-worldSi ahora modificas hello-greet.cc y vuelves a compilar el proyecto, Bazel solo
vuelve a compilar ese archivo.
Si observas el gráfico de dependencias, puedes ver que hello-world depende de una
entrada adicional llamada hello-greet:

Resumen: etapa 2
Ahora compilaste el proyecto con dos destinos. El destino hello-world compila
un archivo fuente y depende de otro destino (//main:hello-greet), que
compila dos archivos fuente adicionales. En la siguiente sección, ve un paso más allá
y agrega otro paquete.
Etapa 3: varios paquetes
En la siguiente etapa, se agrega otra capa de complicación y se compila un proyecto con
varios paquetes. Observa la estructura y el contenido del
cpp-tutorial/stage3 directorio:
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── MODULE.bazel
Puedes ver que ahora hay dos subdirectorios, y cada uno contiene un BUILD
archivo. Por lo tanto, para Bazel, el espacio de trabajo ahora contiene dos paquetes: lib y
main.
Observa el archivo lib/BUILD:
cc_library(
name = "hello-time",
srcs = ["hello-time.cc"],
hdrs = ["hello-time.h"],
visibility = ["//main:__pkg__"],
)
Y el archivo main/BUILD:
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [
":hello-greet",
"//lib:hello-time",
],
)
El destino hello-world en el paquete principal depende del destino hello-time
en el paquete lib (por lo tanto, la etiqueta de destino //lib:hello-time). Bazel lo sabe
a través del atributo deps. Puedes ver esto reflejado en el gráfico de dependencias

Para que la compilación se realice correctamente, haces que el destino //lib:hello-time en lib/BUILD
sea explícitamente visible para los destinos en main/BUILD con el atributo de visibilidad.
Esto se debe a que, de forma predeterminada, los destinos solo son visibles para otros destinos en el mismo archivo BUILD. Bazel usa la visibilidad del destino para evitar problemas, como que las bibliotecas que contienen detalles de implementación se filtren en las APIs públicas.
Ahora compila esta versión final del proyecto. Cambia al cpp-tutorial/stage3
directorio ejecutando lo siguiente:
cd ../stage3Una vez más, ejecuta el siguiente comando:
bazel build //main:hello-worldBazel produce algo como lo siguiente:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 0.167s, Critical Path: 0.00s
Ahora prueba el último objeto binario de este instructivo para obtener un mensaje final Hello world:
bazel-bin/main/hello-worldResumen: etapa 3
Ahora compilaste el proyecto como dos paquetes con tres destinos y comprendes las dependencias entre ellos, lo que te permite seguir adelante y compilar proyectos futuros con Bazel. En la siguiente sección, observa cómo continuar tu recorrido por Bazel.
Próximos pasos
Ya completaste tu primera compilación básica con Bazel, pero esto es solo el comienzo. Estos son algunos recursos más para seguir aprendiendo con Bazel:
- Para seguir enfocándote en C++, lee sobre los casos de uso comunes de compilación de C++ casos.
- Para comenzar a compilar otras aplicaciones con Bazel, consulta los instructivos para Java, aplicaciones para Android o aplicaciones para iOS.
- Para obtener más información sobre cómo trabajar con repositorios locales y remotos, consulta sobre las dependencias externas.
- Para obtener más información sobre las otras reglas de Bazel, consulta esta guía de referencia.
¡Suerte en el proceso de compilación!