Trabaja con dependencias externas

Informar un problema Ver fuente . Por la noche · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel puede depender de destinos de otros proyectos. Dependencias de estos otros Los proyectos se denominan dependencias externas.

El archivo WORKSPACE (o el archivo WORKSPACE.bazel) de la directorio del espacio de trabajo le indica a Bazel cómo obtener las capacidades de otros fuentes de datos. Estos otros proyectos también pueden contener uno o más archivos BUILD con sus propios destinos BUILD archivos en el proyecto principal puede depender de estos objetivos externos mediante el uso de su nombre de el archivo WORKSPACE.

Por ejemplo, supongamos que hay dos proyectos en un sistema:

/
  home/
    user/
      project1/
        WORKSPACE
        BUILD
        srcs/
          ...
      project2/
        WORKSPACE
        BUILD
        my-libs/

Si project1 quisiera depender de un destino, :foo, que se define en /home/user/project2/BUILD, podría especificar que un repositorio llamado project2 se puede encontrar en /home/user/project2. Luego, se orienta en /home/user/project1/BUILD podría depender de @project2//:foo.

El archivo WORKSPACE permite que los usuarios dependan de objetivos de otras partes de la en un sistema de archivos o que se descargan de Internet. Usa la misma sintaxis que BUILD. archivos, pero permite un conjunto diferente de reglas llamadas reglas de repositorio (a veces también conocidas como reglas del lugar de trabajo). Bazel incluye algunas reglas de repositorio integradas y un conjunto reglas de repositorio de Starlark incorporadas. Los usuarios también pueden escribir reglas de repositorio personalizadas. para conseguir un comportamiento más complejo.

Tipos de dependencias externas compatibles

Se pueden usar algunos tipos básicos de dependencias externas:

Según otros proyectos de Bazel

Si quieres usar destinos de otro proyecto de Bazel, puedes usar local_repository: git_repository o http_archive para crear un symlink desde el sistema de archivos local, hacer referencia a un repositorio de Git o descargarlo (respectivamente).

Por ejemplo, supongamos que trabajas en un proyecto, my-project/, y quieres dependerá de los objetivos del proyecto de tu compañero de trabajo, coworkers-project/. Ambas opciones proyectos usan Bazel, por lo que puedes agregar el proyecto de tu compañero de trabajo como un y usar cualquier objetivo que tu compañero de trabajo haya definido a partir de tu propio Compilar archivos. Agregarías lo siguiente a my_project/WORKSPACE:

local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
)

Si tu compañero de trabajo tiene un //foo:bar de destino, tu proyecto puede referirse a él como @coworkers_project//foo:bar Los nombres de proyectos externos nombres de lugares de trabajo válidos.

Según proyectos que no sean de Bazel

Las reglas con el prefijo new_, como new_local_repository, te permiten crear destinos a partir de proyectos que no usan Bazel.

Por ejemplo, supongamos que trabajas en un proyecto, my-project/, y quieres dependerá del proyecto de tu compañero de trabajo, coworkers-project/. La dirección de tu compañero de trabajo El proyecto usa make para compilar, pero quieres depender de uno de los archivos .so. que genera. Para ello, agrega lo siguiente a my_project/WORKSPACE:

new_local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
    build_file = "coworker.BUILD",
)

build_file especifica un archivo BUILD para superponer en el proyecto existente, por ejemplo:

cc_library(
    name = "some-lib",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)

Luego, puedes depender de @coworkers_project//:some-lib de la red BUILD archivos.

Según los paquetes externos

Artefactos y repositorios de Maven

Usa el conjunto de reglas rules_jvm_external. para descargar artefactos de repositorios de Maven y ponerlos a disposición como Java dependencias.

Recupera dependencias

De forma predeterminada, las dependencias externas se recuperan según sea necesario durante bazel build. Si Si quieres cargar previamente las dependencias necesarias para un conjunto específico de destinos, usa bazel fetch Para recuperar incondicionalmente todas las dependencias externas, usa bazel sync Como los repositorios recuperados se almacenan en la base de salida, recuperar ocurre por lugar de trabajo.

