Introducción
¿Es la primera vez que usas Bazel? Está en el lugar correcto. Sigue este instructivo de Primera compilación para obtener una introducción simplificada al 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. Comenzando con las herramientas que necesitas, compilarás y ejecutarás tres proyectos con una complejidad creciente 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, en este instructivo, se usa un proyecto de C++ como ejemplo y se proporcionan los lineamientos generales y el flujo que se aplican a la mayoría de los lenguajes.
Tiempo estimado de finalización: 30 minutos.
Requisitos previos
Primero, instala Bazel si aún no lo lo hiciste. En este instructivo, se usa Git para el control de código fuente, por lo que también debes instalar Git para obtener mejores resultados.
A continuación, ejecuta el siguiente comando para recuperar el proyecto de muestra del repositorio de GitHub de Bazel en la herramienta de línea de comandos que elijas:
git clone https://github.com/bazelbuild/examples
El proyecto de muestra para este instructivo se encuentra en el directorio examples/cpp-tutorial
.
Observa a continuación cómo están estructurados:
examples
└── cpp-tutorial
├──stage1
│ ├── main
│ │ ├── BUILD
│ │ └── hello-world.cc
│ └── WORKSPACE
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── WORKSPACE
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── WORKSPACE
Hay tres conjuntos de archivos, y cada uno representa una etapa en 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 con varios destinos.
Resumen: Introducción
Si instalas Bazel (y Git) y clonas el repositorio de 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 lugar de trabajo.
Primeros pasos
Configura el lugar de trabajo
Antes de compilar un proyecto, debes configurar su lugar de trabajo. Un lugar de trabajo es un directorio que contiene los archivos fuente de tu proyecto y los resultados de compilación de Bazel. También contiene los siguientes archivos significativos:
- El
, que identifica el directorio y su contenido como un lugar de trabajo de Bazel y reside en la raíz de la estructura del directorio del proyectoWORKSPACE
file - Uno o más
, que le indican a Bazel cómo compilar diferentes partes del proyecto Un directorio dentro del lugar de trabajo que contiene un archivoBUILD
filesBUILD
es un paquete. (más adelante en este instructivo, encontrarás más información sobre los paquetes).
En proyectos futuros, crea un
archivo vacío llamado WORKSPACE
en ese directorio para designar un directorio como un lugar de trabajo de Bazel. Para los fines de este instructivo, ya hay un archivo WORKSPACE
en cada etapa.
NOTA: Cuando Bazel compila el proyecto, todas las entradas deben estar en el mismo lugar de trabajo. Los archivos que se encuentran en lugares de trabajo diferentes son independientes entre sí, a menos que estén vinculados. Puedes encontrar información más detallada sobre las reglas del lugar de trabajo en esta guía.
Comprende el archivo BUILD
Un archivo BUILD
contiene varios tipos diferentes de instrucciones para Bazel. Cada
archivo BUILD
requiere al menos una regla
como conjunto de instrucciones, que le indica a Bazel cómo compilar los resultados deseados,
como bibliotecas o objetos binarios 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 de origen y dependencias.
Un objetivo también puede apuntar a otros objetivos.
Observa el archivo BUILD
en el directorio cpp-tutorial/stage1/main
:
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
)
En nuestro ejemplo, el destino hello-world
crea una instancia del cc_binary rule
integrado de Bazel.
La regla le indica a Bazel que compile un objeto binario ejecutable autónomo a partir del archivo de origen hello-world.cc
sin dependencias.
Resumen: primeros pasos
Ahora conoces algunos términos clave y lo que significan en el contexto de este proyecto y de 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 construir la primera parte del proyecto. Para una 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
└── WORKSPACE
Ejecuta lo siguiente para pasar al directorio cpp-tutorial/stage1
:
cd cpp-tutorial/stage1
Luego, ejecute el siguiente comando:
bazel build //main:hello-world
En la etiqueta de destino, la parte //main:
es la ubicación del archivo BUILD
en relación con la raíz del lugar de trabajo y hello-world
es el nombre del destino en el archivo BUILD
.
Bazel produce algo que se ve de la siguiente manera:
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 directorio bazel-bin
, en la raíz del lugar de trabajo.
Ahora, prueba tu objeto binario recién compilado, que se ve así:
bazel-bin/main/hello-world
Se mostrará el mensaje "Hello world
" impreso.
Este es el gráfico de dependencia de la etapa 1:
Resumen: etapa 1
Ahora que completaste tu primera compilación, tienes una idea básica de cómo se estructura. En la siguiente etapa, agregarás complejidad si agregas otro destino.
Etapa 2: Varios destinos de compilación
Si bien un solo destino es suficiente para proyectos pequeños, te recomendamos que dividas los 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 compilando varias partes de un proyecto a la vez. En esta etapa del instructivo, se agrega un destino y en la siguiente se agrega un paquete.
Este es el directorio con el que estás trabajando para la Etapa 2:
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── WORKSPACE
Observa el siguiente archivo BUILD
en el directorio cpp-tutorial/stage2/main
:
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 el cc_library rule
integrado 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 pasar al directorio cpp-tutorial/stage2
. Para ello, ejecuta lo siguiente:
cd ../stage2
Ahora puedes compilar el objeto binario nuevo con el siguiente comando que ya conoces:
bazel build //main:hello-world
Una vez más, Bazel produce algo que se ve de la siguiente manera:
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 tu objeto binario recién compilado, que muestra otro “Hello world
”:
bazel-bin/main/hello-world
Si ahora modificas hello-greet.cc
y vuelves a compilar el proyecto, Bazel solo vuelve a compilar
ese archivo.
Si observas el gráfico de dependencia, podrás ver que hello-world
depende de una entrada adicional llamada hello-greet
:
Resumen: etapa 2
Ya compilaste el proyecto con dos objetivos. El destino hello-world
compila un archivo de origen y depende de otro destino (//main:hello-greet
), que compila dos archivos de origen 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 directorio cpp-tutorial/stage3
a continuación:
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── WORKSPACE
Puedes ver que ahora hay dos subdirectorios, y cada uno contiene un archivo BUILD
. Por lo tanto, para Bazel, el lugar 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__"],
)
En el archivo main/BUILD
, haz lo siguiente:
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 dependencia:
Para que la compilación tenga éxito, debes hacer que el objetivo //lib:hello-time
de lib/BUILD
sea visible de manera explícita para los destinos de main/BUILD
mediante el atributo de visibilidad.
Esto se debe a que, de forma predeterminada, los destinos son visibles solo para otros destinos en el mismo archivo BUILD
. Bazel usa la visibilidad del objetivo para evitar problemas como las bibliotecas
que contienen detalles de implementación que se filtran en APIs públicas.
Ahora, compila esta versión final del proyecto. Para cambiar al directorio cpp-tutorial/stage3
, ejecuta lo siguiente:
cd ../stage3
Vuelve a ejecutar el siguiente comando:
bazel build //main:hello-world
Bazel produce algo que se ve de la siguiente manera:
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-world
Resumen: etapa 3
Ya compilaste el proyecto como dos paquetes con tres destinos y comprendes las dependencias entre ellos, lo que te prepara para continuar y compilar proyectos futuros con Bazel. En la siguiente sección, verás cómo continuar tu recorrido de Bazel.
Próximos pasos
Completaste tu primera compilación básica con Bazel, pero este es solo el comienzo. Estos son algunos recursos más para seguir aprendiendo con Bazel:
- Para enfocarte en C++, lee sobre los casos de uso comunes de compilación de C++.
- Si quieres comenzar a compilar otras aplicaciones con Bazel, consulta los instructivos sobre Java, aplicación para Android o aplicación para iOS).
- Para obtener más información sobre cómo trabajar con repositorios locales y remotos, consulta las dependencias externas.
- Para obtener más información sobre las otras reglas de Bazel, consulta esta guía de referencia.
¡Disfruta creando!