Archivo de bloqueo de Bazel

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

La función de archivo de bloqueo en Bazel permite grabar versiones específicas o dependencias de bibliotecas de software o paquetes requeridos por un proyecto. Integra lo logra almacenando el resultado de la resolución y extensión del módulo la evaluación del rendimiento. El archivo de bloqueo promueve compilaciones reproducibles, lo que garantiza entornos de desarrollo de aplicaciones. Además, mejora la eficiencia de la compilación, ya que permite Bazel omita las partes del proceso de resolución que no se ven afectadas por los cambios. en las dependencias del proyecto. Además, el archivo de bloqueo mejora la estabilidad lo que evita actualizaciones inesperadas o cambios rotundos en las bibliotecas externas lo que reduce el riesgo de introducir errores.

Generación de archivos de bloqueo

El archivo de bloqueo se genera en la raíz del lugar de trabajo con el nombre. MODULE.bazel.lock Se crean o actualizan durante el proceso de compilación. específicamente, después de la resolución del módulo y la evaluación de la extensión. Es importante destacar solo incluye las dependencias que están incluidas en la invocación actual del compilar.

Cuando se producen cambios en el proyecto que afectan sus dependencias, el archivo de bloqueo se automáticamente para reflejar el nuevo estado. Esto garantiza que el bloqueo del archivo se mantiene enfocado en el conjunto específico de dependencias necesarias para la crear, lo que brinda una representación precisa de la resolución dependencias.

Uso del archivo de bloqueo

El bloqueo se puede controlar con el parámetro --lockfile_mode a personalizar el comportamiento de Bazel cuando el estado del proyecto sea diferente del Archivo de bloqueo. Los modos disponibles son los siguientes:

  • update (predeterminado): Usa la información que está presente en el archivo de bloqueo para omitir las descargas de archivos de registro conocidos y evitar tener que volver a evaluar las extensiones cuyos resultados están actualizados. Si falta información, al archivo de bloqueo. En este modo, Bazel evita actualizar información mutable, como las versiones tomadas, para las dependencias que no han cambió.
  • refresh: Es similar a update, pero la información mutable siempre se actualiza cuando cambia a este modo y aproximadamente cada hora mientras está en este modo.
  • error: Es similar a update, pero si falta información o está desactualizada, Bazel fallará y se mostrará un error. Este modo nunca cambia el bloqueo ni realiza solicitudes de red durante la resolución. Extensiones de módulo que marcaron ya que reproducible aún puede realizar solicitudes de red, pero no se espera que siempre produzca el mismo resultado.
  • off: El archivo de bloqueo no se verifica ni se actualiza.

Beneficios del archivo de bloqueo

El archivo de bloqueo ofrece varios beneficios y se puede usar de varias maneras:

  • Compilaciones reproducibles. Capturando las versiones o dependencias específicas de las bibliotecas de software, el archivo de bloqueo garantiza que las compilaciones en diferentes entornos y a lo largo del tiempo. Los desarrolladores pueden confiar en resultados coherentes y predecibles cuando crean sus proyectos.

  • Resoluciones incrementales rápidas. El archivo de bloqueo permite que Bazel evite descargar archivos de registro que ya se usaron en una compilación anterior. Esto mejora significativamente la eficiencia de la compilación, especialmente en situaciones en las que la resolución puede llevar mucho tiempo.

  • Estabilidad y reducción de riesgos. El archivo de bloqueo ayuda a mantener la estabilidad lo que evita actualizaciones inesperadas o cambios rotundos en las bibliotecas externas. De bloquear dependencias en versiones específicas, el riesgo de introducir errores debido a actualizaciones incompatibles o no probadas.

Contenido del archivo de bloqueo

El archivo de bloqueo contiene toda la información necesaria para determinar si el estado del proyecto cambió. También incluye el resultado de construir el proyecto en el estado actual. El archivo de bloqueo consta de dos partes principales:

  1. Hashes de todos los archivos remotos que son entradas para la resolución del módulo
  2. Para cada extensión de módulo, el archivo de bloqueo incluye entradas que lo afectan, representados por bzlTransitiveDigest, usagesDigest y otros campos, como y el resultado de la ejecución de esa extensión, conocida como generatedRepoSpecs

