Bazel admite dependencias externas, archivos de origen (tanto de texto como binarios) que se usan en tu compilación y que no son de tu espacio de trabajo. Por ejemplo, pueden 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 dependencias externas con Bazel: el sistema WORKSPACE
tradicional y centrado en el repositorio y el sistema MODULE.bazel
más reciente centrado en el módulo (con nombre interno Bzlmod y habilitado con la marca --enable_bzlmod
). Los dos sistemas se pueden usar juntos, pero Bzlmod reemplaza el sistema WORKSPACE
en versiones futuras de Bazel. Consulta la guía de migración 1Bzlmod}.
En este documento, se explican los conceptos relacionados con la administración de dependencias externas en Bazel, antes de analizar con más detalle los dos sistemas en orden.
Conceptos
Repositorio
Un directorio con un archivo WORKSPACE
o WORKSPACE.bazel
, que contiene archivos
de origen que se usarán en una compilación de Bazel. A menudo se abrevia como repo.
Repositorio principal
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 combinaron. El término "espacio de trabajo" a menudo se usa para referirse al repositorio principal y, a veces, incluso se usa como sinónimo de "repositorio".
Nombre del repositorio canónico
Es el nombre canónico al que se puede dirigir un repositorio. Dentro del contexto de un espacio de trabajo, cada repositorio tiene un solo nombre canónico. Un destino dentro de un repositorio cuyo nombre canónico es canonical_name
se puede abordar mediante la etiqueta @@canonical_name//pac/kage:target
(ten en cuenta que el @
doble).
El repositorio principal siempre tiene la cadena vacía como nombre canónico.
Nombre aparente del repositorio
Es el nombre al que se puede dirigir un repositorio en el contexto de otro repositorio determinado.
Se puede considerar como el “sobrenombre” de un repositorio: el repositorio con el nombre canónico michael
podría tener el nombre aparente mike
en el contexto del repositorio alice
, pero podría tener el nombre aparente mickey
en el contexto del repositorio bob
. En este caso, la etiqueta @mike//pac/kage:target
puede abordar un objetivo dentro de michael
en el contexto de alice
(observa el único @
).
Por el contrario, esto se puede interpretar como una asignación de repositorio: cada repositorio mantiene una asignación de "nombre aparente del repositorio" a "nombre de repositorio canónico".
Regla del repositorio
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 de una URL determinada y extraerlo", "recuperar un artefacto Maven determinado y ponerlo a disposición como objetivo java_import
" o simplemente "crear un symlink a un directorio local". Cada repositorio se define mediante una llamada a la regla del repositorio 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 repositorio más comunes son, con mucho, http_archive
, que descarga un archivo de una URL y lo extrae, y local_repository
, que crea un symlink a un directorio local que ya es un repositorio de Bazel.
Recupera un repositorio
La acción de hacer que un repositorio esté disponible en el disco local mediante la ejecución de su regla de repositorio asociada. Los repositorios definidos en un lugar de trabajo no están disponibles en el disco local antes de que se recuperen.
Por lo general, Bazel solo recupera un repo cuando necesita algo del repo y este aún no se recuperó. Si el repositorio ya se recuperó antes, Bazel solo lo vuelve a recuperar si su definición cambió.
Diseño del directorio
Después de recuperarlo, puedes encontrar el repositorio en el subdirectorio external
de la base de salida, debajo de 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 dependencia externa, no funciona directamente con definiciones de repositorio. En cambio, compila un gráfico de dependencia a partir de módulos, ejecuta extensiones sobre el gráfico y define los repositorios según corresponda.
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, que declara su nombre, su versión, la lista de dependencias y otra información. El siguiente es 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 consulta el registro nuevamente a fin de aprender a definir un repositorio para cada módulo
(en la mayoría de los casos, mediante http_archive
).
Los módulos también pueden especificar datos personalizados llamados etiquetas, que consumen las extensiones de módulos después de la resolución de módulos para definir repositorios adicionales. Estas extensiones tienen capacidades similares a las reglas del repo, lo que les permite realizar acciones como la E/S de archivos y el envío de 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 módulos de Bazel.
Vínculos externos en Bzlmod
- Ejemplos de uso de bzlmod en bazelbuild/ejemplos
- Revisión de 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 en Bzlmod
Define repositorios con WORKSPACE
Históricamente, puedes administrar dependencias externas si defines repositorios en el archivo WORKSPACE
(o WORKSPACE.bazel
). Este archivo tiene una sintaxis similar a los archivos BUILD
y emplea reglas de repo en lugar de reglas de compilación.
El siguiente fragmento es un ejemplo para usar la regla de 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 repositorio cuyo nombre canónico es foo
. En el sistema WORKSPACE
, de forma predeterminada, el nombre canónico de un repositorio también es su nombre aparente para todos los demás repositorios.
Consulta la lista completa de funciones disponibles en los archivos WORKSPACE
.
Desventajas del sistema WORKSPACE
En los años desde que se introdujo el sistema WORKSPACE
, los usuarios informaron varios problemas, como los 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 pide 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 de "deps" o hacer que el usuario llame a varias macros de "deps" con varias capas. - Bazel evalúa el archivo
WORKSPACE
de forma secuencial. Además, las dependencias se especifican mediantehttp_archive
con URLs, sin información de la versión. Eso significa que no hay una forma confiable de resolver la versión en el caso de dependencias de diamante (A
depende deB
yC
;B
yC
dependen de versiones diferentes deD
).
- Esto tiene sus propios problemas: las macros no pueden
Debido a las deficiencias de WORKSPACE, Bzlmod reemplazará el sistema WORKSPACE heredado en versiones futuras de Bazel. Lee la guía de migración de Bzlmod para descubrir cómo migrar a Bzlmod.