Descripción general de las dependencias externas

Informar un problema Ver fuente

Bazel admite dependencias externas, archivos de origen (tanto de texto como binarios) utilizados en la compilación que no son del lugar 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 lugar de trabajo actual.

A partir de Bazel 6.0, existen dos formas de administrar dependencias externas con Bazel: el sistema WORKSPACE tradicional enfocado en el repositorio y el sistema MODULE.bazel más reciente enfocado en el módulo (con el nombre interno Bzlmod, 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 cómo migrar Bzlmod.{/1

En este documento, se explican los conceptos relacionados con la administración de dependencias externas en Bazel, antes de entrar en más detalles sobre los dos sistemas en orden.

Conceptos

Repositorio

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 solo repo.

Repositorio principal

El repositorio en el que se ejecuta el comando actual de Bazel.

Espacio de trabajo

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 “lugar de trabajo” se combinaron. A menudo, el término “lugar de trabajo” se usó para referirse al repositorio principal y, a veces, se usó como sinónimo de “repositorio”.

Nombre del repositorio canónico

El nombre canónico con el que se puede acceder a un repositorio. Dentro del contexto de un lugar 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 identificar con la etiqueta @@canonical_name//pac/kage:target (ten en cuenta que hay doble @).

El nombre canónico del repositorio principal siempre tiene la string vacía.

Nombre aparente del repositorio

El nombre de un repositorio es accesible en el contexto de otro repositorio determinado. Esto puede considerarse un "apodo" 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 puede 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 (ten en cuenta el solo @).

Por el contrario, se puede entender como una asignación de repositorio: cada repositorio mantiene una asignación de “nombre aparente del repositorio” a un “nombre del repositorio canónico”.

Regla del repositorio

Un esquema para definiciones de repositorio 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 de Maven determinado y hacer que esté disponible como un destino java_import”, o simplemente “symlink a un directorio local”. Cada repositorio se define con una llamada a una regla de 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, por mucho, http_archive, que descarga un archivo de una URL y lo extrae, y local_repository, que vincula symlink a un directorio local que ya es un repositorio de Bazel.

Cómo obtener un repositorio

La acción de hacer que un repositorio esté disponible en un 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 repositorio cuando necesita algo de este, y este aún no se recuperó. Si el repositorio ya se recuperó antes, Bazel solo lo vuelve a recuperar si cambió su definición.

Diseño del directorio

Después de la recuperación, el repositorio se puede encontrar en el subdirectorio external en 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 dependencias externo, no funciona directamente con las definiciones de repositorio. En cambio, compila un gráfico de dependencias a partir de módulos, ejecuta extensiones en la parte superior del 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 y declara su nombre, versión y lista de dependencias, entre otros datos. 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 el gráfico de dependencias transitivas completo antes de realizar la resolución de la versión.

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, con http_archive).

Los módulos también pueden especificar fragmentos de datos personalizados llamados etiquetas que consumen las extensiones de módulo 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 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 compilado a partir de los módulos de Bazel.

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 la de los archivos BUILD y usa reglas del repositorio en lugar de reglas de compilación.

El siguiente fragmento es un ejemplo de cómo usar la regla de repositorio 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 es también el nombre visible para todos los demás repositorios.

Deficiencias del sistema de WORKSPACE

En los años desde que se introdujo el sistema WORKSPACE, los usuarios informaron muchos problemas, entre los que se incluyen los siguientes:

  • Bazel no evalúa los archivos WORKSPACE de ninguna dependencia, por lo que todas las dependencias transitivas deben definirse en el archivo WORKSPACE 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 solicitan a los usuarios que la llamen 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 mediante http_archive con URL, sin información de la versión. Esto significa que no hay una manera confiable de realizar la resolución de la versión en el caso de las dependencias Diamante (A depende de B y C; B y C dependen de versiones diferentes de D).

Debido a las deficiencias de WORKSPACE, Bzlmod reemplazará el sistema de WORKSPACE heredado en versiones futuras de Bazel. Consulta la guía de migración de Bzlmod para saber cómo migrar a Bzlmod.