Guia de consulta

Nesta página, mostramos como começar a usar a linguagem de consulta do Bazel para rastrear dependências no seu código.

Para detalhes de linguagem e da sinalização --output, consulte os manuais de referência, a referência de consulta do Bazel e a referência de cquery do Bazel. Para receber ajuda, digite bazel help query ou bazel help cquery na linha de comando.

Para executar uma consulta ignorando erros, como destinos ausentes, use a sinalização --keep_going.

Como encontrar as dependências de uma regra

Para ver as dependências de //foo, use a função deps na consulta do Bazel:

$ bazel query "deps(//foo)"
//foo:foo
//foo:foo-dep
...

Esse é o conjunto de todos os destinos necessários para criar //foo.

Como rastrear a cadeia de dependências entre dois pacotes

A biblioteca //third_party/zlib:zlibonly não está no arquivo BUILD para //foo, mas é uma dependência indireta. Como rastrear esse caminho de dependência? Há duas funções úteis aqui: allpaths e somepath. Também é possível excluir dependências de ferramentas com --notool_deps se você se importa apenas com o que está incluído no artefato criado, e não com todos os jobs possíveis.

Para visualizar o gráfico de todas as dependências, direcione a saída da consulta do Bazel por meio da ferramenta de linha de comando dot:

$ bazel query "allpaths(//foo, third_party/...)" --notool_deps --output graph | dot -Tsvg > /tmp/deps.svg

Quando um gráfico de dependência é grande e complicado, pode ser útil começar com um único caminho:

$ bazel query "somepath(//foo:foo, third_party/zlib:zlibonly)"
//foo:foo
//translations/tools:translator
//translations/base:base
//third_party/py/MySQL:MySQL
//third_party/py/MySQL:_MySQL.so
//third_party/mysql:mysql
//third_party/zlib:zlibonly

Se você não especificar --output graph com allpaths, receberá uma lista nivelada do gráfico de dependência.

$ bazel query "allpaths(//foo, third_party/...)"
  ...many errors detected in BUILD files...
//foo:foo
//translations/tools:translator
//translations/tools:aggregator
//translations/base:base
//tools/pkg:pex
//tools/pkg:pex_phase_one
//tools/pkg:pex_lib
//third_party/python:python_lib
//translations/tools:messages
//third_party/py/xml:xml
//third_party/py/xml:utils/boolean.so
//third_party/py/xml:parsers/sgmlop.so
//third_party/py/xml:parsers/pyexpat.so
//third_party/py/MySQL:MySQL
//third_party/py/MySQL:_MySQL.so
//third_party/mysql:mysql
//third_party/openssl:openssl
//third_party/zlib:zlibonly
//third_party/zlib:zlibonly_v1_2_3
//third_party/python:headers
//third_party/openssl:crypto

À parte: dependências implícitas

O arquivo BUILD para //foo nunca faz referência a //translations/tools:aggregator. Então, onde está a dependência direta?

Algumas regras incluem dependências implícitas em outras bibliotecas ou ferramentas. Por exemplo, para criar uma regra genproto, primeiro você precisa criar o Protocol Compiler. Dessa forma, cada regra genproto carrega uma dependência implícita no compilador de protocolo. Essas dependências não são mencionadas no arquivo de build, mas adicionadas pela ferramenta de build. O conjunto completo de dependências implícitas ainda não está documentado. O uso de --noimplicit_deps permite filtrar essas dependências dos resultados da consulta. Para o cquery, isso vai incluir conjuntos de ferramentas resolvidos.

Reverter dependências

Talvez você queira saber o conjunto de destinos que depende de algum destino. Por exemplo, se você for alterar algum código, pode querer saber que outro código você está prestes a quebrar. Você pode usar rdeps(u, x) para encontrar as dependências reversas dos destinos em x dentro do fechamento transitivo de u.

A Sky Query do Bazel é compatível com a função allrdeps, que permite consultar dependências reversas em um universo especificado por você.

Usos diversos

É possível usar bazel query para analisar muitas relações de dependência.

O que existe ...

Quais pacotes existem abaixo de foo?

bazel query 'foo/...' --output package

Quais regras estão definidas no pacote foo?

bazel query 'kind(rule, foo:*)' --output label_kind

Quais arquivos são gerados por regras no pacote foo?

bazel query 'kind("generated file", //foo:*)'

Quais destinos são gerados pela macro starlark foo?

bazel query 'attr(generator_function, foo, //path/to/search/...)'

Qual é o conjunto de arquivos BUILD necessários para criar //foo?

bazel query 'buildfiles(deps(//foo))' | cut -f1 -d:

Para quais testes individuais uma test_suite se expande?

bazel query 'tests(//foo:smoke_tests)'

Quais das alternativas abaixo são testes de C++?

bazel query 'kind(cc_.*, tests(//foo:smoke_tests))'

Quais destes são pequenos? Médio? Grande?

bazel query 'attr(size, small, tests(//foo:smoke_tests))'

bazel query 'attr(size, medium, tests(//foo:smoke_tests))'

bazel query 'attr(size, large, tests(//foo:smoke_tests))'

