En esta página, se explica cómo definir reglas de repositorio y se proporcionan ejemplos para obtener más detalles.
Un repositorio externo es un árbol de directorios que contiene archivos fuente que se pueden usar en una compilación de Bazel y que se genera a pedido cuando se ejecuta su regla de repo correspondiente. Los repositorios se pueden definir de muchas maneras, pero, en última instancia, cada uno se define invocando una regla de repositorio, al igual que los destinos de compilación se definen invocando reglas de compilación. Se pueden usar para depender de bibliotecas de terceros (como las bibliotecas empaquetadas de Maven), pero también para generar archivos BUILD
específicos del host en el que se ejecuta Bazel.
Definición de la regla del repositorio
En un archivo .bzl
, usa la función repository_rule para definir una nueva regla de repo y almacenarla en una variable global. Después de definir una regla de repo, se puede invocar como una función para definir repos. Por lo general, esta invocación se realiza desde una función de implementación de extensión de módulo.
Los dos componentes principales de una definición de regla del repositorio son su esquema de atributos y su función de implementación. El esquema de atributos determina los nombres y los tipos de atributos que se pasan a una invocación de regla del repositorio, y la función de implementación se ejecuta cuando es necesario recuperar el repositorio.
Atributos
Los atributos son argumentos que se pasan a la invocación de la regla del repo. El esquema de los atributos que acepta una regla de repo se especifica con el argumento attrs
cuando la regla de repo se define con una llamada a repository_rule
. Ejemplo que define los atributos url
y sha256
como cadenas:
http_archive = repository_rule(
implementation=_impl,
attrs={
"url": attr.string(mandatory=True),
"sha256": attr.string(mandatory=True),
}
)
Para acceder a un atributo dentro de la función de implementación, usa repository_ctx.attr.<attribute_name>
:
def _impl(repository_ctx):
url = repository_ctx.attr.url
checksum = repository_ctx.attr.sha256
Todos los repository_rule
tienen el atributo name
definido de forma implícita. Este es un atributo de cadena que se comporta de forma algo mágica: cuando se especifica como entrada para una invocación de regla de repo, toma un nombre de repo aparente, pero cuando se lee desde la función de implementación de la regla de repo con repository_ctx.attr.name
, devuelve el nombre canónico del repo.
Función de implementación
Cada regla de repo requiere una función implementation
. Contiene la lógica real de la regla y se ejecuta estrictamente en la fase de carga.
La función tiene exactamente un parámetro de entrada, repository_ctx
. La función devuelve None
para indicar que la regla es reproducible con los parámetros especificados o un diccionario con un conjunto de parámetros para esa regla que la convertirían en una regla reproducible que genera el mismo repo. Por ejemplo, para una regla que hace un seguimiento de un repositorio de Git, esto significaría devolver un identificador de confirmación específico en lugar de una rama flotante que se especificó originalmente.
El parámetro de entrada repository_ctx
se puede usar para acceder a los valores de los atributos y a las funciones no herméticas (buscar un archivo binario, ejecutar un archivo binario, crear un archivo en el repositorio o descargar un archivo de Internet). Consulta la documentación de la API para obtener más contexto. Ejemplo:
def _impl(repository_ctx):
repository_ctx.symlink(repository_ctx.attr.path, "")
local_repository = repository_rule(
implementation=_impl,
...)
¿Cuándo se ejecuta la función de implementación?
La función de implementación de una regla de repositorio se ejecuta cuando Bazel necesita un destino de ese repositorio, por ejemplo, cuando otro destino (en otro repositorio) depende de él o si se menciona en la línea de comandos. Luego, se espera que la función de implementación cree el repo en el sistema de archivos. Esto se denomina "recuperación" del repo.
A diferencia de los destinos normales, los repositorios no se vuelven a recuperar necesariamente cuando cambia algo que haría que el repositorio sea diferente. Esto se debe a que hay elementos cuyos cambios Bazel no puede detectar o que causarían una sobrecarga excesiva en cada compilación (por ejemplo, los elementos que se recuperan de la red). Por lo tanto, los repositorios solo se vuelven a recuperar si cambia uno de los siguientes elementos:
- Son los atributos que se pasan a la invocación de la regla del repo.
- Es el código de Starlark que comprende la implementación de la regla del repositorio.
- Es el valor de cualquier variable de entorno que se pase al método
getenv()
derepository_ctx
o que se declare con el atributoenviron
derepository_rule
. Los valores de estas variables de entorno se pueden codificar de forma rígida en la línea de comandos con la marca--repo_env
. - La existencia, el contenido y el tipo de cualquier ruta de acceso que se
watch
en la función de implementación de la regla del repo.- Algunos otros métodos de
repository_ctx
con un parámetrowatch
, comoread()
,execute()
yextract()
, también pueden hacer que se observen rutas. - Del mismo modo,
repository_ctx.watch_tree
ypath.readdir
pueden hacer que se observen rutas de otras maneras.
- Algunos otros métodos de
- Cuando se ejecuta
bazel fetch --force
Hay dos parámetros de repository_rule
que controlan cuándo se vuelven a recuperar los repositorios:
- Si se configura la marca
configure
, el repositorio se vuelve a recuperar enbazel fetch --force --configure
(los repositorios que no sonconfigure
no se vuelven a recuperar). - Si se configura la marca
local
, además de los casos anteriores, el repo también se vuelve a recuperar cuando se reinicia el servidor de Bazel.
Cómo forzar la recuperación de repositorios externos
A veces, un repo externo puede quedar desactualizado sin que se modifique su definición o sus dependencias. Por ejemplo, un repo que recupera fuentes podría seguir una rama específica de un repositorio de terceros, y hay nuevas confirmaciones disponibles en esa rama. En este caso, puedes pedirle a Bazel que vuelva a recuperar todos los repositorios externos de forma incondicional llamando a bazel fetch --force --all
.
Además, algunas reglas del repo inspeccionan la máquina local y podrían quedar desactualizadas si se actualizó la máquina local. Aquí puedes pedirle a Bazel que solo vuelva a recuperar los repositorios externos en los que la definición de repository_rule
tenga establecido el atributo configure
, usa bazel fetch --force
--configure
.
Ejemplos
Cadena de herramientas de C++ configurada automáticamente: Utiliza una regla de repo para crear automáticamente los archivos de configuración de C++ para Bazel buscando el compilador local de C++, el entorno y las marcas que admite el compilador de C++.
Go repositories usa varios
repository_rule
para definir la lista de dependencias necesarias para usar las reglas de Go.rules_jvm_external crea un repositorio externo llamado
@maven
de forma predeterminada que genera destinos de compilación para cada artefacto de Maven en el árbol de dependencias transitivas.