Reglas del repositorio

Informar un problema Ver fuente

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 se puede usar solo en el archivo WORKSPACE y habilita las operaciones no herméticas en la fase de carga de Bazel. Cada regla de repositorio externo crea su propio lugar de trabajo, con sus propios archivos y artefactos BUILD. 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.

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. Tiene un atributo name obligatorio y cada destino presente en sus archivos de compilación puede denominarse @<name>//package:target, en el que <name> es el valor del atributo name.

La regla se carga cuando la compilas de manera explícita o si es una dependencia de la compilación. En este caso, Bazel ejecutará su función implementation. Esta función describe cómo crear el repositorio, su contenido y los archivos BUILD.

Atributos

El atributo son argumentos de la regla que se pasan como dict al argumento de la regla attrs. Los atributos y sus tipos se definen en una lista cuando defines una regla del repositorio. Ejemplo en el que se definen los atributos url y sha256 como cadenas:

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, 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 atributos definidos de manera implícita (al igual que las reglas de compilación). Los dos atributos implícitos son name (al igual que para las reglas de compilación) y 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 el de las reglas del repositorio nativo local_repository y new_local_repository.

Si el nombre de un atributo comienza con _, es privado y los usuarios no pueden configurarlo.

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 muestra None para indicar que la regla es reproducible según los parámetros especificados, o un dict con un conjunto de parámetros para esa regla que convertiría esa regla en una que se pueda reproducir y que genere el mismo repositorio. Por ejemplo, para una regla que realiza un seguimiento de un repositorio de Git que significaría mostrar 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 valores de atributos y a funciones no herméticas (buscar o ejecutar uno, crear un archivo en el repositorio o descargar un archivo de Internet). Consulta la biblioteca 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 un 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 repositorio en el sistema de archivos. Esto se llama "recuperación" del repositorio.

A diferencia de los destinos normales, los repositorios no necesariamente se vuelven a recuperar cuando cambia algo que haría que el repositorio fuera diferente. Esto se debe a que Bazel no puede detectar cambios en algunos elementos o generaría 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 condiciones:

  • Los parámetros que se pasan a la declaración del repositorio en el archivo WORKSPACE.
  • El código de Starlark comprende la implementación del repositorio.
  • Es el valor de cualquier variable de entorno que se pasa al método getenv() de repository_ctx o se declara con el atributo environ de repository_rule. Los valores de estas variables de entorno se pueden conectar de forma directa en la línea de comandos con la marca --repo_env.
  • El contenido de cualquier archivo que se pase a read(), execute() y métodos similares de repository_ctx al que hace referencia una etiqueta (por ejemplo, //mypkg:label.txt, pero no mypkg/label.txt)
  • Cuando se ejecuta bazel sync.

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 solo se volverá a recuperar en bazel sync cuando se le pase el parámetro --configure (si no se configura el atributo, este comando no causará una nueva recuperación)
  • Si se configura 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 afecta la declaración del repositorio (p.ej., el archivo WORKSPACE o un archivo que carga), sin importar si los cambios generaron un cambio en la declaración del repositorio o su código.

    En estos casos, no se vuelven a recuperar los repositorios que no son locales. Esto se debe a que se supone que estos repositorios se comunican con la red o son costosos.

Reinicia 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 la función de implementación se detendrá, la dependencia faltante se resolverá y 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 las etiquetas se cargan previamente, siempre que todos los argumentos de las etiquetas se puedan resolver en un archivo existente. Ten en cuenta que resolver una ruta de acceso desde una cadena o una etiqueta que se construyó solo durante la ejecución de la función puede causar un reinicio.

Forzar la 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 seguir una rama específica de un repositorio de terceros, y hay confirmaciones nuevas disponibles en esa rama. En este caso, puedes pedirle a Bazel que recupere todos los repositorios externos de forma incondicional llamando a bazel sync.

Además, algunas reglas inspeccionan la máquina local y podrían quedar desactualizadas si esta se actualiza. 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 sync --configure.

Ejemplos

  • Cadena de herramientas de configuración automática de C++: Usa una regla de repositorio a fin de crear automáticamente los archivos de configuración de C++ para Bazel mediante la búsqueda del compilador de C++ local, el entorno y las marcas que admite el compilador de C++.

  • Los repositorios de Go usan varios repository_rule a fin de 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 transitivas.