Dependencias de la duplicación

Siempre que sea posible, se recomienda tener una política de versión única en tu en un proyecto final. Esto es necesario para las dependencias con las que compilas y terminas en tu objeto binario final. Pero en los casos en los que esto no sea así, es posible dependencias shadow. Considera la siguiente situación:

miproyecto/WORKSPACE

workspace(name = "myproject")

local_repository(
    name = "A",
    path = "../A",
)
local_repository(
    name = "B",
    path = "../B",
)

A/WORKSPACE

workspace(name = "A")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "...",
)

B/WORKSPACE

workspace(name = "B")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)

Ambas dependencias, A y B, dependen de testrunner, pero dependen de diferentes versiones de testrunner. No hay motivo para que estos ejecutores de pruebas no coexisten pacíficamente en myproject; sin embargo, se enfrentarán con cada una porque tienen el mismo nombre. Para declarar ambas dependencias, actualiza myproject/WORKSPACE:

workspace(name = "myproject")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner-v1",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "..."
)
http_archive(
    name = "testrunner-v2",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)
local_repository(
    name = "A",
    path = "../A",
    repo_mapping = {"@testrunner" : "@testrunner-v1"}
)
local_repository(
    name = "B",
    path = "../B",
    repo_mapping = {"@testrunner" : "@testrunner-v2"}
)

Este mecanismo también se puede utilizar para unir diamantes. Por ejemplo, si A y B tenían la misma dependencia, pero la llamaron con nombres diferentes, esas dependencias pueden unirme en myproject/WORKSPACE.

Anula repositorios desde la línea de comandos

Para anular un repositorio declarado con un repositorio local desde la línea de comandos, usa el --override_repository marca. El uso de esta marca cambia el contenido de los repositorios externos sin sin modificar tu código fuente.

Por ejemplo, para anular @foo en el directorio local /path/to/local/foo, usa este código: pasa la marca --override_repository=foo=/path/to/local/foo.

A continuación, se presentan algunos de los casos prácticos:

  • Problemas de depuración. Por ejemplo, puedes anular un repositorio de http_archive. a un directorio local en el que puedas realizar cambios con mayor facilidad.
  • Proveedores Si estás en un entorno en el que no puedes hacer llamadas de red anular las reglas de repositorio basadas en la red para que apunten a directorios locales en su lugar.

Usa proxies

Bazel captará las direcciones de proxy de HTTPS_PROXY y HTTP_PROXY. variables de entorno y usarlas para descargar archivos HTTP/HTTPS (si se especifican).

Compatibilidad con IPv6

En máquinas que solo usan IPv6, Bazel podrá descargar dependencias con sin cambios. Sin embargo, en las máquinas IPv4/IPv6 de pila doble, Bazel sigue el mismo procedimiento como Java: si se habilita IPv4, se prefiere IPv4. En algunas situaciones, Por ejemplo, cuando la red IPv4 no puede resolver o llegar a direcciones externas Esto puede causar excepciones Network unreachable y fallas de compilación. En estos casos, puedes anular el comportamiento de Bazel y dar prioridad a IPv6. Mediante la propiedad del sistema java.net.preferIPv6Addresses=true En particular, haz lo siguiente:

  • Usa --host_jvm_args=-Djava.net.preferIPv6Addresses=true opción de inicio, por ejemplo, agregando la siguiente línea en tu Archivo .bazelrc:

    startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true

  • Si ejecutas destinos de compilación de Java que necesitan conectarse a Internet (a veces, se necesita para las pruebas de integración); también usa --jvmopt=-Djava.net.preferIPv6Addresses=true marca de herramienta, por ejemplo, haciendo que siguiente línea en tu archivo .bazelrc:

    build --jvmopt=-Djava.net.preferIPv6Addresses

  • Si utilizas rules_jvm_external, p. ej., para la resolución de la versión de la dependencia, agrega -Djava.net.preferIPv6Addresses=true a COURSIER_OPTS variable de entorno para proporcionar opciones de JVM para Coursier

