Bazel admite dependencias externas, archivos fuente (tanto de texto como binarios) que se usan en tu compilación y que no provienen de tu espacio de trabajo. Por ejemplo, podrían ser un conjunto de reglas alojado en un repositorio de GitHub, un artefacto de Maven o un directorio en tu máquina local fuera de tu espacio de trabajo actual.
A partir de Bazel 6.0, hay dos formas de administrar las dependencias externas con Bazel: el sistema WORKSPACE
tradicional centrado en el repositorio y el sistema MODULE.bazel
más reciente centrado en el módulo (con el nombre interno Bzlmod y habilitado con la marca --enable_bzlmod
). Los dos sistemas se pueden usar juntos, pero Bzlmod reemplazará al sistema WORKSPACE
en futuras versiones de Bazel. Consulta la guía de migración de Bzlmod para obtener información sobre cómo migrar.
En este documento, se explican los conceptos relacionados con la administración de dependencias externas en Bazel antes de detallar un poco más los dos sistemas en orden.
Conceptos
Repositorio
Es un directorio con un archivo WORKSPACE
o WORKSPACE.bazel
que contiene archivos fuente para usar en una compilación de Bazel. A menudo, se abrevia como repo.
Repositorio principal
Es el repositorio en el que se ejecuta el comando de Bazel actual.
Workspace
El entorno que comparten todos los comandos de Bazel se ejecuta en el mismo repositorio principal.
Ten en cuenta que, históricamente, los conceptos de "repositorio" y "espacio de trabajo" se han fusionado. El término "espacio de trabajo" se ha usado a menudo para hacer referencia al repositorio principal y, a veces, incluso como sinónimo de "repositorio".
Nombre canónico del repositorio
Es el nombre canónico por el que se puede direccionar un repositorio. En el contexto de un espacio de trabajo, cada repositorio tiene un solo nombre canónico. Se puede hacer referencia a un destino dentro de un repo cuyo nombre canónico es canonical_name
con la etiqueta @@canonical_name//pac/kage:target
(ten en cuenta el doble @
).
El repositorio principal siempre tiene la cadena vacía como nombre canónico.
Nombre aparente del repositorio
Es el nombre con el que se puede direccionar un repositorio en el contexto de otro repositorio.
Se puede considerar como el "apodo" de un repo: el repo con el nombre canónico michael
podría tener el nombre aparente mike
en el contexto del repo alice
, pero podría tener el nombre aparente mickey
en el contexto del repo bob
. En este caso, se puede hacer referencia a un destino dentro de michael
con la etiqueta @mike//pac/kage:target
en el contexto de alice
(ten en cuenta el único @
).
A la inversa, esto se puede entender como una asignación de repositorios: cada repositorio mantiene una asignación del "nombre aparente del repositorio" a un "nombre canónico del repositorio".
Regla del repositorio
Es un esquema para las definiciones de repositorios que le indica a Bazel cómo materializar un repositorio. Por ejemplo, podría ser "descargar un archivo ZIP desde una URL determinada y extraerlo", "recuperar un artefacto de Maven determinado y ponerlo a disposición como un destino de java_import
" o simplemente "crear un vínculo simbólico a un directorio local". Cada repo se define llamando a una regla de repo con una cantidad adecuada de argumentos.
Consulta Reglas del repositorio para obtener más información sobre cómo escribir tus propias reglas del repositorio.
Las reglas de repositorios más comunes son, por lejos, http_archive
, que descarga un archivo de una URL y lo extrae, y local_repository
, que crea un vínculo simbólico a un directorio local que ya es un repositorio de Bazel.
Cómo recuperar un repositorio
Es la acción de hacer que un repo esté disponible en el disco local ejecutando su regla de repo asociada. Los repositorios definidos en un espacio de trabajo no están disponibles en el disco local antes de que se recuperen.
Normalmente, Bazel solo recupera un repo cuando necesita algo de él y el repo aún no se recuperó. Si el repo ya se recuperó antes, Bazel solo lo vuelve a recuperar si cambió su definición.
Diseño del directorio
Después de recuperarse, el repo se puede encontrar en el subdirectorio external
de la base de salida, con su nombre canónico.
Puedes ejecutar el siguiente comando para ver el contenido del repositorio con el nombre canónico canonical_name
:
ls $(bazel info output_base)/external/ canonical_name
Administra dependencias externas con Bzlmod
Bzlmod, el nuevo subsistema de dependencias externas, no funciona directamente con las definiciones de repositorios. En cambio, crea un gráfico de dependencias a partir de módulos, ejecuta extensiones sobre el gráfico y define los repositorios en consecuencia.
Un módulo de Bazel es un proyecto de Bazel que puede tener varias versiones, cada una de las cuales publica metadatos sobre otros módulos de los que depende. Un módulo debe tener un archivo MODULE.bazel
en la raíz del repositorio, junto al archivo WORKSPACE
. Este archivo es el manifiesto del módulo, en el que se declara su nombre, versión, lista de dependencias, entre otra información. A continuación, se muestra un ejemplo básico:
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "protobuf", version = "3.19.0")
Un módulo solo debe enumerar sus dependencias directas, que Bzlmod busca en un registro de Bazel (de forma predeterminada, el registro central de Bazel). El registro proporciona los archivos MODULE.bazel
de las dependencias, lo que permite que Bazel descubra todo el gráfico de dependencias transitivas antes de realizar la resolución de versiones.
Después de la resolución de la versión, en la que se selecciona una versión para cada módulo, Bazel vuelve a consultar el registro para saber cómo definir un repo para cada módulo (en la mayoría de los casos, con http_archive
).
Los módulos también pueden especificar fragmentos de datos personalizados llamados etiquetas, que las extensiones de módulos consumen después de la resolución del módulo para definir repositorios adicionales. Estas extensiones tienen capacidades similares a las reglas del repositorio, lo que les permite realizar acciones como E/S de archivos y enviar solicitudes de red. Entre otras cosas, permiten que Bazel interactúe con otros sistemas de administración de paquetes y, al mismo tiempo, respetan el gráfico de dependencias creado a partir de los módulos de Bazel.
Vínculos externos en Bzlmod
- Ejemplos de uso de Bzlmod en bazelbuild/examples
- Revisión general de las dependencias externas de Bazel (documento de diseño original de Bzlmod)
- Charla de BazelCon 2021 sobre Bzlmod
- Charla del Día de la comunidad de Bazel sobre Bzlmod
Define repositorios con WORKSPACE
Históricamente, puedes administrar dependencias externas definiendo repositorios en el archivo WORKSPACE
(o WORKSPACE.bazel
). Este archivo tiene una sintaxis similar a la de los archivos BUILD
, y utiliza reglas de repo en lugar de reglas de compilación.
El siguiente fragmento es un ejemplo para usar la regla del repo http_archive
en el archivo WORKSPACE
:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "foo",
urls = ["https://example.com/foo.zip"],
sha256 = "c9526390a7cd420fdcec2988b4f3626fe9c5b51e2959f685e8f4d170d1a9bd96",
)
El fragmento define un repo cuyo nombre canónico es foo
. En el sistema WORKSPACE
, de forma predeterminada, el nombre canónico de un repo también es su nombre aparente para todos los demás repos.
Consulta la lista completa de funciones disponibles en los archivos WORKSPACE
.
Deficiencias del sistema WORKSPACE
En los años transcurridos desde que se introdujo el sistema WORKSPACE
, los usuarios informaron muchas dificultades, entre ellas las siguientes:
- Bazel no evalúa los archivos
WORKSPACE
de ninguna dependencia, por lo que todas las dependencias transitivas deben definirse en el archivoWORKSPACE
del repositorio principal, además de las dependencias directas. - Para solucionar este problema, los proyectos adoptaron el patrón "deps.bzl", en el que definen una macro que, a su vez, define varios repositorios y les piden a los usuarios que llamen a esta macro en sus archivos
WORKSPACE
.- Esto tiene sus propios problemas: las macros no pueden
load
otros archivos.bzl
, por lo que estos proyectos deben definir sus dependencias transitivas en esta macro "deps" o solucionar este problema haciendo que el usuario llame a varias macros "deps" en capas. - Bazel evalúa el archivo
WORKSPACE
de forma secuencial. Además, las dependencias se especifican conhttp_archive
y URLs, sin información de versión. Esto significa que no hay una forma confiable de resolver la versión en el caso de las dependencias de diamante (A
depende deB
yC
;B
yC
dependen de diferentes versiones deD
).
- Esto tiene sus propios problemas: las macros no pueden
Debido a las deficiencias de WORKSPACE, Bzlmod reemplazará el sistema heredado de WORKSPACE en futuras versiones de Bazel. Lee la guía de migración de Bzlmod para saber cómo migrar a Bzlmod.