O Bazel oferece suporte a dependências externas, arquivos de origem (texto e binários) usados no build que não são do seu espaço de trabalho. Por exemplo, eles podem ser um conjunto de regras hospedado em um repositório do GitHub, um artefato do Maven ou um diretório na sua máquina local fora do espaço de trabalho atual.
A partir do Bazel 6.0, há duas maneiras de gerenciar dependências externas com o Bazel:
o sistema tradicional WORKSPACE focado em repositórios, e
o sistema MODULE.bazel mais recente focado em módulos (com o codinome Bzlmod,
e ativado com a flag --enable_bzlmod). Os dois sistemas podem ser usados
juntos, mas o Bzlmod está substituindo o sistema WORKSPACE em versões futuras do Bazel.
Consulte o guia de migração do Bzlmod para saber como
migrar.
Este documento explica os conceitos relacionados ao gerenciamento de dependências externas no Bazel antes de entrar em mais detalhes sobre os dois sistemas.
Conceitos
Repositório
Um diretório com um arquivo WORKSPACE ou WORKSPACE.bazel, que contém arquivos de origem
a serem usados em um build do Bazel. Geralmente abreviado para apenas repo.
Repositório principal
O repositório em que o comando atual do Bazel está sendo executado.
Espaço de trabalho
O ambiente compartilhado por todos os comandos do Bazel executados no mesmo repositório principal.
Historicamente, os conceitos de "repositório" e "espaço de trabalho" foram confundidos. O termo "espaço de trabalho" costuma ser usado para se referir ao repositório principal e, às vezes, até como sinônimo de "repositório".
Nome canônico do repositório
O nome canônico pelo qual um repositório pode ser endereçado. No contexto de um
espaço de trabalho, cada repositório tem um único nome canônico. Um destino dentro de um repositório
cujo nome canônico é canonical_name pode ser endereçado pelo rótulo
@@canonical_name//pac/kage:target (observe o @ duplo).
O repositório principal sempre tem a string vazia como nome canônico.
Nome aparente do repositório
O nome pelo qual um repositório pode ser endereçado no contexto de outro repositório.
Isso pode ser considerado como um "apelido" de um repositório: o repositório com o nome canônico
michael pode ter o nome aparente mike no contexto do repositório
alice, mas pode ter o nome aparente mickey no contexto do repositório
bob. Nesse caso, um destino dentro de michael pode ser endereçado pelo rótulo
@mike//pac/kage:target no contexto de alice (observe o @ único).
Por outro lado, isso pode ser entendido como um mapeamento de repositório: cada repositório mantém um mapeamento de "nome aparente do repositório" para um "nome canônico do repositório".
Regra de repositório
Um esquema para definições de repositório que informa ao Bazel como materializar um
repositório. Por exemplo, pode ser "fazer o download de um arquivo zip de um determinado URL
e extraí-lo", ou "buscar um determinado artefato do Maven e disponibilizá-lo como um
java_import destino", ou simplesmente "criar um link simbólico para um diretório local". Cada repositório é
definido chamando uma regra de repositório com um número adequado de argumentos.
Consulte Regras de repositório para mais informações sobre como escrever suas próprias regras de repositório.
As regras de repositório mais comuns são
http_archive, que faz o download de um arquivo
de um URL e o extrai, e
local_repository, que cria um link simbólico para um
diretório local que já é um repositório do Bazel.
Buscar um repositório
A ação de disponibilizar um repositório no disco local executando a regra de repositório associada Os repositórios definidos em um espaço de trabalho não estão disponíveis no disco local antes de serem buscados.
Normalmente, o Bazel só busca um repositório quando precisa de algo dele, e o repositório ainda não foi buscado. Se o repositório já tiver sido buscado antes, o Bazel só o buscará novamente se a definição dele tiver mudado.
Layout do diretório
Depois de buscado, o repositório pode ser encontrado no subdiretório external na
base de saída, com o nome canônico.
Execute o comando a seguir para conferir o conteúdo do repositório com o
nome canônico canonical_name:
ls $(bazel info output_base)/external/ canonical_name Gerenciar dependências externas com o Bzlmod
O Bzlmod, o novo subsistema de dependência externa, não funciona diretamente com definições de repo. Em vez disso, ele cria um gráfico de dependência de módulos, executa extensões na parte de cima do gráfico e define repositórios de acordo com isso.
Um módulo do Bazel é um projeto do Bazel que pode ter várias
versões, cada uma delas publicando metadados sobre outros módulos de que depende. Um módulo precisa ter um arquivo MODULE.bazel na raiz do repositório, ao lado do
WORKSPACE arquivo. Esse arquivo é o manifesto do módulo, declarando o nome,
a versão, a lista de dependências, entre outras informações. Confira abaixo um exemplo básico:
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "protobuf", version = "3.19.0")
Um módulo só precisa listar as dependências diretas, que o Bzlmod procura em um
registro do Bazel. Por padrão, o Registro central
do Bazel. O registro fornece os
arquivos MODULE.bazel das dependências, o que permite que o Bazel descubra todo o
gráfico de dependência transitiva antes de realizar a resolução de versão.
Após a resolução de versão, em que uma versão é selecionada para cada módulo,
o Bazel consulta o registro novamente para saber como definir um repositório para cada módulo
(na maioria dos casos, usando http_archive).
Os módulos também podem especificar partes personalizadas de dados chamadas tags, que são consumidas por extensões de módulo após a resolução do módulo para definir repositórios adicionais. Essas extensões têm recursos semelhantes às regras de repositório, permitindo que elas executem ações como E/S de arquivos e envio de solicitações de rede. Entre outras coisas, elas permitem que o Bazel interaja com outros sistemas de gerenciamento de pacotes , respeitando o gráfico de dependência criado com módulos do Bazel.
Links externos no Bzlmod
- Exemplos de uso do Bzlmod em bazelbuild/examples
- Revisão das dependências externas do Bazel (documento de design original do Bzlmod, link em inglês)
- Palestra do BazelCon 2021 sobre o Bzlmod
- Palestra do Bazel Community Day sobre o Bzlmod
Definir repositórios com WORKSPACE
Historicamente, é possível gerenciar dependências externas definindo repositórios no
WORKSPACE (ou WORKSPACE.bazel) arquivo. Esse arquivo tem uma sintaxe semelhante aos
BUILD arquivos, usando regras de repositório em vez de regras de build.
O snippet a seguir é um exemplo de uso da regra de repositório http_archive no
WORKSPACE arquivo:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "foo",
urls = ["https://example.com/foo.zip"],
sha256 = "c9526390a7cd420fdcec2988b4f3626fe9c5b51e2959f685e8f4d170d1a9bd96",
)
O snippet define um repositório cujo nome canônico é foo. No WORKSPACE
sistema, por padrão, o nome canônico de um repositório também é o nome aparente para
todos os outros repositórios.
Limitações do sistema WORKSPACE
Nos anos desde que o sistema WORKSPACE foi introduzido, os usuários relataram
muitos pontos fracos, incluindo:
- O Bazel não avalia os arquivos
WORKSPACEde nenhuma dependência. Portanto, todas as dependências transitivas precisam ser definidas no arquivoWORKSPACEdo repositório principal, além das dependências diretas. - Para contornar isso, os projetos adotaram o padrão "deps.bzl", em que
definem uma macro que, por sua vez, define vários repositórios e pedem aos usuários que
chamem essa macro nos arquivos
WORKSPACE.- Isso tem problemas próprios: as macros não podem
loadoutros.bzlarquivos. Portanto, esses projetos precisam definir as dependências transitivas nessa macro "deps" ou contornar esse problema fazendo com que o usuário chame várias macros "deps" em camadas. - O Bazel avalia o arquivo
WORKSPACEsequencialmente. Além disso, as dependências são especificadas usandohttp_archivecom URLs, sem nenhuma informação de versão. Isso significa que não há uma maneira confiável de realizar a resolução de versão no caso de dependências de diamante (Adepende deBeC;BeCdependem de versões diferentes deD).
- Isso tem problemas próprios: as macros não podem
Devido às limitações do WORKSPACE, o Bzlmod vai substituir o sistema legado do WORKSPACE em versões futuras do Bazel. Leia o guia de migração do Bzlmod para saber como migrar para o Bzlmod.