Arquivo de bloqueio do Bazel

Reportar um problema Ver código-fonte Nightly · 8.0 . 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

O recurso de arquivo de bloqueio no Bazel permite o registro de versões ou dependências específicas de bibliotecas ou pacotes de software necessários para um projeto. Para isso, ele armazena o resultado da resolução do módulo e da avaliação da extensão. O arquivo de bloqueio promove builds reproduzíveis, garantindo ambientes de desenvolvimento consistentes. Além disso, ela melhora a eficiência do build, permitindo que o Bazel pule o processo de resolução quando não há mudanças nas dependências do projeto. Além disso, o arquivo de bloqueio melhora a estabilidade, impedindo atualizações inesperadas ou mudanças interruptivas em bibliotecas externas, reduzindo o risco de introdução de bugs.

Geração de arquivos de bloqueio

O arquivo de bloqueio é gerado na raiz do espaço de trabalho com o nome MODULE.bazel.lock. Ela é criada ou atualizada durante o processo de build, especificamente após a resolução do módulo e a avaliação da extensão. O arquivo de bloqueio captura o estado atual do projeto, incluindo o arquivo MODULE, sinalizações, substituições e outras informações relevantes. Ele inclui apenas as dependências incluídas na invocação atual do build.

Quando ocorrem mudanças no projeto que afetam as dependências, o arquivo de bloqueio é atualizado automaticamente para refletir o novo estado. Isso garante que o arquivo de bloqueio continue focado no conjunto específico de dependências necessárias para o build atual, fornecendo uma representação precisa das dependências resolução do projeto.

Uso de arquivos de bloqueio

O arquivo de bloqueio pode ser controlado pela flag --lockfile_mode para personalizar o comportamento do Bazel quando o estado do projeto for diferente do arquivo de bloqueio. Os modos disponíveis são:

  • update (padrão): se o estado do projeto corresponder ao arquivo de bloqueio, o resultado da resolução será retornado imediatamente pelo arquivo de bloqueio. Caso contrário, a resolução é executada e o arquivo de bloqueio é atualizado para refletir o estado atual.
  • error: se o estado do projeto corresponder ao arquivo de bloqueio, o resultado da resolução será retornado pelo arquivo de bloqueio. Caso contrário, o Bazel gera um erro indicando as variações entre o projeto e o arquivo de bloqueio. Esse modo é particularmente útil quando você quer garantir que as dependências do projeto permaneçam inalteradas e que quaisquer diferenças sejam tratadas como erros.
  • off: o arquivo de bloqueio não é verificado.

Benefícios do arquivo de bloqueio

O arquivo de bloqueio oferece vários benefícios e pode ser usado de várias maneiras:

  • Builds reproduzíveis. Ao capturar as versões ou dependências específicas de bibliotecas de software, o arquivo de bloqueio garante que os builds sejam reproduzíveis em diferentes ambientes e ao longo do tempo. Os desenvolvedores podem contar com resultados consistentes e previsíveis ao criar projetos.

  • Resolução eficiente de problemas. O arquivo de bloqueio permite que o Bazel pule o processo de resolução se não houver mudanças nas dependências do projeto desde o último build. Isso melhora significativamente a eficiência do build, especialmente em cenários em que a resolução pode levar muito tempo.

  • Estabilidade e redução de riscos. O arquivo de bloqueio ajuda a manter a estabilidade impedindo atualizações inesperadas ou mudanças interruptivas em bibliotecas externas. Ao bloquear as dependências em versões específicas, o risco de introduzir bugs devido a atualizações incompatíveis ou não testadas é reduzido.

Conteúdo do arquivo de bloqueio

O arquivo de bloqueio contém todas as informações necessárias para determinar se o estado do projeto mudou. Ele também inclui o resultado da criação do projeto no estado atual. O arquivo de bloqueio consiste em duas partes principais:

  1. Entradas da resolução do módulo, como moduleFileHash, flags e localOverrideHashes, bem como a saída da resolução, que é moduleDepGraph.
  2. Para cada extensão de módulo, o arquivo de bloqueio inclui entradas que afetam, representadas por transitiveDigest, e a saída da execução dessa extensão, chamada de generatedRepoSpecs.