Dependencias transitivas

Bazel solo lee las dependencias que se indican en tu archivo WORKSPACE. Si tu proyecto (A) depende de otro proyecto (B) que indica una dependencia de un tercero proyecto (C) en su archivo WORKSPACE, deberás agregar B y C al archivo WORKSPACE de tu proyecto. Este requisito puede inflar WORKSPACE, pero limita las posibilidades de tener una biblioteca Incluye C en la versión 1.0 y otro incluye C en la versión 2.0.

Almacenamiento en caché de dependencias externas

De forma predeterminada, Bazel solo volverá a descargar dependencias externas si sus cambios en las definiciones. Cambios en los archivos a los que se hace referencia en la definición (como parches) o archivos BUILD) también las tiene en cuenta Bazel.

Para forzar una nueva descarga, usa bazel sync.

Diseño

Todas las dependencias externas se descargan en un directorio en el subdirectorio external en la base de salida. En caso de una repositorio local, se crea un symlink en lugar de crear un directorio nuevo. Para ver el directorio external, ejecuta lo siguiente:

ls $(bazel info output_base)/external

Ten en cuenta que ejecutar bazel clean no borrará el almacenamiento . Para quitar todos los artefactos externos, usa bazel clean --expunge.

Compilaciones sin conexión

A veces, es conveniente o necesario ejecutar una compilación sin conexión. Para casos de uso sencillos, como viajar en un avión, prefetching de los elementos los repositorios con bazel fetch o bazel sync pueden ser suficientes; además, el Con la opción --nofetch, se puede inhabilitar la recuperación de más repositorios durante la compilación.

Para compilaciones sin conexión reales, en las que se deben proporcionar los archivos necesarios por una entidad diferente de bazel, bazel admite la opción --distdir Cuando una regla de repositorio le pide a Bazel que recupere un archivo mediante ctx.download o ctx.download_and_extract y proporciona una suma hash del archivo necesario, Bazel primero buscará en los directorios especificados por esa opción para un archivo que coincida con el nombre base de la primera URL proporcionada y usar esa copia local si el hash coincide.

Bazel usa esta técnica para realizar un arranque sin conexión desde la distribución artefacto. Para ello, recopila todos los recursos dependencias en un entorno distdir_tar

Sin embargo, bazel permite la ejecución de comandos arbitrarios en las reglas del repositorio. sin saber si llaman a la red. Por lo tanto, Bazel no tiene opción para que las compilaciones sean completamente sin conexión. Por lo tanto, probar si una compilación funciona correctamente el uso sin conexión requiere el bloqueo externo de la red, como lo hace Bazel en su una prueba de arranque.

Prácticas recomendadas

Reglas del repositorio

Por lo general, una regla de repositorio debe ser responsable de lo siguiente:

  • Detectar la configuración del sistema y escribirla en archivos.
  • Buscar recursos en otras partes del sistema.
  • Se están descargando recursos a partir de URLs.
  • Generar o vincular symlink archivos BUILD en el directorio del repositorio externo

Evita usar repository_ctx.execute cuando sea posible. Por ejemplo, cuando usas un código C++ que no es de Bazel que tiene una compilación con Make, es preferible usar repository_ctx.download() y, luego, escribe un archivo BUILD que lo compile, en lugar de ejecutar ctx.execute(["make"]).

Prefiero http_archive en lugar de git_repository y new_git_repository Estos son los motivos:

  • Las reglas del repositorio de Git dependen del sistema git(1), mientras que el descargador HTTP se compila a Bazel y no tiene dependencias de sistema.
  • http_archive admite una lista de urls como duplicaciones, y git_repository solo admite una. un solo remote.
  • http_archive funciona con la caché del repositorio, pero no git_repository Consulta #5116 para obtener más información.

No uses bind(). Consulta "Considera quitar vincular durante mucho tiempo debate sobre sus problemas y alternativas.