Modo do fornecedor

O modo fornecedor é um recurso que permite criar uma cópia local de dependências externas. Isso é útil para builds off-line ou quando você quer controlar a origem de uma dependência externa.

Ativar o modo de fornecedor

É possível ativar o modo de fornecedor especificando a flag --vendor_dir.

Por exemplo, adicione ao arquivo .bazelrc:

# Enable vendor mode with vendor directory under <workspace>/vendor_src
common --vendor_dir=vendor_src

O diretório do fornecedor pode ser um caminho relativo para a raiz do espaço de trabalho ou um caminho absoluto.

Fornecer um repositório externo específico

É possível usar o comando vendor com a flag --repo para especificar qual repositório fornecer. Ele aceita o nome canônico do repositório e o nome aparente do repositório.

Por exemplo, ao executar:

bazel vendor --vendor_dir=vendor_src --repo=@rules_cc

ou

bazel vendor --vendor_dir=vendor_src --repo=@@rules_cc+

vão fazer com que rules_cc seja vendido em <workspace root>/vendor_src/rules_cc+.

Disponibilizar pacotes de terceiros para dependências externas de determinados destinos

Para incluir todas as dependências externas necessárias para criar determinados padrões de destino, execute bazel vendor <target patterns>.

Por exemplo:

bazel vendor --vendor_dir=vendor_src //src/main:hello-world //src/test/...

vai fornecer todos os repositórios necessários para criar o destino //src/main:hello-world e todos os destinos em //src/test/... com a configuração atual.

Por baixo dos panos, ele executa um comando bazel build --nobuild para analisar os padrões de destino. Portanto, flags de build podem ser aplicadas a esse comando e afetar o resultado.

Criar o destino off-line

Com as dependências externas disponibilizadas por pacotes de terceiros, é possível criar o destino off-line

bazel build --vendor_dir=vendor_src //src/main:hello-world //src/test/...

A build precisa funcionar em um ambiente de build limpo, sem acesso à rede e cache do repositório.

Portanto, é possível fazer check-in na origem vendida e criar os mesmos destinos off-line em outra máquina.

Disponibilizar pacotes de terceiros para todas as dependências externas

Para incluir todos os repositórios no gráfico de dependências externas transitivas, execute:

bazel vendor --vendor_dir=vendor_src

Observe que a disponibilização de pacotes de terceiros de todas as dependências tem algumas desvantagens:

  • Buscar todos os repositórios, incluindo os introduzidos de forma transitiva, pode levar tempo.
  • O diretório do fornecedor pode ficar muito grande.
  • Alguns repositórios podem não ser buscados se não forem compatíveis com a plataforma ou o ambiente atual.

Portanto, considere a disponibilização de pacotes de terceiros para metas específicas primeiro.

Ferramentas do fornecedor para subcomandos do Bazel

Alguns subcomandos do Bazel (como bazel mod tidy) têm dependências implícitas de ferramentas que não podem ser acessadas de destinos de build do usuário. Portanto, elas não são incluídas por bazel vendor //.... Para vender essas ferramentas também, adicione o grupo de arquivos @bazel_tools//tools:tools_for_bazel_subcommands à sua invocação de fornecedor:

bazel vendor //... @bazel_tools//tools:tools_for_bazel_subcommands

Isso é necessário se você planeja executar comandos como bazel mod tidy em um ambiente off-line ou hermético (por exemplo, com --vendor_dir e --nofetch).

Configurar o modo de fornecedor com VENDOR.bazel

Você pode controlar como determinados repositórios são processados com o arquivo VENDOR.bazel localizado no diretório vendor.

Há duas diretivas disponíveis, ambas aceitando uma lista de nomes canônicos de repositórios como argumentos:

  • ignore(): para ignorar completamente um repositório do modo do fornecedor.
  • pin(): para fixar um repositório na origem vendida atual como se houvesse uma flag --override_repository para esse repositório. O Bazel NÃO vai atualizar a origem vendida para este repositório ao executar o comando de venda, a menos que ela seja desfixada. O usuário pode modificar e manter manualmente a origem vendida para esse repositório.

Por exemplo:

ignore("@@rules_cc+")
pin("@@bazel_skylib+")

Com essa configuração

  • Ambos os repositórios serão excluídos dos comandos subsequentes do fornecedor.
  • O Repo bazel_skylib será substituído pela origem localizada no diretório vendor.
  • O usuário pode modificar com segurança a origem vendida de bazel_skylib.
  • Para fazer isso, o usuário precisa desativar a declaração de PIN primeiro.bazel_skylib

Entenda como o modo do fornecedor funciona

O Bazel busca dependências externas de um projeto em $(bazel info output_base)/external. Fazer o vendoring de dependências externas significa mover arquivos e diretórios relevantes para o diretório de fornecedor especificado e usar a origem vendored para builds posteriores.

O conteúdo vendido inclui:

  • O diretório do repositório
  • O arquivo de marcador do repositório

Durante um build, se o arquivo marcador vendido estiver atualizado ou se o repositório estiver fixado no arquivo VENDOR.bazel, o Bazel usará a origem vendida criando um link simbólico para ela em $(bazel info output_base)/external em vez de realmente executar a regra do repositório. Caso contrário, um aviso será mostrado, e o Bazel vai voltar a buscar a versão mais recente do repositório.

Arquivos de registro do fornecedor

O Bazel precisa realizar a resolução do módulo para buscar dependências externas, o que pode exigir o acesso a arquivos de registro pela Internet. Para fazer um build off-line, o Bazel vende todos os arquivos de registro buscados da rede no diretório <vendor_dir>/_registries.

Repositórios externos podem conter symlinks que apontam para outros arquivos ou diretórios. Para garantir que os links simbólicos funcionem corretamente, o Bazel usa a seguinte estratégia para reescrever os links simbólicos na origem vendida:

  • Crie um link simbólico <vendor_dir>/bazel-external que aponte para $(bazel info output_base)/external. Ele é atualizado automaticamente por todos os comandos do Bazel.
  • Para a origem vendida, reescreva todos os links simbólicos que apontam originalmente para um caminho em $(bazel info output_base)/external para um caminho relativo em <vendor_dir>/bazel-external.

Por exemplo, se o symlink original for

<vendor_dir>/repo_foo+/link  =>  $(bazel info output_base)/external/repo_bar+/file

Ele será reescrito como

<vendor_dir>/repo_foo+/link  =>  ../../bazel-external/repo_bar+/file

onde

<vendor_dir>/bazel-external  =>  $(bazel info output_base)/external  # This might be new if output base is changed

Como <vendor_dir>/bazel-external é gerado automaticamente pelo Bazel, é recomendável adicioná-lo a .gitignore ou equivalente para evitar o check-in.

Com essa estratégia, os symlinks na origem vendida funcionam corretamente mesmo depois que ela é movida para outro local ou a base de saída do Bazel é alterada.