Nesta página, você vai aprender a criar um programa com o Bazel, a sintaxe de comandos de build e sintaxe de padrão de destino.
Guia de início rápido
Para executar o Bazel, acesse o diretório base workspace.
ou qualquer um dos subdiretórios e digite bazel
. Consulte build se você
precisar criar um novo espaço de trabalho.
bazel help
[Bazel release bazel version]
Usage: bazel command options ...
Comandos disponíveis
analyze-profile
: analisa os dados do perfil do build.aquery
: executa uma consulta no gráfico de ações pós-análise.build
: cria os destinos especificados.canonicalize-flags
: canoniza flags do Bazel.clean
: remove os arquivos de saída e, opcionalmente, interrompe o servidor.cquery
: executa uma consulta de gráfico de dependências de pós-análise.dump
: despeja o estado interno do processo do servidor do Bazel.help
: mostra a ajuda dos comandos ou do índice.info
: mostra informações de tempo de execução sobre o servidor do Bazel.fetch
: busca todas as dependências externas de um destino.mobile-install
: instala apps em dispositivos móveis.query
: executa uma consulta de gráfico de dependência.run
: executa o destino especificado.shutdown
: interrompe o servidor do Bazel.test
: cria e executa os destinos de teste especificados.version
: imprime informações da versão do Bazel.
Receber ajuda
bazel help command
: mostra ajuda e opções paracommand
.bazel help
startup_options
: opções para a JVM que hospeda o Bazel.bazel help
target-syntax
: explica a sintaxe para especificar metas.bazel help info-keys
: mostra uma lista de chaves usadas pelo comando info.
A ferramenta bazel
executa muitas funções, chamadas de comandos. Os métodos
as mais usadas são bazel build
e bazel test
. Você pode procurar na ajuda on-line
mensagens usando bazel help
.
Criando um destino
Antes de iniciar um build, você precisa de um espaço de trabalho. Um espaço de trabalho árvore de diretórios que contém todos os arquivos de origem necessários para criar seu para o aplicativo. Ele permite executar um build de um modelo volume
Para criar um programa com o Bazel, digite bazel build
seguido do
target que você quer criar.
bazel build //foo
Depois de emitir o comando para criar //foo
, você vai ver uma saída semelhante a esta:
INFO: Analyzed target //foo:foo (14 packages loaded, 48 targets configured).
INFO: Found 1 target...
Target //foo:foo up-to-date:
bazel-bin/foo/foo
INFO: Elapsed time: 9.905s, Critical Path: 3.25s
INFO: Build completed successfully, 6 total actions
Primeiro, o Bazel carrega todos os pacotes no gráfico de dependência do destino. Isso
inclui dependências declaradas, arquivos listados diretamente no arquivo BUILD
do destino.
e dependências transitivas, os arquivos listados nos arquivos BUILD
da sua
de destino. Depois de identificar todas as dependências, o Bazel analisa
para fins de correção e cria as ações de build. Por último, o Bazel executa
os compiladores e outras ferramentas do build.
Durante a fase de execução da compilação, o Bazel imprime mensagens de progresso. O progresso As mensagens incluem a etapa de build atual (como compilador ou vinculador), já que o início e o número de ações concluídas sobre o número total de ações de compilação. Conforme o o número total de ações aumenta conforme o Bazel descobre o gráfico de ação inteiro, mas o número se estabiliza em alguns segundos.
No final da compilação, o Bazel imprime os destinos solicitados,
se esses arquivos foram criados corretamente. Em caso afirmativo, os arquivos de saída podem ser
encontradas. Os scripts que executam builds podem analisar essa saída de maneira confiável. ver
--show_result
para mais detalhes.
Se você digitar o mesmo comando novamente, o build terminará muito mais rápido.
bazel build //foo
INFO: Analyzed target //foo:foo (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //foo:foo up-to-date:
bazel-bin/foo/foo
INFO: Elapsed time: 0.144s, Critical Path: 0.00s
INFO: Build completed successfully, 1 total action
Essa é uma versão nula. Como nada mudou, não há pacotes para recarregar. e nenhuma etapa de build para executar. Se algo foi alterado em "foo" ou as dependências, o Bazel executa novamente algumas ações de compilação ou conclui uma build incremental.
Como criar vários destinos
O Bazel permite várias maneiras de especificar os destinos a serem criados. Coletivamente,
isso é conhecido como padrões de destino. Essa sintaxe é usada em comandos como
build
, test
ou query
.
Já os rótulos são usados para especificar
por exemplo, para declarar dependências em arquivos BUILD
, o destino
especificar vários destinos. Os padrões de segmentação são uma generalização
a sintaxe do rótulo para conjuntos de destinos, usando caracteres curinga. No caso mais simples,
rótulo válido também é um padrão-alvo válido, identificando um conjunto
alvo.
Todos os padrões de destino que começam com //
são resolvidos em relação ao atual
espaço de trabalho.
//foo/bar:wiz |
Apenas o //foo/bar:wiz de destino. |
//foo/bar |
É equivalente a //foo/bar:bar . |
//foo/bar:all |
Todos os destinos de regra no pacote foo/bar . |
//foo/... |
Todos os destinos de regras em todos os pacotes abaixo do diretório foo . |
//foo/...:all |
Todos os destinos de regras em todos os pacotes abaixo do diretório foo . |
//foo/...:* |
Todos os destinos (regras e arquivos) em todos os pacotes abaixo do diretório foo . |
//foo/...:all-targets |
Todos os destinos (regras e arquivos) em todos os pacotes abaixo do diretório foo . |
//... |
Todos os destinos de regras em pacotes no repositório principal. Não inclui metas de repositórios externos. |
//:all |
Todos os destinos de regra no pacote de nível superior, se houver um arquivo `BUILD` no raiz do espaço de trabalho. |
Os padrões de destino que não começam com //
são resolvidos em relação ao
diretório de trabalho atual. Estes exemplos pressupõem um diretório de trabalho de foo
:
:foo |
Equivalente a //foo:foo . |
bar:wiz |
É equivalente a //foo/bar:wiz . |
bar/wiz |
Equivalente a:
|
bar:all |
Equivalente a //foo/bar:all . |
:all |
Equivalente a //foo:all . |
...:all |
Equivalente a //foo/...:all . |
... |
Equivalente a //foo/...:all . |
bar/...:all |
Equivalente a //foo/bar/...:all . |
Por padrão, os links simbólicos de diretório são seguidos para padrões de destino recursivos, exceto aqueles que apontam para a base de saída, como a conveniência links simbólicos que são criados no diretório raiz do espaço de trabalho.
Além disso, o Bazel não segue links simbólicos ao avaliar o destino recursivo
em qualquer diretório que contenha um arquivo nomeado da seguinte maneira:
DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN
foo/...
é um caractere curinga sobre pacotes, indicando todos os pacotes recursivamente
abaixo do diretório foo
(para todas as raízes do caminho do pacote). :all
é um
caractere curinga sobre destinos, correspondendo a todas as regras em um pacote. Esses dois podem ser
combinado, como em foo/...:all
, e quando ambos os caracteres curinga são usados, ele pode ser
abreviado como foo/...
.
Além disso, :*
(ou :all-targets
) é um caractere curinga que corresponde a cada destino.
nos pacotes correspondentes, incluindo arquivos que normalmente não são criados por nenhuma regra,
como arquivos _deploy.jar
associados a regras java_binary
.
Isso implica que :*
denota um superconjunto de :all
. e possivelmente
confusa, essa sintaxe permite que o conhecido caractere curinga :all
seja usado para
builds típicos, em que a criação de destinos como _deploy.jar
não é o ideal.
Além disso, o Bazel permite que uma barra seja usada em vez dos dois pontos exigidos por
a sintaxe do rótulo; isso geralmente é conveniente ao usar a expansão de nome de arquivo Bash.
Por exemplo, foo/bar/wiz
é equivalente a //foo/bar:wiz
(se houver
pacote foo/bar
) ou para //foo:bar/wiz
(se houver um pacote foo
).
Muitos comandos do Bazel aceitam uma lista de padrões de destino como argumentos, e todos eles
respeitar o operador de negação de prefixo -
. Isso pode ser usado para subtrair um conjunto de
destinos do conjunto especificado pelos argumentos anteriores. Isso significa
a ordem é importante. Por exemplo,
bazel build foo/... bar/...
significa "criar todos os destinos abaixo de foo
e todos os destinos abaixo de bar
", enquanto
bazel build -- foo/... -foo/bar/...
significa "criar todos os destinos abaixo de foo
, exceto aqueles abaixo de foo/bar
". O
O argumento --
é obrigatório para evitar que os argumentos subsequentes comecem com -
seja interpretada como opções adicionais.
É importante ressaltar que subtrair metas dessa forma não
garantir que eles não sejam criados, porque podem ser dependências de destinos
que não foram subtraídas. Por exemplo, se houver um //foo:all-apis
de destino
que, entre outros, dependiam de //foo/bar:api
, este último seria criado conforme
parte da construção do primeiro.
Os destinos com tags = ["manual"]
não estão incluídos nos padrões de destino com caracteres curinga
(...
, :*
, :all
etc.) quando especificado em comandos como
bazel build
e bazel test
(mas estão incluídos em
caracteres curinga negativos, ou seja, serão subtraídos). Você deve
especifique esses destinos de teste com padrões explícitos de destino na linha de comando se
você quer que o Bazel as compile/teste. Por outro lado, bazel query
não realiza
qualquer filtragem automaticamente (isso anularia o propósito de
bazel query
).
Como buscar dependências externas
Por padrão, o Bazel faz o download e vincula dependências externas de dependências externas durante a
ser construído. No entanto, isso pode ser indesejável, porque você deseja saber
quando novas dependências externas são adicionadas ou porque você quer
"pré-busca" dependências (por exemplo, antes de um voo em que você vai estar off-line). Se você
quiser evitar que novas dependências sejam adicionadas durante a criação,
é possível especificar a sinalização --fetch=false
. Essa sinalização só
se aplica às regras de repositório que não apontam para um diretório no diretório
no sistema de arquivos. Por exemplo, em local_repository
,
new_local_repository
e regras de repositório do SDK e do NDK do Android
sempre entrará em vigor, independentemente do valor --fetch
.
Se você não permitir a busca durante builds, e o Bazel encontrar novas instâncias dependências, o build falhará.
É possível buscar dependências manualmente executando bazel fetch
. Se
não permitir durante a busca do build, será necessário executar bazel fetch
:
- Antes de criar pela primeira vez.
- Depois de adicionar uma nova dependência externa.
Depois disso, não será necessário executá-lo novamente até que o ESPAÇO DE TRABALHO mudanças no arquivo.
fetch
recebe uma lista de destinos para os quais buscar dependências. Para
exemplo, isso buscaria as dependências necessárias para criar //foo:bar
e //bar:baz
:
bazel fetch //foo:bar //bar:baz
Para buscar todas as dependências externas de um espaço de trabalho, execute:
bazel fetch //...
Com o Bazel 7 ou mais recente, se você tiver o Bzlmod ativado, também é possível buscar todos dependências externas executando
bazel fetch
Você não precisa executar a busca do Bazel se tiver todas as ferramentas que está
usando (de jars de biblioteca para o próprio JDK) na raiz do espaço de trabalho.
No entanto, se você estiver usando algo fora do diretório do espaço de trabalho, o Bazel
executará automaticamente bazel fetch
antes da execução;
bazel build
.
O cache do repositório
O Bazel tenta evitar a busca do mesmo arquivo várias vezes, mesmo que o mesmo arquivo
necessário em diferentes espaços de trabalho ou se a definição de um
repositório foi alterado, mas ainda precisa do mesmo arquivo para download. Para isso,
O Bazel armazena em cache todos os arquivos baixados no cache do repositório que, por padrão,
está localizado em ~/.cache/bazel/_bazel_$USER/cache/repos/v1/
. O
o local pode ser alterado pela opção --repository_cache
. O
o cache é compartilhado entre todos os espaços de trabalho e versões instaladas do Bazel.
Uma entrada é retirada do cache se
O Bazel tem certeza de que tem uma cópia do arquivo correto, ou seja, se o
de download tem uma soma SHA256 do arquivo especificado e um arquivo com essa
está no cache. Portanto, especificar um hash para cada arquivo externo
não apenas uma boa ideia do ponto de vista da segurança, também ajuda a evitar
downloads desnecessários.
A cada ocorrência em cache, o horário de modificação do arquivo no cache é atualizado. Dessa forma, o último uso de um arquivo no diretório de cache pode facilmente por exemplo, a limpeza manual do cache. O cache nunca é limpos automaticamente, pois podem conter uma cópia de um arquivo mais disponíveis no upstream.
[Descontinuado] Diretórios de arquivos de distribuição
Descontinuado: é preferível usar o cache do repositório para criar builds off-line.
O diretório de distribuição é outro mecanismo do Bazel para evitar downloads. O Bazel pesquisa os diretórios de distribuição antes do cache do repositório. A principal diferença é que o diretório de distribuição exige instruções de preparação.
Usar o
--distdir=/path/to-directory
especifique mais diretórios somente leitura para procurar arquivos
em vez de buscá-los. Um arquivo é retirado desse diretório se o nome do arquivo
é igual ao nome de base do URL e, além disso, o hash do arquivo é
igual ao especificado na solicitação de download. Isso só funciona se o
hash de arquivo é especificado na declaração WORKSPACE.
Embora a condição no nome do arquivo não seja necessária para a correção, ela reduz o número de arquivos candidatos a um por diretório especificado. Neste maneira, a especificação de diretórios de arquivos de distribuição permanece eficiente, mesmo que o número de arquivos nesse diretório aumenta.
Como executar o Bazel em um ambiente com isolamento físico
Para manter o tamanho do binário do Bazel pequeno, as dependências implícitas dele são buscadas. na rede durante a execução pela primeira vez. Essas dependências implícitas conter conjuntos de ferramentas e regras que podem não ser necessárias para todos. Para exemplo, as ferramentas do Android são desagrupadas e buscadas apenas ao criar projetos.
No entanto, essas dependências implícitas podem causar problemas ao executar o Bazel em uma ambiente com isolamento físico, mesmo que você tenha fornecido todos os seus dependências. Para resolver isso, você pode preparar um cache de repositório (com o Bazel 7 ou ou diretório de distribuição (com o Bazel anterior à versão 7) contendo essas dependências em uma máquina com acesso à rede e, em seguida, transferi-las com uma abordagem off-line.
Cache do repositório (com Bazel 7 ou mais recente)
Para preparar o cache do repositório, use o
--repository_cache
. Você precisará fazer isso uma vez para cada nova versão binária do Bazel, já que
as dependências implícitas podem ser diferentes para cada versão.
Para buscar essas dependências fora do ambiente com isolamento térmico, primeiro crie um espaço de trabalho vazio:
mkdir empty_workspace && cd empty_workspace
touch MODULE.bazel
touch WORKSPACE
Para buscar as dependências integradas do Bzlmod, execute
bazel fetch --repository_cache="path/to/repository/cache"
Se você ainda depende do arquivo WORKSPACE legado, busque o WORKSPACE integrado dependências, execute
bazel sync --repository_cache="path/to/repository/cache"
Por fim, quando você usar o Bazel no ambiente com isolamento físico, transmita a mesma
sinalização --repository_cache
. Para facilitar, adicione como .bazelrc
.
entrada:
common --repository_cache="path/to/repository/cache"
Além disso, talvez seja necessário clonar
BCR localmente e usar
sinalização --registry
para apontar sua cópia local e impedir que o Bazel acesse o
BCR pela Internet. Adicione a linha abaixo ao .bazelrc
:
common --registry="path/to/local/bcr/registry"
Diretório de distribuição (com Bazel anterior à 7)
Para preparar o diretório de distribuição, use o
--distdir
. Você precisará fazer isso uma vez para cada nova versão binária do Bazel, já que
as dependências implícitas podem ser diferentes para cada versão.
Para criar essas dependências fora do ambiente com isolamento térmico, primeiro Confira a árvore de origem do Bazel na versão correta:
git clone https://github.com/bazelbuild/bazel "$BAZEL_DIR"
cd "$BAZEL_DIR"
git checkout "$BAZEL_VERSION"
Depois, crie o tarball contendo as dependências implícitas de ambiente de execução para esse versão específica do Bazel:
bazel build @additional_distfiles//:archives.tar
Exporte o tarball para um diretório que possa ser copiado para o isolamento térmico
de nuvem. Observe a sinalização --strip-components
, porque --distdir
pode ser
bastante exigente com o nível de aninhamento de diretórios:
tar xvf bazel-bin/external/additional_distfiles/archives.tar \
-C "$NEW_DIRECTORY" --strip-components=3
Por fim, quando você usar o Bazel no ambiente com isolamento físico, transmita o --distdir
que aponta para o diretório. Para facilitar, adicione como .bazelrc
.
entrada:
build --distdir=path/to/directory
Configurações do build e compilação cruzada
Todas as entradas que especificam o comportamento e o resultado de um determinado build podem ser
divididos em duas categorias distintas. O primeiro tipo é o intrínseco,
informações armazenadas nos arquivos BUILD
do seu projeto: a regra de build, o
valores dos atributos e o conjunto completo de suas dependências transitivas.
O segundo tipo são os dados externos ou ambientais, fornecidos pelo usuário ou
pela ferramenta de criação: a escolha da arquitetura-alvo, compilação e vinculação
e outras opções de configuração de conjunto de ferramentas. Nos referimos a um conjunto completo
de dados ambientais como uma configuração.
Em qualquer build, pode haver mais de uma configuração. Considere um
de compilação cruzada, em que você cria um executável //foo:bin
para uma versão de 64 bits
mas sua estação de trabalho é uma máquina de 32 bits. Claramente, o build vai
exigem a criação de //foo:bin
usando um conjunto de ferramentas capaz de criar
mas o sistema de compilação também precisa criar várias ferramentas usadas durante a
por conta própria. Por exemplo, ferramentas criadas a partir da origem e depois
usadas em uma regra geral e precisam ser criados para execução na estação de trabalho. Assim,
podemos identificar duas configurações: a configuração "exec", que é usada
para criar ferramentas que são executadas durante o build e a configuração de destino
(ou solicitar configuração, mas dizemos "configuração de destino" com mais frequência)
embora essa palavra já tenha muitos significados), o que é usado para criar
que você acabou de solicitar.
Tipicamente, há muitas bibliotecas que são pré-requisitos tanto da biblioteca
destino de build (//foo:bin
) e uma ou mais ferramentas de execução, por exemplo, algumas
bibliotecas de base. Essas bibliotecas precisam ser criadas duas vezes, uma para o comando
e outra para a de destino. o Bazel cuida
garantindo que ambas as variantes sejam criadas e que os arquivos derivados sejam mantidos
separados para evitar interferência; Normalmente, esses destinos podem ser construídos simultaneamente,
porque são independentes umas das outras. Se você vir mensagens de progresso
indicando que um determinado destino está sendo construído duas vezes, esta é a probabilidade
explicação.
A configuração "exec" é derivada da configuração de destino da seguinte maneira:
- Use a mesma versão do Crosstool (
--crosstool_top
) conforme especificada no solicitação de configuração, a menos que--host_crosstool_top
seja especificado. - Use o valor de
--host_cpu
para--cpu
(padrão:k8
). - Use os mesmos valores dessas opções, conforme especificado na solicitação
configuração:
--compiler
,--use_ijars
, e se--host_crosstool_top
for usado, o valor de--host_cpu
é usado para procurar umdefault_toolchain
no Crosstool (ignorando--compiler
) para a execução configuração do Terraform. - Use o valor de
--host_javabase
para--javabase
- Use o valor de
--host_java_toolchain
para--java_toolchain
- Use builds otimizados para código C++ (
-c opt
). - Não gera informações de depuração (
--copt=-g0
). - Remover informações de depuração de executáveis e bibliotecas compartilhadas
(
--strip=always
). - Colocar todos os arquivos derivados em um local especial, diferente daquele usado pelo qualquer configuração de solicitação possível.
- Suprimir a marcação de binários com dados de build (consulte as opções de
--embed_*
). - Todos os outros valores permanecem com os valores padrão.
Há muitas razões pelas quais pode ser preferível selecionar um exec diferente da solicitação. Mais importante:
Primeiro, ao usar binários otimizados, você reduz o tempo gasto vinculando e executando as ferramentas, o espaço em disco ocupado pelas ferramentas e a o tempo de E/S da rede em builds distribuídos.
Segundo, ao desacoplar as configurações "exec" e "request" em todos os builds, você evitar recriações muito caras que resultariam de pequenas alterações no solicitação de configuração (como a alteração de uma opção do vinculador faz), conforme descrito antes.
Corrigir recriações incrementais
Um dos principais objetivos do projeto do Bazel é garantir recriações. As ferramentas de build anteriores, especialmente as baseadas em Make, criam vários e suposições insatisfatórias na implementação de builds incrementais.
Primeiro, que os carimbos de data/hora dos arquivos aumentam monotonicamente. Embora este seja o desse caso típico, é muito fácil cair em desacordo com essa suposição; sincronizando com um revisões anteriores de um arquivo diminui o tempo de modificação desse arquivo; Os sistemas baseados em Make não serão recriados.
De modo mais geral, embora o Make detecte alterações nos arquivos, ele não detecta alterações
a comandos. Se você mudar as opções passadas ao compilador em um determinado build
o Make não vai executar novamente o compilador e será necessário descartar manualmente
as saídas inválidas do build anterior usando make clean
.
Além disso, o Make não é robusto contra o encerramento malsucedido de um de seus subprocessos depois que aquele subprocesso começou a gravar em seu arquivo de saída. a execução atual do Make falhar, a invocação subsequente do Make presumir cegamente que o arquivo de saída truncado é válido (por ser mais recente do que as entradas) e não será reconstruído. Da mesma forma, se o processo Make for morto, uma situação semelhante pode ocorrer.
O Bazel evita essas suposições, entre outras. O Bazel mantém um banco de dados de todas trabalho já feito e só omitirá uma etapa de versão se descobrir que o conjunto de arquivos de entrada (e os carimbos de data/hora) dessa etapa do build, e a compilação da etapa de build, devem corresponder exatamente a um no banco de dados e conjunto de arquivos de saída (e os respectivos carimbos de data/hora) da entrada do banco de dados corresponde exatamente os carimbos de data/hora dos arquivos em disco. Qualquer mudança nos arquivos de entrada ou na saída ou ao próprio comando, fará com que a etapa de criação seja reexecutada.
O benefício para os usuários de builds incrementais corretos é: menos tempo desperdiçado devido
confusão. Além disso, menos tempo gasto aguardando recriações causadas pelo uso de make
clean
, seja ela necessária ou preventiva.
Criar consistência e builds incrementais
Formalmente, definimos o estado de um build como consistente quando todas as existem arquivos de saída e seu conteúdo está correto, conforme especificado pelas etapas ou e as regras necessárias para criá-las. Quando você edita um arquivo de origem, o estado da build é considerado inconsistente e permanece inconsistente até a próxima execução a ferramenta de build até a conclusão. Descrevemos essa situação como instável inconsistência, porque é apenas temporária e a consistência é restaurada ao executar a ferramenta de build.
Existe outro tipo de inconsistência que é perniciosa: a estável
e inconsistências. Se o build atingir um estado inconsistente estável e, em seguida,
invocação bem-sucedida da ferramenta de build não restaura a consistência: o build
ficou "travada" e as saídas permanecem incorretas. Estados inconsistentes estáveis
são o principal motivo para os usuários do Make (e outras ferramentas de build) digitarem make clean
.
Descobrir que a ferramenta de build falhou dessa maneira (e depois recuperar
pode levar muito tempo e ser muito frustrante.
Conceitualmente, a maneira mais simples de ter um build consistente é abandonar todas as saídas de build anteriores e comece de novo: faça de cada build um build limpo. Essa abordagem é obviamente muito demorada para ser prática (exceto para engenheiros de lançamento) e, portanto, para ser útil, a ferramenta de compilação deve ser capaz de para executar builds incrementais sem comprometer a consistência.
A análise de dependência incremental correta é difícil e, como descrito acima, muitas outras ferramentas de build não conseguem evitar estados inconsistentes estáveis durante builds incrementais. Por outro lado, o Bazel oferece a seguinte garantia: depois que uma invocação bem-sucedida da ferramenta de compilação durante a qual você não fez edições, o estejam em um estado consistente. Se você editar os arquivos de origem durante uma build, o Bazel não garante a consistência do resultado do build atual. Mas isso garante que os resultados da próxima compilação restaurar a consistência.
Como em todas as garantias, há alguns detalhes: há algumas formas conhecidas de entrar em um estado inconsistente estável com o Bazel. Não garantimos que investigar tais problemas surgindo de tentativas deliberadas de encontrar bugs no análise de dependência incremental, mas vamos investigar e fazer o possível para corrigir todos os estados inconsistentes estáveis que surjam de problemas normais ou "razoáveis" do ferramenta de build.
Se você detectar um estado inconsistente estável com o Bazel, informe um bug.
Execução no modo sandbox
O Bazel usa sandboxes para garantir que as ações sejam executadas hermeticamente e
corretamente. O Bazel executa spawns (fala fraca: ações) em sandboxes que
contêm apenas o conjunto mínimo de arquivos que a ferramenta exige para realizar seu trabalho. Atualmente
O sandbox funciona no Linux 3.12 ou mais recente com a opção CONFIG_USER_NS
.
ativado e também no macOS 10.11 ou mais recente.
O Bazel vai mostrar um aviso se o sistema não for compatível com o sandbox para alertas.
ao fato de que não há garantia de que as construções são herméticas e podem afetar
o sistema host de formas desconhecidas. Para desativar esse aviso, transmita o
Sinalização --ignore_unsupported_sandboxing
para o Bazel.
Em algumas plataformas, como o Google Kubernetes
do Google Kubernetes Engine ou do Debian,
os namespaces de usuário são desativados por padrão devido à segurança
problemas. Para verificar isso, consulte o arquivo
/proc/sys/kernel/unprivileged_userns_clone
: se existir e contiver um 0,
os namespaces de usuários podem ser ativados
sudo sysctl kernel.unprivileged_userns_clone=1
.
Em alguns casos, o sandbox do Bazel não executa as regras por causa do sistema
configuração da infraestrutura. O sintoma geralmente é uma falha que emite uma mensagem semelhante a
namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory
:
Nesse caso, tente desativar o sandbox para regras gerais com
--strategy=Genrule=standalone
e para outras regras com
--spawn_strategy=standalone
. Além disso, informe um bug na
rastreador de problemas e mencione qual distribuição Linux você está usando para que possamos
investigar e fornecer uma correção em uma versão subsequente.
Fases de um build
No Bazel, um build ocorre em três fases distintas. como usuário, compreender a diferença entre eles fornece informações sobre as opções que controlam um build Confira abaixo.
Fase de carregamento
A primeira é o carregamento, durante o qual todos os arquivos BUILD necessários para o os destinos iniciais e o fechamento transitivo de dependências são carregados, analisados, avaliados e armazenados em cache.
Na primeira compilação após o início de um servidor Bazel, a fase de carregamento normalmente leva muitos segundos, a partir do qual muitos arquivos BUILD são carregados do sistema de arquivos. Em builds subsequentes, especialmente se nenhum arquivo BUILD tiver sido alterado, o carregamento ocorre muito rapidamente.
Os erros relatados durante essa fase incluem: pacote não encontrado, destino não encontrado, erros léxicos e gramaticais em um arquivo BUILD e erros de avaliação.
Fase de análise
A segunda fase, análise, envolve a análise e validação semânticas de cada regra de build, a construção de um gráfico de dependência de build e a determinação de exatamente qual trabalho deve ser feito em cada etapa do build.
Assim como o carregamento, a análise também leva vários segundos quando calculada por completo. No entanto, o Bazel armazena em cache o gráfico de dependência de uma compilação para a próxima e somente analisa novamente o que precisa ser feito, o que pode tornar as compilações incrementais extremamente rápidas em caso os pacotes não tenham mudado desde o build anterior.
Os erros relatados neste estágio incluem: dependências inadequadas, dependências entradas em uma regra e todas as mensagens de erro específicas dela.
As fases de carregamento e análise são rápidas porque o Bazel evita arquivos desnecessários E/S neste estágio, lendo apenas arquivos BUILD para determinar o trabalho a ser feito. Por padrão, ele é uma boa base para ferramentas de análise, como o comando query do Bazel, que é implementado sobre o carregamento fase de testes.
Fase de execução
A terceira e última fase do build é a execução. Essa fase garante que se as saídas de cada etapa do build forem consistentes com as entradas, compilação/vinculação/etc. as ferramentas conforme necessário. É nessa etapa que o build gasta a maior parte do tempo, variando de alguns segundos a mais de uma hora para um grande ser construído. Os erros relatados durante essa fase incluem: arquivos de origem ausentes, erros em uma ferramenta executada por alguma ação de compilação ou falha de uma ferramenta para conjunto esperado de saídas.