Esta página aborda 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 seu próprio espaço de trabalho, com 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á em execução.
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 armazená-la em uma variável global.
Uma regra de repositório personalizada pode ser usada como uma regra de repositório nativa. Ela
tem um atributo name obrigatório, e cada destino presente nos arquivos de build
pode ser referenciado como @<name>//package:target, em que <name> é o valor do
name atributo.
A regra é carregada quando você a cria explicitamente ou se ela é uma dependência do build. Nesse caso, o Bazel executa 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 dicionário 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 de 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 têm atributos definidos implicitamente (assim como as regras de build). Os dois atributos implícitos são name (assim como para 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 nativas
local_repository
e
new_local_repository.
Se um nome de atributo começar com _, ele será particular 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. 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 com os parâmetros especificados ou um dicionário com um conjunto de parâmetros para essa regra que a transformaria em uma regra reproduzível, gerando o mesmo repositório. Por exemplo, para uma regra que acompanha um repositório Git, isso significa retornar um identificador de commit 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
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 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. A função de implementação precisa criar 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 e faz com que o repositório seja diferente. Isso ocorre porque há coisas que o Bazel não consegue detectar mudanças ou que causariam muita sobrecarga em cada build (por exemplo, coisas buscadas na rede). Portanto, os repositórios são buscados novamente apenas se uma das seguintes situações mudar:
- Os parâmetros transmitidos à declaração do repositório no arquivo
WORKSPACE. - O código Starlark que compreende a implementação do repositório.
- O valor de qualquer variável de ambiente transmitida ao método
repository_ctx'sgetenv()ou declarada com o atributoenvirondarepository_rule. Os valores dessas variáveis de ambiente podem ser codificados na linha de comando com a--repo_envflag. - O conteúdo de qualquer arquivo transmitido aos métodos
read(),execute()e semelhantes derepository_ctxque é 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 flag
configureestiver definida, o repositório só será buscado novamente embazel syncquando o--configureparâmetro for transmitido a ele. Se o atributo não estiver definido, esse comando não causará uma nova busca. Se a flag
localestiver 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 arquivoWORKSPACEou 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 para se comunicar com a rede ou serem 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 da 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 ter que ser repetido), os argumentos de rótulo são buscados previamente, 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 construído apenas durante a execução da função ainda pode causar uma reinicialização.
Como forçar a 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 buscar novamente todos os repositórios externos incondicionalmente chamando bazel sync.
Além disso, algumas regras inspecionam a máquina local e podem ficar desatualizadas se ela for atualizada. Aqui, você pode pedir ao Bazel para
buscar novamente apenas os repositórios externos em que a
repository_rule
definição tem o atributo configure definido. Use bazel sync --configure.
Exemplos
Conjunto de ferramentas configurado automaticamente para C++: ela usa uma regra de repositório para criar automaticamente os arquivos de configuração do C++ para o Bazel, procurando o compilador local do C++, o ambiente e as flags compatíveis com o compilador do C++.
Os repositórios Go usam vários
repository_rulepara definir a lista de dependências necessárias para usar as regras Go.rules_jvm_external cria um repositório externo chamado
@mavenpor padrão que gera destinos de build para cada artefato do Maven na árvore de dependência transitiva.