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 GitHub, um artefato 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 WORKSPACE
tradicional, focado em repositório, e
o sistema MODULE.bazel
mais recente com foco em módulo (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
Bzlmod. Confira o guia Bz0.mod
para saber como migrar{/1.
Neste documento, explicamos os conceitos relacionados ao gerenciamento de dependências externas no Bazel antes de entrar em mais detalhes sobre os dois sistemas em ordem.
conceitos
Repositório
Um diretório com um arquivo WORKSPACE
ou WORKSPACE.bazel
, contendo arquivos de origem a serem usados em uma versão do Bazel. Geralmente encurtado 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 é executado no mesmo repositório principal.
Historicamente, os conceitos de "repositório" e "workspace" foram confundidos. O termo "workspace" é frequentemente usado para se referir ao repositório principal e às vezes usado até mesmo como sinônimo de "repositório".
Nome do repositório canônico
O nome canônico pelo qual um repositório é endereçável. Dentro do contexto de um
espaço de trabalho, cada repositório tem um único nome canônico. Um destino dentro de um repositório
com o 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 do repositório aparente
O nome pelo qual um repositório é endereçável no contexto de outro repositório.
Isso pode ser considerado o "apelido" de um repo: o repositório com o nome canônico michael
pode ter o nome aparente mike
no contexto do repo alice
, mas pode ter o nome aparente mickey
no contexto do repo bob
. Nesse caso, um destino dentro de michael
pode ser tratado 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 do repositório aparente" para um "nome de repositório canônico".
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", "buscar um determinado artefato Maven e disponibilizá-lo como um
destino java_import
" ou simplesmente "vincular um diretório local" Todo repo é
definido chamando uma regra de repo com um número apropriado de argumentos.
Consulte Regras de repositório para mais informações sobre como gravar 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 vincula simbolicamente 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 repo associada. Os repositórios definidos em um espaço de trabalho não ficam disponíveis no disco local antes de serem buscados.
Normalmente, o Bazel só busca um repositório quando precisa de algo e ele ainda não foi buscado. Se o repositório já tiver sido buscado antes, o Bazel só vai fazer uma nova busca se a definição tiver sido alterada.
Layout do diretório
Depois de ser buscado, o repo pode ser encontrado no subdiretório external
na base de saída, sob o nome canônico dele.
Execute o seguinte comando para ver 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 a partir de módulos, executa extensões sobre o gráfico e define repos adequadamente.
Um módulo do Bazel é um projeto do Bazel que pode ter várias
versões, e cada uma delas publica metadados sobre outros módulos de que
ele depende. Um módulo precisa ter um arquivo MODULE.bazel
na raiz do repositório, ao lado do
arquivo WORKSPACE
. Esse arquivo é o manifesto do módulo, declarando o nome,
a versão, a lista de dependências, entre outras informações. Confira a seguir 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ó pode listar suas dependências diretas, que o Bzlmod pesquisa em um
registro do Bazel: por padrão, o Bazel Central
Registry. 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 da versão.
Após a resolução da 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 dados personalizados, chamados de tags, que são consumidas por extensões de módulo após a resolução do módulo para definir outros repositórios. Essas extensões têm recursos semelhantes às regras de repo, permitindo que elas executem ações como E/S de arquivos e envio de solicitações de rede. Entre outras coisas, eles permitem que o Bazel interaja com outros sistemas de gerenciamento de pacotes e, ao mesmo tempo, respeita o gráfico de dependência criado com base nos módulos do Bazel.
Links externos no Bzlmod
- Exemplos de uso do Bzlmod em bazelbuild/examples (em inglês)
- Revisão das dependências externas do Bazel (documento de design original do Bzlmod)
- Palestra da BazelCon 2021 sobre a Bzlmod
- Palestra do Dia da Comunidade do Bazel no Bzlmod
Definir repositórios com WORKSPACE
Antes, é possível gerenciar dependências externas definindo repositórios no
arquivo WORKSPACE
(ou WORKSPACE.bazel
). Esse arquivo tem uma sintaxe semelhante aos
arquivos BUILD
, empregando 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
arquivo WORKSPACE
:
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 com o nome canônico foo
. No sistema WORKSPACE
, por padrão, o nome canônico de um repositório também é o nome aparente dele para
todos os outros repositórios.
Falhas no sistema do WORKSPACE
Nos anos desde o lançamento do sistema WORKSPACE
, os usuários relataram
muitos pontos problemáticos, incluindo:
- O Bazel não avalia os arquivos
WORKSPACE
de nenhuma dependência. Portanto, todas as dependências transitivas precisam ser definidas no arquivoWORKSPACE
do repo 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 que os usuários
chamem essa macro nos arquivos
WORKSPACE
.- Isso tem seus próprios problemas: as macros não conseguem
load
outros arquivos.bzl
, portanto, esses projetos precisam definir as dependências transitivas nessa macro "deps" ou contornar esse problema fazendo com que o usuário chame macros "deps" em várias camadas. - O Bazel avalia o arquivo
WORKSPACE
sequencialmente. Além disso, as dependências são especificadas usandohttp_archive
com 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 losango (A
depende deB
eC
;B
eC
dependem de versões diferentes deD
).
- Isso tem seus próprios problemas: as macros não conseguem
Devido às deficiências do WORKSPACE, o Bzlmod vai substituir o sistema legado WORKSPACE em versões futuras do Bazel. Leia o guia de migração do Bzlmod (em inglês) sobre como migrar para o Bzlmod.