Regras de repositório

Informar um problema Ver fonte Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

Nesta página, você aprende a definir regras de repositório e encontra exemplos para mais detalhes.

Um repositório externo é uma árvore de diretórios que contém arquivos de origem utilizáveis em um build do Bazel, gerado sob demanda ao executar a regra de repositório correspondente. Os repositórios podem ser definidos de várias maneiras, mas, em última análise, cada um é 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 do Maven), mas também para gerar arquivos BUILD específicos do host em que o Bazel está sendo executado.

Definição de regra do repositório

Em um arquivo .bzl, use a função repository_rule para definir uma nova regra de repositório e armazená-la 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 de dentro de uma função de implementação de extensão de módulo.

Os dois principais componentes de uma definição de regra de repositório são o esquema de atributo e a função de implementação. O esquema de atributo determina os nomes e tipos de atributos transmitidos a uma invocação de regra de repositório, e a função de implementação é executada quando o repositório precisa ser buscado.

Atributos

Atributos são argumentos transmitidos à invocação da regra do repositório. O esquema de atributos aceitos por uma regra de repositório é especificado usando o argumento attrs quando a regra é definida com uma chamada para repository_rule. Exemplo de definição dos 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_rules têm o atributo name definido implicitamente. Esse é um atributo de string que se comporta de maneira um pouco mágica: quando especificado como entrada para uma invocação de regra de repositório, ele usa um nome de repositório aparente. No entanto, quando lido da função de implementação da regra de repositório usando repository_ctx.attr.name, ele retorna o nome canônico do repositório.

Função de implementação

Cada regra de repositório requer uma função implementation. Ele contém a lógica real da regra e é executado 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 que transformariam a regra em uma reproduzível, gerando o mesmo repositório. Por exemplo, para uma regra que rastreia 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 baixar um arquivo da Internet). Consulte a documentação da API 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 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. A função de implementação deve criar o repositório no sistema de arquivos. Isso é chamado de "busca" do repositório.

Ao contrário dos destinos regulares, os repositórios não são necessariamente buscados novamente quando algo muda e faz com que o repositório seja diferente. Isso acontece porque há coisas que o Bazel não consegue detectar mudanças ou que causariam muito sobrecarga em cada build (por exemplo, coisas buscadas na rede). Portanto, os repositórios só serão buscados novamente se uma das seguintes condições mudar:

  • Os atributos transmitidos à invocação da regra do repositório.
  • O código Starlark que compreende a implementação da regra do repositório.
  • O valor de qualquer variável de ambiente transmitida ao método getenv() de repository_ctx ou declarada com o atributo environ do repository_rule. Os valores dessas variáveis de ambiente podem ser codificados na linha de comando com a flag --repo_env.
  • A existência, o conteúdo e o tipo de caminhos que estão sendo watchados na função de implementação da regra do repositório.
    • Outros métodos de repository_ctx com um parâmetro watch, como read(), execute() e extract(), também podem fazer com que os caminhos sejam monitorados.
    • Da mesma forma, repository_ctx.watch_tree e path.readdir podem fazer com que os caminhos sejam monitorados de outras maneiras.
  • Quando bazel fetch --force é 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 será buscado novamente em bazel fetch --force --configure. Repositórios não configure não são buscados novamente.
  • 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.

Forçar a nova busca de repositórios externos

Às vezes, um repositório externo pode ficar desatualizado sem que haja mudanças na definição ou nas dependências dele. 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 fetch --force --all.

Além disso, algumas regras do repositório 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 definição repository_rule tem o atributo configure definido. Use bazel fetch --force --configure.

Exemplos

  • Cadeia de ferramentas autoconfigurada em C++: usa uma regra de repositório para criar automaticamente os arquivos de configuração em C++ para o Bazel. Para isso, procura o compilador local em C++, o ambiente e as flags compatíveis com o compilador em C++.

  • Os repositórios Go usam vários repository_rule para definir a lista de dependências necessárias para usar as regras do Go.

  • Por padrão, rules_jvm_external cria um repositório externo chamado @maven que gera destinos de build para cada artefato do Maven na árvore de dependências transitivas.