Como adaptar regras do Bazel para execução remota

Esta página é destinada a usuários do Bazel que escrevem regras personalizadas de build e teste e querem entender os requisitos para regras do Bazel no contexto da execução remota.

A execução remota permite que o Bazel execute ações em uma plataforma separada, como um data center. O Bazel usa um protocolo gRPC (em inglês) para a execução remota. Você pode testar a execução remota com o bazel-buildfarm (em inglês), um projeto de código aberto que tem como objetivo fornecer uma plataforma de execução remota distribuída.

Nesta página, usamos a seguinte terminologia ao se referir a diferentes tipos de ambiente ou plataformas:

  • Plataforma de host: em que o Bazel é executado.
  • Plataforma de execução: em que as ações do Bazel são executadas.
  • Plataforma de destino: em que as saídas de build (e algumas ações) são executadas.

Informações gerais

Ao configurar um build do Bazel para execução remota, siga as diretrizes descritas nesta página para garantir que ele seja executado remotamente sem erros. Isso se deve à natureza da execução remota, ou seja:

  • Ações de build isoladas. As ferramentas de build não retêm o estado, e as dependências não podem vazar entre elas.

  • Ambientes de execução diversos. A configuração do build local nem sempre é adequada para ambientes de execução remota.

Nesta página, descrevemos os problemas que podem surgir ao implementar regras personalizadas de build e teste do Bazel para execução remota e como evitá-los. Ele aborda os seguintes tópicos:

Como invocar ferramentas de build usando regras do conjunto de ferramentas

Uma regra do conjunto de ferramentas do Bazel é um provedor de configuração que informa a uma regra de build quais ferramentas, como compiladores e vinculadores, usar e como configurá-las usando parâmetros definidos pelo criador da regra. Uma regra de conjunto de ferramentas permite que as regras de compilação e teste invoquem ferramentas de compilação de maneira previsível e pré-configurada, que é compatível com a execução remota. Por exemplo, use uma regra de conjunto de ferramentas em vez de invocar ferramentas de compilação por meio de PATH, JAVA_HOME ou outras variáveis locais que podem não estar definidas como valores equivalentes (ou de forma alguma) no ambiente de execução remota.

Atualmente, existem regras do conjunto de ferramentas para regras de compilação e teste do Bazel para Scala, Rust e Go. Novas regras de conjunto de ferramentas estão sendo criadas para outras linguagens e ferramentas, como bash. Se não houver uma regra de conjunto de ferramentas para a ferramenta usada, considere criar uma regra de conjunto de ferramentas.

Como gerenciar dependências implícitas

Se uma ferramenta de compilação puder acessar dependências em ações de compilação, essas ações falharão quando executadas remotamente, porque cada ação de compilação remota é executada separadamente das outras. Algumas ferramentas de compilação retêm o estado em ações de compilação e acesso a dependências que não foram incluídas explicitamente na invocação da ferramenta, o que fará com que as ações de compilação executadas remotamente falhem.

Por exemplo, quando o Bazel instrui um compilador com estado a compilar foo localmente, o compilador retém as referências às saídas de compilação do foo. Quando o Bazel instrui o compilador a compilar bar, que depende de foo, sem declarar explicitamente essa dependência no arquivo BUILD para inclusão na invocação do compilador, a ação é executada com êxito, desde que a mesma instância do compilador seja executada para ambas as ações (como é comum para execução local). No entanto, como em um cenário de execução remota cada ação de compilação executa uma instância de compilador separada, o estado do compilador e a dependência implícita de bar em foo serão perdidos e a compilação falhará.

Para ajudar a detectar e eliminar esses problemas de dependência, o Bazel 0.14.1 oferece o sandbox local do Docker, que tem as mesmas restrições para dependências que a execução remota. Use o sandbox para preparar seu build para execução remota identificando e resolvendo erros de build relacionados a dependências. Consulte Como solucionar problemas de execução remota do Bazel com o Docker Sandbox para mais informações.

Como gerenciar binários dependentes da plataforma

Normalmente, um binário criado na plataforma do host não pode ser executado com segurança em uma plataforma de execução remota arbitrária devido a dependências potencialmente incompatíveis. Por exemplo, o binário SingleJar fornecido com o Bazel é direcionado à plataforma do host. No entanto, para a execução remota, o SingleJar precisa ser compilado como parte do processo de criação do seu código para que ele seja direcionado à plataforma de execução remota. Consulte a lógica de seleção de destino.