Este es un ejemplo que demuestra la estructura del archivo de bloqueo, junto con explicaciones para cada sección:

{
  "lockFileVersion": 10,
  "registryFileHashes": {
    "https://bcr.bazel.build/bazel_registry.json": "8a28e4af...5d5b3497",
    "https://bcr.bazel.build/modules/foo/1.0/MODULE.bazel": "7cd0312e...5c96ace2",
    "https://bcr.bazel.build/modules/foo/2.0/MODULE.bazel": "70390338... 9fc57589",
    "https://bcr.bazel.build/modules/foo/2.0/source.json": "7e3a9adf...170d94ad",
    "https://registry.mycorp.com/modules/foo/1.0/MODULE.bazel": "not found",
    ...
  },
  "selectedYankedVersions": {
    "foo@2.0": "Yanked for demo purposes"
  },
  "moduleExtensions": {
    "//:extension.bzl%lockfile_ext": {
      "general": {
        "bzlTransitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
        "usagesDigest": "aLmqbvowmHkkBPve05yyDNGN7oh7QE9kBADr3QIZTZs=",
        ...,
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      }
    },
    "//:extension.bzl%lockfile_ext2": {
      "os:macos": {
        "bzlTransitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
        "usagesDigest": "aLmqbvowmHkkBPve05y....yDNGN7oh7r3QIZTZs=",
        ...,
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      },
      "os:linux": {
        "bzlTransitiveDigest": "eWDzxG/aLsyY3Ubrto....+Jp4maQvEPxn0pLK=",
        "usagesDigest": "aLmqbvowmHkkBPve05y....yDNGN7oh7r3QIZTZs=",
        ...,
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      }
    }
  }
}

Hashes de archivos de registro

La sección registryFileHashes contiene los hashes de todos los archivos de registros remotos a los que se accede durante la resolución del módulo. Dado que la resolución es completamente determinista cuando se le proporcionan las mismas entradas y todas genera un hash para las entradas, lo que garantiza un resultado de resolución reproducible. y evitar la duplicación excesiva de información remota en el archivo de bloqueo. Ten en cuenta que Esto también requiere una grabación cuando un registro en particular no contenía un pero un registro con menor precedencia sí lo hizo (consulta la entrada "no encontrado" en el ejemplo). Esta información inherentemente mutable se puede actualizar bazel mod deps --lockfile_mode=refresh

Bazel usa los hashes del archivo de bloqueo para buscar archivos de registro en la en la caché del repositorio antes de descargarlos, lo que acelera del proyecto.

Versiones yanks seleccionadas

La sección selectedYankedVersions contiene las versiones duplicadas de los módulos. que se seleccionaron según la resolución del módulo. Ya que esto suele dar como resultado un error cuando se intenta compilar, esta sección solo no está vacía cuando se generan versiones se permite explícitamente mediante --allow_yanked_versions o BZLMOD_ALLOW_YANKED_VERSIONS

Este campo es necesario, ya que, en comparación con los archivos del módulo, se extrajo información de la versión. es inherentemente mutable y, por lo tanto, un hash no puede hacer referencia a él. Esta información se puede actualizar a través de bazel mod deps --lockfile_mode=refresh.

Extensiones de módulo

La sección moduleExtensions es un mapa que incluye solo las extensiones utilizadas en la invocación actual o anteriormente, y se excluyen las extensiones que ya no se utilizan. En otras palabras, si una extensión no se está usando ya no está en el gráfico de dependencia, se quita de moduleExtensions. mapa.

Si una extensión es independiente del sistema operativo o del tipo de arquitectura esta sección presenta solo una consulta "general", entrada. De lo contrario, varios nombradas por el SO, la arquitectura o ambos, con cada que corresponde al resultado de evaluar la extensión en esos detalles.

