En esta página, se explica cómo crear reglas de repositorio y se proporcionan ejemplos para obtener más detalles.
Un repositorio externo es una regla que solo se puede usar
en el archivo WORKSPACE
y habilita la operación no hermética en la fase de carga
de Bazel. Cada regla de repositorio externo crea su propio espacio de trabajo, con sus
poseer archivos y artefactos BUILD
. Se pueden usar para depender de bibliotecas de terceros (como bibliotecas empaquetadas de Maven), pero también para generar archivos BUILD
específicos del host en el que se ejecuta Bazel.
Creación de reglas de repositorio
En un archivo .bzl
, usa la función
repository_rule para crear una
regla de repositorio nueva y almacenarla en una variable global.
Una regla de repositorio personalizada se puede usar como una regla de repositorio nativo. Integra
tiene un atributo name
obligatorio y cada destino presente en sus archivos de compilación
puede denominarse @<name>//package:target
, donde <name>
es el valor de la
atributo name
.
La regla se carga cuando la compilas explícitamente, o si es una dependencia de
la compilación. En este caso, Bazel ejecutará su función implementation
. En esta función, se describe cómo crear el repositorio, su contenido y los archivos BUILD
.
Atributos
El atributo son argumentos de regla que se pasan como un diccionario al argumento de la regla attrs
.
Los atributos y sus tipos se definen cuando defines un
regla de repositorio. Un ejemplo en el que se definen los atributos url
y sha256
como
strings:
local_repository = repository_rule(
implementation=_impl,
local=True,
attrs={
"url": attr.string(mandatory=True)
"sha256": attr.string(mandatory=True)
}
)
Para acceder a un atributo dentro de la función de implementación, use
repository_ctx.attr.<attribute_name>
def _impl(repository_ctx):
url = repository_ctx.attr.url
checksum = repository_ctx.attr.sha256
Todos los repository_rule
tienen atributos definidos de forma implícita (al igual que las reglas de compilación). Los dos atributos implícitos son name
(al igual que ocurre con las reglas de compilación)
repo_mapping
Se puede acceder al nombre de una regla de repositorio con repository_ctx.name
. El significado de repo_mapping
es el mismo que para el
reglas de repositorio nativo
local_repository
y
new_local_repository
Si el nombre de un atributo comienza con _
, es privado y los usuarios no pueden establecerlo.
Función de implementación
Cada regla de repositorio 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 en función de la
parámetros específicos, o un dict con un conjunto de parámetros para esa regla que
convertiría esa regla en una reproducible que
generaba el mismo repositorio. Para
ejemplo, para una regla que realiza un seguimiento de un repositorio de Git, esto implicaría mostrar un
identificador de confirmación específico en lugar de una rama flotante que originalmente estaba
especificada.
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 (encontrar un objeto binario, ejecutarlo, crear un archivo en el repositorio o descargar un archivo de Internet). Consulta la biblioteca para obtener más información
adicional. 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 un repositorio se ejecuta cuando Bazel necesita un objetivo de ese repositorio, por ejemplo, cuando otro destino (en otro repositorio) depende de él o si se menciona en la línea de comandos. Se espera que la función de implementación cree el repositorio en el sistema de archivos. Esto se llama "recuperar" del repositorio.
A diferencia de los objetivos normales, los repositorios no se vuelven a recuperar necesariamente cuando cambia algo que haría que el repositorio fuera diferente. Este es porque hay aspectos en los que Bazel no puede detectar cambios o causar demasiada sobrecarga en cada compilación (por ejemplo, elementos que se recuperan de la red). Por lo tanto, los repositorios se vuelven a recuperar solo si cambia una de las siguientes opciones:
- Son los parámetros que se pasan a la declaración del repositorio en el archivo
WORKSPACE
. - El código de Starlark, que comprende la implementación del repositorio.
- El valor de cualquier variable de entorno declarada con el
environ
atributo de larepository_rule
. Los valores de estas variables de entorno se pueden codificar en la línea de comandos con la marca--action_env
(pero esta marca invalidará cada acción de la compilación). - El contenido de cualquier archivo que se pasa a
read()
,execute()
y métodos similares derepository_ctx
a los que se hace referencia con una etiqueta (por ejemplo,//mypkg:label.txt
, pero nomypkg/label.txt
) - Cuando se ejecuta
bazel sync
.
Hay dos parámetros de repository_rule
que controlan cuándo se crean
se vuelven a recuperar:
- Si se establece la marca
configure
, el repositorio solo se vuelve a recuperar enbazel sync
cuando se le pasa el parámetro--configure
(si no se establece el atributo, este comando no provocará una recuperación). Si se establece la marca
local
, además de los casos anteriores, el repositorio también se vuelve a recuperar cuando se reinicia el servidor de Bazel o cuando cambia cualquier archivo que afecte la declaración del repositorio (p. ej., el archivoWORKSPACE
o un archivo que cargue), independientemente de si los cambios provocaron un cambio en la declaración del repositorio o su código.En estos casos, no se vuelven a recuperar los repositorios no locales. Esto se debe a que se supone que estos repositorios se comunican con la red o son costosos.
Cómo reiniciar la función de implementación
La función de implementación se puede reiniciar mientras se recupera un repositorio si falta una dependencia que solicita. En ese caso, la ejecución de se detendrá la función de implementación, se resolverá la dependencia faltante La función se volverá a ejecutar después de que se haya resuelto la dependencia. Para evitar reinicios innecesarios (que son costosos, ya que es posible que se deba repetir el acceso a la red), los argumentos de etiqueta se precargan, siempre que todos los argumentos de etiqueta se puedan resolver en un archivo existente. Ten en cuenta que resolver una ruta de acceso a partir de una string o una etiqueta que se construyó solo durante la ejecución de la función aún podría causar un reinicio.
Fuerza la nueva recuperación de repositorios externos
A veces, un repositorio externo puede quedar desactualizado sin ningún cambio en su definición o dependencias. Por ejemplo, un repositorio que recupera fuentes podría
siguen una rama específica de un repositorio de terceros, y se agregan
disponibles en esa rama. En este caso, puedes pedirle a Bazel que vuelva a recuperar todos
a repositorios externos de forma incondicional llamando a bazel sync
.
Además, algunas reglas inspeccionan la máquina local y pueden quedar
anticuadas si se actualiza. Aquí puedes pedirle a Bazel que
solo recuperar los repositorios externos en los que
repository_rule
definición tiene establecido el atributo configure
, usa bazel sync --configure
.
Ejemplos
Cadena de herramientas configurada automáticamente para C++: usa una regla de repositorio para crear automáticamente la archivos de configuración de C++ para Bazel buscando el compilador C++ local, el y los indicadores que admite el compilador de C++.
Los repositorios de Go usan 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 Maven en el árbol de dependencias transitivo.