Esta página explica como criar regras de repositório e fornece exemplos para mais detalhes.
Um repositório externo é uma regra que só pode ser usada
no arquivo WORKSPACE
e permite operações não herméticas na fase de carregamento
do Bazel. Cada regra de repositório externo cria o próprio espaço de trabalho, com os
próprios arquivos e artefatos BUILD
. Eles podem ser usados para depender de bibliotecas
de terceiros (como bibliotecas empacotadas do Maven), mas também para gerar arquivos BUILD
específicos para o host em que o Bazel está sendo executado.
Criação de regra de repositório
Em um arquivo .bzl
, use o
função repository_rule para criar um novo
regra de repositório e armazená-la em uma variável global.
Uma regra de repositório personalizada pode ser usada da mesma forma que uma regra de repositório nativa. Ela
tem um atributo name
obrigatório e todos os destinos presentes nos arquivos de build
pode ser chamado de @<name>//package:target
, em que <name>
é o valor do
name
.
A regra é carregada quando você a cria explicitamente ou se ela for uma dependência do
build. Nesse caso, o Bazel vai executar a função implementation
. Isso
descreve como criar o repositório, o conteúdo dele e os arquivos BUILD
.
Atributos
Os atributos são argumentos de regra transmitidos como um dict para o argumento de regra attrs
.
Os atributos e os tipos deles são definidos e listados quando você define uma
regra de repositório. Um exemplo de definição dos atributos url
e sha256
como
strings:
local_repository = repository_rule(
implementation=_impl,
local=True,
attrs={
"url": attr.string(mandatory=True)
"sha256": attr.string(mandatory=True)
}
)
Para acessar um atributo na função de implementação, use
repository_ctx.attr.<attribute_name>
:
def _impl(repository_ctx):
url = repository_ctx.attr.url
checksum = repository_ctx.attr.sha256
Todos os repository_rule
s têm atributos definidos implicitamente (assim como as regras
de build). Os dois atributos implícitos são name
(assim como as regras de build) e
repo_mapping
. O nome de uma regra de repositório pode ser acessado com
repository_ctx.name
: O significado de repo_mapping
é o mesmo das
regras de repositório nativo
local_repository
e
new_local_repository
.
Se o nome de um atributo começar com _
, ele será privado e os usuários não poderão defini-lo.
Função de implementação
Cada regra de repositório requer uma função implementation
. Ele contém
lógica real da regra e é executada estritamente na fase de carregamento.
A função tem exatamente um parâmetro de entrada, repository_ctx
. A função
retorna None
para indicar que a regra é reproduzível com os
parâmetros especificados ou um dicionário com um conjunto de parâmetros para essa regra que
a tornaria reproduzível, gerando o mesmo repositório. Por
exemplo, para uma regra que rastreia um repositório do Git, isso significa retornar um
identificador de confirmação específico em vez de uma ramificação flutuante que foi especificada
originalmente.
O parâmetro de entrada repository_ctx
pode ser usado para
acessar valores de atributos e funções não herméticas (encontrar um binário,
executar um binário, criar um arquivo no repositório ou fazer o download de um arquivo
da Internet). Consulte a biblioteca para mais informações
contexto. Exemplo:
def _impl(repository_ctx):
repository_ctx.symlink(repository_ctx.attr.path, "")
local_repository = repository_rule(
implementation=_impl,
...)
Quando a função de implementação é executada?
A função de implementação de um repositório é executada quando o Bazel precisa destino desse repositório, por exemplo, quando outro destino (em outro repositório) depende dele ou se ele é mencionado na linha de comando. A função de implementação precisa criar o repositório no sistema de arquivos. Isso é chamado de "busca" repositório.
Ao contrário dos destinos normais, os repositórios não são necessariamente buscados de novo quando algo muda e causa uma diferença no repositório. Isso é porque o Bazel não detecta mudanças em algumas coisas ou causar muita sobrecarga em cada compilação (por exemplo, itens buscados da rede). Portanto, os repositórios serão buscados novamente somente se um dos as seguintes mudanças:
- Os parâmetros transmitidos para a declaração do repositório no
WORKSPACE
. - O código Starlark que compreende a implementação do repositório.
- O valor de qualquer variável de ambiente declarada com o atributo
environ
dorepository_rule
. Os valores dessas variáveis de ambiente podem ser fixados no comando com o--action_env
(mas vai invalidar todas as ações da compilação). - O conteúdo de qualquer arquivo transmitido para
read()
,execute()
e similares métodos derepository_ctx
, que são referenciados por um rótulo (por exemplo,//mypkg:label.txt
, mas nãomypkg/label.txt
) - Quando
bazel sync
é executado.
Há dois parâmetros de repository_rule
que controlam quando os repositórios
são buscados novamente:
- Se a flag
configure
estiver definida, o repositório só vai ser buscado novamentebazel sync
quando o parâmetro--configure
for passado a ela (se o atributo não estiver definido, este comando não causará uma nova busca) Se a flag
local
estiver definida, além dos casos acima, o repositório também será buscado novamente quando o servidor do Bazel for reiniciado ou quando qualquer arquivo que afete a declaração do repositório mudar (por exemplo, o arquivoWORKSPACE
ou um arquivo que ele carrega), independentemente de as mudanças resultarem em uma mudança na declaração do repositório ou no código dele.Os repositórios não locais não são buscados novamente nesses casos. Isso ocorre porque esses repositórios são considerados como se estivessem se comunicando com a rede ou fossem caros.
Como reiniciar a função de implementação
A função de implementação pode ser reiniciada enquanto um repositório está sendo buscado se uma dependência solicitada estiver ausente. Nesse caso, a execução a função de implementação será interrompida, a dependência ausente será resolvida e a função será executada novamente depois que a dependência for resolvida. Para evitar reinicializações desnecessárias (que são caras, já que o acesso à rede pode precisar ser repetido), os argumentos de rótulo são pré-buscados, desde que todos os argumentos de rótulo possam ser resolvidos em um arquivo existente. A resolução de um caminho de uma string ou um rótulo que foi criado apenas durante a execução da função ainda pode causar uma reinicialização.
Como forçar uma nova busca de repositórios externos
Às vezes, um repositório externo pode ficar desatualizado sem nenhuma mudança na
definição ou nas dependências. Por exemplo, um repositório que busca fontes pode
seguir uma ramificação específica de um repositório de terceiros, e novos commits estão
disponíveis nessa ramificação. Nesse caso, você pode pedir ao Bazel para refazer todas as
repositórios externos incondicionalmente, chamando bazel sync
.
Além disso, algumas regras inspecionam a máquina local e podem ficar
desatualizadas se a máquina local for atualizada. Aqui você pode pedir ao Bazel para
apenas rebuscar os repositórios externos em que o
repository_rule
definição tiver o atributo configure
definido, use bazel sync --configure
.
Exemplos
Conjunto de ferramentas configurado automaticamente para C++: ele usa uma regra de repositório para criar automaticamente arquivos de configuração C++ para Bazel procurando pelo compilador C++ local, o e as sinalizações compatíveis com o compilador C++.
Os repositórios do Go usam vários
repository_rule
para definir a lista de dependências necessárias para usar as regras do Go.rules_jvm_external cria um repositório externo chamado
@maven
por padrão, que gera destinos de build para cada artefato do Maven na árvore de dependências transitivas.