Bazel compila software a partir del código fuente organizado en un árbol de directorios llamado espacio de trabajo. Los archivos fuente del espacio de trabajo se organizan en una jerarquía anidada de paquetes, en la que cada paquete es un directorio que contiene un conjunto de archivos fuente relacionados y un archivo BUILD
. El archivo BUILD
especifica qué resultados de software se pueden compilar a partir del código fuente.
Workspace
Un espacio de trabajo es un árbol de directorios en tu sistema de archivos que contiene los archivos fuente del software que deseas compilar. Cada espacio de trabajo tiene un archivo de texto llamado WORKSPACE
que puede estar vacío o contener referencias a dependencias externas necesarias para compilar los resultados.
Los directorios que contienen un archivo llamado WORKSPACE
se consideran la raíz de un espacio de trabajo. Por lo tanto, Bazel ignora cualquier árbol de directorios en un espacio de trabajo cuya raíz se encuentre en un subdirectorio que contenga un archivo WORKSPACE
, ya que forman otro espacio de trabajo.
Bazel también admite el archivo WORKSPACE.bazel
como alias del archivo WORKSPACE
. Si existen ambos archivos, se usa WORKSPACE.bazel
.
Repositorios
El código se organiza en repositorios. El directorio que contiene el archivo WORKSPACE
es la raíz del repositorio principal, también llamado @
. Otros repositorios (externos) se definen en el archivo WORKSPACE
con reglas del espacio de trabajo o se generan a partir de módulos y extensiones en el sistema Bzlmod. Consulta la descripción general de las dependencias externas para obtener más información.
Las reglas del espacio de trabajo incluidas en Bazel se documentan en la sección Workspace Rules de la Build Encyclopedia y en la documentación sobre las reglas del repositorio de Starlark integradas.
Como los repositorios externos son repositorios en sí mismos, a menudo también contienen un archivo WORKSPACE
. Sin embargo, Bazel ignora estos archivos WORKSPACE
adicionales. En particular, los repositorios de los que se depende de forma transitiva no se agregan automáticamente.
Paquetes
La unidad principal de organización del código en un repositorio es el paquete. Un paquete es una colección de archivos relacionados y una especificación de cómo se pueden usar para producir artefactos de salida.
Un paquete se define como un directorio que contiene un archivo BUILD
llamado BUILD
o BUILD.bazel
. Un paquete incluye todos los archivos de su directorio, además de todos los subdirectorios que se encuentran debajo de él, excepto aquellos que contienen un archivo BUILD
. Según esta definición, ningún archivo o directorio puede formar parte de dos paquetes diferentes.
Por ejemplo, en el siguiente árbol de directorios, hay dos paquetes, my/app
, y el subpaquete my/app/tests
. Ten en cuenta que my/app/data
no es un paquete, sino un directorio que pertenece al paquete my/app
.
src/my/app/BUILD
src/my/app/app.cc
src/my/app/data/input.txt
src/my/app/tests/BUILD
src/my/app/tests/test.cc
Destinos
Un paquete es un contenedor de destinos, que se definen en el archivo BUILD
del paquete. La mayoría de los destinos son de uno de los dos tipos principales: archivos y reglas.
Los archivos se dividen en dos tipos. Los archivos fuente suelen escribirse gracias al esfuerzo de las personas y se registran en el repositorio. Los archivos generados, a veces denominados archivos derivados o archivos de salida, no se registran, sino que se generan a partir de archivos fuente.
El segundo tipo de destino se declara con una regla. Cada instancia de regla especifica la relación entre un conjunto de archivos de entrada y un conjunto de archivos de salida. Las entradas de una regla pueden ser archivos fuente, pero también pueden ser las salidas de otras reglas.
En la mayoría de los casos, no importa si la entrada de una regla es un archivo fuente o un archivo generado; lo único que importa es el contenido de ese archivo. Este hecho facilita el reemplazo de un archivo fuente complejo por un archivo generado producido por una regla, como sucede cuando la carga de mantener manualmente un archivo altamente estructurado se vuelve demasiado tediosa y alguien escribe un programa para derivarlo. No se requiere ningún cambio en los consumidores de ese archivo. Por el contrario, un archivo generado se puede reemplazar fácilmente por un archivo fuente con solo cambios locales.
Las entradas de una regla también pueden incluir otras reglas. El significado preciso de esas relaciones suele ser bastante complejo y depende del lenguaje o de la regla, pero, intuitivamente, es simple: una regla A de biblioteca de C++ podría tener otra regla B de biblioteca de C++ para una entrada. El efecto de esta dependencia es que los archivos de encabezado de B están disponibles para A durante la compilación, los símbolos de B están disponibles para A durante la vinculación y los datos de tiempo de ejecución de B están disponibles para A durante la ejecución.
Una invariante de todas las reglas es que los archivos que genera una regla siempre pertenecen al mismo paquete que la regla en sí. No es posible generar archivos en otro paquete. Sin embargo, no es raro que las entradas de una regla provengan de otro paquete.
Los grupos de paquetes son conjuntos de paquetes cuyo propósito es limitar la accesibilidad de ciertas reglas. Los grupos de paquetes se definen con la función package_group
. Tienen tres propiedades: la lista de paquetes que contienen, su nombre y otros grupos de paquetes que incluyen. Las únicas formas permitidas de hacer referencia a ellos son desde el atributo visibility
de las reglas o desde el atributo default_visibility
de la función package
. No generan ni consumen archivos. Para obtener más información, consulta la documentación de package_group
.