Nesta página, explicamos como criar regras de repositório e fornecemos 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 BUILD
e artefatos. 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.
Criação de regras de repositório
Em um arquivo .bzl
, use a função repository_rule para criar uma nova regra de repositório e armazene-a em uma variável global.
Uma regra de repositório personalizada pode ser usada da mesma forma que uma regra de repositório nativo. Ele
tem um atributo name
obrigatório, e cada destino presente nos arquivos de build
pode ser chamado de @<name>//package:target
, em que <name>
é o valor do
atributo name
.
A regra é carregada quando você a cria explicitamente ou se é uma dependência
do build. Nesse caso, o Bazel executará a função implementation
. Essa
função descreve como criar o repositório, o conteúdo e os arquivos BUILD
.
Atributos
Os atributos são argumentos de regra transmitidos como um dict para o argumento da regra attrs
.
Os atributos e os tipos deles são definidos e listados quando você define uma
regra de repositório. Um exemplo que define 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
criação). Os dois atributos implícitos são name
(assim como para as regras de criação) 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
.
Caso um nome de atributo comece com _
, ele é particular e não pode ser definido pelos usuários.
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
transformaria essa regra em uma regra reproduzível que gera o mesmo repositório. 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 a biblioteca para mais
contexto. Exemplos
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 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 mudar que faria com que o repositório fosse 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 só serão buscados novamente se uma das seguintes coisas mudar:
- Os parâmetros transmitidos para a declaração do repositório no
arquivo
WORKSPACE
. - O código Starlark, que inclui a implementação do repositório.
- O valor de qualquer variável de ambiente declarada com o atributo
environ
darepository_rule
. Os valores dessas variáveis de ambiente podem ser conectados na linha de comando com a flag--action_env
, mas essa sinalização invalidará todas as ações do build. - 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 sync
é 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 sync
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
for 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 seja alterado (por exemplo, o arquivoWORKSPACE
ou um arquivo carregado), independentemente de as alterações resultarem em uma alteração 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 supõe-se que esses repositórios se comunicam com a rede ou sejam 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, 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, as origens de busca de um repositório podem
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 sync
.
Além disso, algumas regras inspecionam a máquina local e poderão ficar desatualizadas se for feito upgrade da máquina local. 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 e use bazel sync --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.