Nesta página, explicamos como definir regras de repositório e fornecemos exemplos para mais detalhes.
Um repositório externo é uma árvore de diretórios,
contendo arquivos de origem utilizáveis em um build do Bazel, que é gerado sob demanda
executando a regra repo correspondente. Os repositórios podem ser definidos de várias
maneiras, mas cada repositório é definido invocando uma regra de repositório, assim como
os destinos de build são definidos invocando regras de build. Eles podem ser usados para depender de
bibliotecas de terceiros (como bibliotecas empacotadas Maven), mas também para gerar
arquivos BUILD
específicos para o host em que o Bazel está sendo executado.
Definição da regra de repositório
Em um arquivo .bzl
, use a função repository_rule para definir uma nova regra de repositório e armazene-a em uma variável global. Depois que uma regra de repositório é definida,
ela pode ser invocada como uma função para definir repositórios. Essa invocação geralmente é
realizada dentro de uma função de implementação de
extensão do módulo.
Os dois componentes principais de uma definição de regra de repositório são o esquema de atributos e a função de implementação. O esquema de atributos determina os nomes e tipos de atributos transmitidos para uma invocação de regra de repositório, e a função de implementação é executada quando o repositório precisa ser buscado.
Atributos
Os atributos são argumentos transmitidos para a invocação da regra de repositório. O esquema de atributos aceitos por uma regra de repo é especificado usando o argumento attrs
quando a regra de repo é definida com uma chamada para repository_rule
. Um exemplo definindo os atributos
url
e sha256
como strings:
http_archive = repository_rule(
implementation=_impl,
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 o atributo name
definido implicitamente. Esse é um
atributo de string que se comporta de forma mágica: quando especificado como uma entrada para
uma invocação de regra de repo, ele recebe um nome de repositório aparente. No entanto, quando lido da
função de implementação da regra do repo usando repository_ctx.attr.name
, ele retorna
o nome do repositório canônico.
Função de implementação
Cada regra de repositório requer uma função implementation
. Ela contém a
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 de acordo com os
parâmetros especificados ou um dict com um conjunto de parâmetros para essa regra que
a transformaria em uma regra reproduzível gerando o mesmo repo. Por
exemplo, uma regra que rastreia um repositório git significaria retornar um
identificador de confirmação específico em vez de uma ramificação flutuante
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 os documentos da API para
saber mais. 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 uma regra de repositório é executada quando o Bazel precisa de um destino desse repositório, por exemplo, quando outro destino (em outro repositório) depende dele ou se ele é mencionado na linha de comando. Espera-se que a função de implementação crie o repositório no sistema de arquivos. Isso é chamado de "busca" do repositório.
Ao contrário dos destinos normais, os repositórios não são necessariamente buscados novamente quando algo muda que faria com que ele seja diferente. Isso ocorre porque há coisas em que o Bazel não consegue detectar mudanças ou causar muita sobrecarga em cada build (por exemplo, itens buscados na rede). Portanto, os repositórios serão buscados novamente somente se uma das seguintes condições mudar:
- Os atributos transmitidos à invocação da regra do repo.
- O código Starlark, que inclui a implementação da regra de repositório.
- O valor de qualquer variável de ambiente transmitida para o método
getenv()
derepository_ctx
ou declarado com o atributoenviron
darepository_rule
. Os valores dessas variáveis de ambiente podem ser conectados na linha de comando com a flag--repo_env
. - O conteúdo de qualquer arquivo transmitido para
read()
,execute()
e métodos semelhantes derepository_ctx
, que é referenciado por um rótulo (por exemplo,//mypkg:label.txt
, mas nãomypkg/label.txt
). - Quando
bazel fetch --force
é executado.
Há dois parâmetros de repository_rule
que controlam quando os repositórios são
buscados novamente:
- Se a sinalização
configure
for definida, o repositório só será buscado novamente embazel fetch
quando o parâmetro--configure
for transmitido a ele. Se o atributo não for definido, esse comando não vai causar uma nova busca. - Se a sinalização
local
estiver definida, além dos casos acima, o repositório também será buscado novamente quando o servidor do Bazel for reiniciado.
Como reiniciar a função de implementação
A função de implementação pode ser reiniciada enquanto um repositório está sendo buscado, caso uma dependência solicitada esteja ausente. Nesse caso, a execução da função de implementação é interrompida, a dependência ausente é resolvida e a função é executada novamente depois que a dependência é resolvida. Para evitar reinicializações desnecessárias, que são caras, porque o acesso à rede pode precisar ser repetido, os argumentos de rótulo são pré-buscados, desde que todos os argumentos possam ser resolvidos para um arquivo existente. Resolver um caminho de uma string ou rótulo 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 alteração na definição ou nas dependências. Por exemplo, uma origem de busca de repositório pode
seguir uma ramificação específica de um repositório de terceiros, e novas confirmações estão
disponíveis nessa ramificação. Nesse caso, é possível pedir ao Bazel para buscar novamente todos
os repositórios externos incondicionalmente chamando bazel fetch --force --all
.
Além disso, algumas regras de repositório inspecionam a máquina local e podem ficar desatualizadas se a máquina local tiver sido atualizada. Aqui é possível pedir ao Bazel para
buscar novamente apenas os repositórios externos em que a definição
repository_rule
tem o atributo configure
definido. Use
bazel fetch --all --configure
.
Exemplos
Conjunto de ferramentas configurado automaticamente para C++: ele usa uma regra de repositório para criar automaticamente os arquivos de configuração C++ para o Bazel procurando o compilador C++ local, o ambiente e as sinalizações compatíveis com o compilador do 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 Maven na árvore de dependências transitiva.