Cada entrada en el mapa de extensiones corresponde a una extensión utilizada y se identificados por el archivo y el nombre que los contienen. El valor correspondiente para cada contiene la información relevante asociada con esa extensión:

  1. El bzlTransitiveDigest es el resumen de la implementación de la extensión. y los archivos .bzl que carga transitivamente.
  2. El usagesDigest es el resumen de los usos de la extensión en la gráfico de dependencia, que incluye todas las etiquetas.
  3. Otros campos sin especificar que hacen un seguimiento de otras entradas a la extensión como contenidos de archivos o directorios que lee, o variables que usa.
  4. generatedRepoSpecs codifica los repositorios creados por el con la entrada actual.
  5. El campo opcional moduleExtensionMetadata contiene metadatos que proporciona el la extensión, por ejemplo, si ciertos repositorios que creó deberían el módulo raíz importa a través de use_repo. Esta información alimenta la Comando bazel mod tidy.

Las extensiones de módulo pueden inhabilitar la inclusión en el archivo de bloqueo estableciendo que muestra los metadatos con reproducible = True. Al hacerlo, prometen que sino que siempre crearán los mismos repositorios cuando se les proporcionen las mismas entradas.

Prácticas recomendadas

Para maximizar los beneficios de la función de archivo bloqueado, considera lo siguiente prácticas:

  • Actualiza regularmente el archivo de bloqueo para reflejar los cambios en las dependencias del proyecto o configuración. Esto garantiza que las compilaciones posteriores se basen en la información un conjunto de dependencias preciso y actualizado. Para bloquear todas las extensiones, sigue estos pasos: de una sola vez, ejecuta bazel mod deps --lockfile_mode=update.

  • Incluye el bloqueo de versión en el control de versión para facilitar la colaboración y garantizar que todos los miembros del equipo tengan acceso al mismo archivo de bloqueo, lo que promueve entornos de desarrollo coherentes en todo el proyecto.

  • Usa bazelisk para ejecutar Bazel y, además, incluye un Archivo .bazelversion en el control de versión que especifica la versión de Bazel correspondiente al archivo de bloqueo. Debido a que Bazel en sí depende de de tu compilación, el archivo de bloqueo es específico de la versión de Bazel y cambiar incluso entre versiones retrocompatibles Lanzamientos de Bazel. Usar bazelisk garantiza que todos los desarrolladores usen una versión de Bazel que coincida con el archivo de bloqueo

Si sigues estas prácticas recomendadas, podrás usar eficazmente el archivo bloqueado en Bazel para que sea más eficiente, confiable y en los flujos de trabajo de desarrollo de software.

Conflictos de combinación

El formato del archivo bloqueado está diseñado para minimizar los conflictos de combinación, pero aún pueden suceder.

Resolución automática

Bazel proporciona una canalización controlador de combinación de Git para resolver estos conflictos automáticamente.

Para configurar el controlador, agrega esta línea a un archivo .gitattributes en la raíz del tu repositorio de Git:

# A custom merge driver for the Bazel lockfile.
# https://bazel.build/external/lockfile#automatic-resolution
MODULE.bazel.lock merge=bazel-lockfile-merge

Luego, cada desarrollador que quiera usar el controlador deberá registrarlo una vez mediante siguiendo estos pasos:

  1. Instala jq (1.5 o una versión posterior).
  2. Ejecute los siguientes comandos:
jq_script=$(curl https://raw.githubusercontent.com/bazelbuild/bazel/master/scripts/bazel-lockfile-merge.jq)
printf '%s\n' "${jq_script}" | less # to optionally inspect the jq script
git config --global merge.bazel-lockfile-merge.name   "Merge driver for the Bazel lockfile (MODULE.bazel.lock)"
git config --global merge.bazel-lockfile-merge.driver "jq -s '${jq_script}' -- %O %A %B > %A.jq_tmp && mv %A.jq_tmp %A"

Resolución manual

Conflictos de combinación simples en registryFileHashes y selectedYankedVersions campos se pueden resolver de forma segura manteniendo todas las entradas de ambos lados de conflicto.

Otros tipos de conflictos de combinación no deben resolverse manualmente. En su lugar, siga estos pasos:

  1. Restablecer el estado anterior del archivo de bloqueo a través de git reset MODULE.bazel.lock && git checkout MODULE.bazel.lock.
  2. Resuelve cualquier conflicto en el archivo MODULE.bazel.
  3. Ejecuta bazel mod deps para actualizar el archivo de bloqueo.