Não envie binários de ferramentas de build necessárias para seu build com o código-fonte, a menos que você tenha certeza de que eles serão executados com segurança na plataforma de execução. Em vez disso, siga um destes procedimentos:

  • Envie ou faça referência externa ao código-fonte da ferramenta para que ela possa ser criada para a plataforma de execução remota.

  • Pré-instale a ferramenta no ambiente de execução remota (por exemplo, um contêiner de conjunto de ferramentas), se ela for estável o suficiente, e use as regras do conjunto de ferramentas para executá-la na versão.

Como gerenciar regras do WORKSPACE no estilo de configuração

As regras WORKSPACE do Bazel podem ser usadas para testar a plataforma host em busca de ferramentas e bibliotecas exigidas pelo build, que, para builds locais, também é a plataforma de execução do Bazel. Se o build depender explicitamente de ferramentas e artefatos locais, ele falhará durante a execução remota se a plataforma de execução remota não for idêntica à plataforma do host.

As seguintes ações realizadas pelas regras WORKSPACE não são compatíveis com a execução remota:

  • Como criar binários. Executar ações de compilação em regras WORKSPACE resulta em binários incompatíveis com a plataforma de execução remota, caso seja diferente da plataforma do host.

  • Instalando pacotes pip. Os pacotes pip instalados por regras WORKSPACE exigem que as dependências sejam pré-instaladas na plataforma de host. Esses pacotes, criados especificamente para a plataforma host, serão incompatíveis com a plataforma de execução remota se forem diferentes da plataforma host.

  • Simulação para ferramentas ou artefatos locais. Links simbólicos para ferramentas ou bibliotecas instaladas na plataforma host criadas por regras WORKSPACE farão com que o build falhe na plataforma de execução remota, já que o Bazel não poderá localizá-los. Em vez disso, crie links simbólicos usando ações de build padrão para que as ferramentas e bibliotecas vinculadas sejam acessíveis na árvore runfiles do Bazel. Não use repository_ctx.symlink para vincular arquivos de destino fora do diretório de repositório externo.

  • Imitação da plataforma de hospedagem. Evite criar arquivos fora da árvore runfiles do Bazel, assim como variáveis de ambiente e ações semelhantes, porque eles podem se comportar de maneira inesperada na plataforma de execução remota.

Para encontrar possíveis comportamentos não herméticos, use o registro de regras do Workspace.

Se uma dependência externa executa operações específicas dependentes da plataforma do host, divida essas operações entre WORKSPACE e regras de build da seguinte maneira:

  • Inspeção de plataforma e enumeração de dependência. Essas operações são seguras para serem executadas localmente usando regras WORKSPACE, que podem verificar quais bibliotecas estão instaladas, fazer o download dos pacotes que precisam ser criados e preparar os artefatos necessários para compilação. Para execução remota, essas regras também precisam oferecer suporte ao uso de artefatos pré-verificados para fornecer as informações que normalmente seriam recebidas durante a inspeção da plataforma do host. Os artefatos pré-verificados permitem que o Bazel descreva dependências como se fossem locais. Para isso, use instruções condicionais ou a sinalização --override_repository.

  • Gerar ou compilar artefatos específicos do destino e mutação da plataforma. Essas operações precisam ser executadas usando regras de build normais. Ações que produzem artefatos específicos do destino para dependências externas precisam ser executadas durante a compilação.

Para gerar mais facilmente artefatos pré-verificados para execução remota, use regras WORKSPACE para emitir arquivos gerados. Você pode executar essas regras em cada novo ambiente de execução, como dentro de cada contêiner de conjunto de ferramentas, e verificar as saídas da compilação de execução remota no repositório de origem para referência.

Por exemplo, para as regras do Tensorflow para cuda e python, as regras de WORKSPACE produzem o seguinte BUILD files. Na execução local, são usados os arquivos produzidos pela verificação do ambiente do host. Para execução remota, uma instrução condicional em uma variável de ambiente permite que a regra use arquivos que foram verificados no repositório.

Os arquivos BUILD declaram genrules, que pode ser executado de maneira local e remota, e realizam o processamento necessário que era feito anteriormente por meio de repository_ctx.symlink, como mostrado aqui.