Quais são os testes abaixo de foo que correspondem a um padrão?

bazel query 'filter("pa?t", kind(".*_test rule", //foo/...))'

O padrão é um regex e é aplicado ao nome completo da regra. É semelhante a fazer

bazel query 'kind(".*_test rule", //foo/...)' | grep -E 'pa?t'

Qual pacote contém o arquivo path/to/file/bar.java?

 bazel query path/to/file/bar.java --output=package

Qual é o rótulo do build path/to/file/bar.java?

bazel query path/to/file/bar.java

Quais metas de regra contêm o arquivo path/to/file/bar.java como origem?

fullname=$(bazel query path/to/file/bar.java)
bazel query "attr('srcs', $fullname, ${fullname//:*/}:*)"

Quais dependências de pacote existem ...

De quais pacotes foo depende? (O que preciso conferir para criar foo)

bazel query 'buildfiles(deps(//foo:foo))' --output package

De quais pacotes a árvore de foo depende, exceto foo/contrib?

bazel query 'deps(foo/... except foo/contrib/...)' --output package

Quais dependências de regras existem ...

De quais regras de genproto a barra depende?

bazel query 'kind(genproto, deps(bar/...))'

Encontre a definição de alguma biblioteca JNI (C++) que depende transitivamente de uma regra binária do Java na árvore de servlet.

bazel query 'some(kind(cc_.*library, deps(kind(java_binary, //java/com/example/frontend/...))))' --output location
...Agora encontre as definições de todos os binários Java que dependem deles
bazel query 'let jbs = kind(java_binary, //java/com/example/frontend/...) in
  let cls = kind(cc_.*library, deps($jbs)) in
    $jbs intersect allpaths($jbs, $cls)'

Quais dependências de arquivo existem ...

Qual é o conjunto completo de arquivos de origem Java necessários para criar foo?

Arquivos de origem:

bazel query 'kind("source file", deps(//path/to/target/foo/...))' | grep java$

Arquivos gerados:

bazel query 'kind("generated file", deps(//path/to/target/foo/...))' | grep java$

Qual é o conjunto completo de arquivos de origem Java necessário para criar testes QUX?

Arquivos de origem:

bazel query 'kind("source file", deps(kind(".*_test rule", javatests/com/example/qux/...)))' | grep java$

Arquivos gerados:

bazel query 'kind("generated file", deps(kind(".*_test rule", javatests/com/example/qux/...)))' | grep java$

Que diferenças existem nas dependências entre X e Y ...

Quais metas a //foo depende de //foo:foolib não?

bazel query 'deps(//foo) except deps(//foo:foolib)'

De quais bibliotecas C++ os testes foo dependem do binário de produção //foo não?

bazel query 'kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo))'

Por que essa dependência existe ...

Por que bar depende de groups2?

bazel query 'somepath(bar/...,groups2/...:*)'

Com os resultados dessa consulta, você geralmente vai descobrir que um único destino se destaca como uma dependência inesperada, grave e indesejável de bar. A consulta pode então ser refinada para:

Mostre um caminho de docker/updater:updater_systest (um py_test) para alguns cc_library de que ele depende:

bazel query 'let cc = kind(cc_library, deps(docker/updater:updater_systest)) in
  somepath(docker/updater:updater_systest, $cc)'

Por que a biblioteca //photos/frontend:lib depende de duas variantes da mesma biblioteca //third_party/jpeglib e //third_party/jpeg?

Essa consulta se resume a: "mostrar o subgráfico de //photos/frontend:lib que depende das duas bibliotecas". Quando mostrado em ordem topológica, o último elemento do resultado é o culpado mais provável.

bazel query 'allpaths(//photos/frontend:lib, //third_party/jpeglib)
                intersect
               allpaths(//photos/frontend:lib, //third_party/jpeg)'
//photos/frontend:lib
//photos/frontend:lib_impl
//photos/frontend:lib_dispatcher
//photos/frontend:icons
//photos/frontend/modules/gadgets:gadget_icon
//photos/thumbnailer:thumbnail_lib
//third_party/jpeg/img:renderer

O que depende de ...

Quais regras abaixo da barra dependem de Y?

bazel query 'bar/... intersect allpaths(bar/..., Y)'

Quais destinos dependem diretamente de T no pacote de T?

bazel query 'same_pkg_direct_rdeps(T)'

Como quebro uma dependência ...

Quais caminhos de dependência preciso quebrar para fazer com que bar não dependa mais de X?

Para gerar o gráfico em um arquivo svg:

bazel query 'allpaths(bar/...,X)' --output graph | dot -Tsvg > /tmp/dep.svg

Diversos

Quantas etapas sequenciais há no build //foo-tests?

Infelizmente, a linguagem de consulta não pode atualmente fornecer o caminho mais longo de x para y, mas pode encontrar o nó (ou a) mais distante do ponto de partida ou mostrar os comprimentos do caminho mais longo de x a cada y de que depende. Use maxrank:

bazel query 'deps(//foo-tests)' --output maxrank | tail -1
85 //third_party/zlib:zutil.c

O resultado indica que existem caminhos de comprimento 85 que precisam ocorrer em ordem nesse build.