Confira um exemplo que demonstra a estrutura do arquivo de bloqueio, além de explicações para cada seção:

{
  "lockFileVersion": 1,
  "moduleFileHash": "b0f47b98a67ee15f9.......8dff8721c66b721e370",
  "flags": {
    "cmdRegistries": [
      "https://bcr.bazel.build/"
    ],
    "cmdModuleOverrides": {},
    "allowedYankedVersions": [],
    "envVarAllowedYankedVersions": "",
    "ignoreDevDependency": false,
    "directDependenciesMode": "WARNING",
    "compatibilityMode": "ERROR"
  },
  "localOverrideHashes": {
    "bazel_tools": "b5ae1fa37632140aff8.......15c6fe84a1231d6af9"
  },
  "moduleDepGraph": {
    "<root>": {
      "name": "",
      "version": "",
      "executionPlatformsToRegister": [],
      "toolchainsToRegister": [],
      "extensionUsages": [
        {
          "extensionBzlFile": "extension.bzl",
          "extensionName": "lockfile_ext"
        }
      ],
      ...
    }
  },
  "moduleExtensions": {
    "//:extension.bzl%lockfile_ext": {
      "transitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
      "generatedRepoSpecs": {
        "hello": {
          "bzlFile": "@@//:extension.bzl",
          ...
        }
      }
    }
  }
}

Hash do arquivo do módulo

O moduleFileHash representa o hash do conteúdo do arquivo MODULE.bazel. Se algumas mudanças ocorrerem nesse arquivo, o valor do hash será diferente.

Sinalizações

O objeto Flags armazena todas as flags que podem afetar o resultado da resolução.

Hashes de substituição local

Se o módulo raiz incluir local_path_overrides, essa seção vai armazenar o hash do arquivo MODULE.bazel no repositório local. Ele permite rastrear mudanças dessa dependência.

Gráfico de dependência de módulo

O moduleDepGraph representa o resultado do processo de resolução usando as entradas mencionadas acima. Ele forma o gráfico de dependência de todos os módulos necessários para executar o projeto.

Extensões de módulo

A seção moduleExtensions é um mapa que inclui apenas as extensões usadas na invocação atual ou invocadas anteriormente, excluindo as extensões que não são mais utilizadas. Em outras palavras, se uma extensão não estiver mais sendo usada no gráfico de dependências, ela será removida do mapa moduleExtensions.

Cada entrada nesse mapa corresponde a uma extensão usada e é identificada pelo arquivo e nome que a contém. O valor correspondente de cada entrada contém as informações relevantes associadas a essa extensão:

  1. O transitiveDigest é o resumo da implementação da extensão e dos arquivos .bzl transitivos.
  2. O generatedRepoSpecs é o resultado da execução dessa extensão com a entrada atual.

Outro fator que pode afetar os resultados da extensão é o uso. Embora não sejam armazenados no arquivo de bloqueio, os usos são considerados ao comparar o estado atual da extensão com o do arquivo de bloqueio.

Práticas recomendadas

Para maximizar os benefícios do recurso de arquivo de bloqueio, considere as seguintes práticas recomendadas:

  • Atualize o arquivo de bloqueio regularmente para refletir as mudanças nas dependências ou na configuração do projeto. Isso garante que os builds subsequentes sejam baseados no conjunto de dependências mais atualizado e preciso.

  • Inclua o arquivo de bloqueio no controle de versões para facilitar a colaboração e garantir que todos os membros da equipe tenham acesso ao mesmo arquivo, promovendo ambientes de desenvolvimento consistentes em todo o projeto.

Ao seguir essas práticas recomendadas, você pode usar o recurso de arquivo de bloqueio no Bazel, o que leva a fluxos de trabalho de desenvolvimento de software mais eficientes, confiáveis e colaborativos.