cquery
é uma variante do query
que processa corretamente
select()
e opções de build efeitos no build
gráfico.
Para isso, ele executa os resultados da análise do Bazel
fase de transformação,
que integra esses efeitos. query
, por outro lado, executa os resultados de
Fase de carregamento do Bazel antes da avaliação das opções.
Exemplo:
$ cat > tree/BUILD <<EOF sh_library( name = "ash", deps = select({ ":excelsior": [":manna-ash"], ":americana": [":white-ash"], "//conditions:default": [":common-ash"], }), ) sh_library(name = "manna-ash") sh_library(name = "white-ash") sh_library(name = "common-ash") config_setting( name = "excelsior", values = {"define": "species=excelsior"}, ) config_setting( name = "americana", values = {"define": "species=americana"}, ) EOF
# Traditional query: query doesn't know which select() branch you will choose, # so it conservatively lists all of possible choices, including all used config_settings. $ bazel query "deps(//tree:ash)" --noimplicit_deps //tree:americana //tree:ash //tree:common-ash //tree:excelsior //tree:manna-ash //tree:white-ash # cquery: cquery lets you set build options at the command line and chooses # the exact dependencies that implies (and also the config_setting targets). $ bazel cquery "deps(//tree:ash)" --define species=excelsior --noimplicit_deps //tree:ash (9f87702) //tree:manna-ash (9f87702) //tree:americana (9f87702) //tree:excelsior (9f87702)
Cada resultado inclui um identificador exclusivo (9f87702)
de
a configuração
com o qual o destino foi criado.
Como cquery
é executado no gráfico de destino configurado. não há insight
em artefatos, como ações de versão ou acesso a test_suite
porque eles não são destinos configurados. Para o primeiro, consulte aquery
.
Sintaxe básica
Uma chamada cquery
simples tem esta aparência:
bazel cquery "function(//target)"
A expressão de consulta "function(//target)"
consiste no seguinte:
function(...)
é a função a ser executada no destino.cquery
oferece suporte à maioria das funções dequery
, além de uma alguns novos.//target
é a expressão fornecida à função. Neste exemplo, é um alvo simples. Mas a linguagem de consulta também permite o aninhamento de funções. Veja exemplos no Guia de consulta.
cquery
requer um destino para executar o carregamento e a análise.
fases. A menos que especificado de outra forma, cquery
analisa os destinos listados no
expressão de consulta. Consulte --universe_scope
.
para consultar dependências de destinos de build de nível superior.
Configurações
A linha:
//tree:ash (9f87702)
significa que //tree:ash
foi criado em uma configuração com o ID 9f87702
. Para a maioria
é um hash opaco dos valores de opção de build que definem o
configuração do Terraform.
Para conferir o conteúdo completo da configuração, execute:
$ bazel config 9f87702
9f87702
é um prefixo do ID completo. Isso ocorre porque os IDs completos são
Hashes SHA-256, que são longos e difíceis de acompanhar. cquery
entende qualquer valor
prefixo de um ID completo, semelhante a
Hashes curtos do Git (em inglês).
Para conferir os IDs completos, execute $ bazel config
.
Avaliação do padrão de destino
//foo
tem um significado diferente para cquery
e query
. Isso ocorre porque
cquery
avalia destinos configurados, e o gráfico de build pode ter vários
versões configuradas do //foo
.
Para cquery
, um padrão de destino na expressão de consulta avalia
a cada destino configurado com um rótulo que corresponda a esse padrão. A saída é
determinista, mas cquery
não garante a realização de pedidos além do
contrato principal para ordenação de consultas.
Isso produz resultados mais sutis para expressões de consulta do que com query
.
Por exemplo, o exemplo a seguir pode produzir vários resultados:
# Analyzes //foo in the target configuration, but also analyzes # //genrule_with_foo_as_tool which depends on an exec-configured # //foo. So there are two configured target instances of //foo in # the build graph. $ bazel cquery //foo --universe_scope=//foo,//genrule_with_foo_as_tool //foo (9f87702) //foo (exec)
Se você quiser declarar precisamente qual instância consultar, use
a função config
.
Consulte o padrão de destino de query
documentação para mais informações sobre padrões de destino.
Funções
Do conjunto de funções
compatível com query
, cquery
oferece suporte a todos
allrdeps
,
buildfiles
,
rbuildfiles
,
siblings
,
tests
e
visible
.
cquery
também introduz estas novas funções:
config
expr ::= config(expr, word)
O operador config
tenta encontrar o destino configurado para
o rótulo indicado pelo primeiro argumento e a configuração especificada pelo
segundo argumento.
Os valores válidos para o segundo argumento são null
ou um
hash de configuração personalizada. Os hashes podem ser recuperados de $
bazel config
ou da saída de um cquery
anterior.
Exemplos:
$ bazel cquery "config(//bar, 3732cc8)" --universe_scope=//foo
$ bazel cquery "deps(//foo)" //bar (exec) //baz (exec) $ bazel cquery "config(//baz, 3732cc8)"
Se nem todos os resultados do primeiro argumento puderem ser encontrados no arquivo do servidor, apenas aquelas que podem ser encontradas são retornadas. Se não houver resultados não for encontrada na configuração especificada, a consulta falhará.
Opções
Opções de build
cquery
é executado em uma versão regular do Bazel e, portanto, herda o conjunto de
opções disponíveis durante uma compilação.
Como usar as opções do cquery
--universe_scope
(lista separada por vírgulas)
Muitas vezes, as dependências dos destinos configurados passam transições, o que faz com que sua configuração seja diferente do seu dependente. Esta sinalização permite que você consulte um destino como se ele fosse criado como uma dependência ou um objeto transitivo dependência de outro destino. Exemplo:
# x/BUILD genrule( name = "my_gen", srcs = ["x.in"], outs = ["x.cc"], cmd = "$(locations :tool) $< >$@", tools = [":tool"], ) cc_binary( name = "tool", srcs = ["tool.cpp"], )
As regras gerais configuram as ferramentas na configuração exec Portanto, as consultas a seguir produziriam as seguintes saídas:
Consulta | Destino criado | Saída |
---|---|---|
bazel cquery "//x:tool" | //x:tool | //x:tool(targetconfig) |
bazel cquery "//x:tool" --universe_scope="//x:my_gen" | //x:my_gen | //x:tool(execconfig) |
Se essa flag for definida, o conteúdo dela será criado. Se não estiver definido, todos os destinos
mencionados na expressão de consulta são construídos. O fechamento transitivo da
os destinos criados são usados como o universo da consulta. De qualquer forma, os alvos
ser construídos devem ser construídos no nível superior (isto é, compatível com sistemas de
). cquery
retorna resultados no fechamento transitivo desses
metas de nível superior.
Mesmo que seja possível criar todos os destinos em uma expressão de consulta na parte superior
pode ser vantajoso não fazer isso. Por exemplo, definir explicitamente
--universe_scope
pode impedir a criação de destinos várias vezes em
configurações que não são importantes para você. Também pode ajudar a especificar qual versão de configuração de um
desejado que você está procurando (já que isso não é possível no momento
para especificar isso de outra maneira). Defina essa flag
se a expressão de consulta for mais complexa que deps(//foo)
.
--implicit_deps
(booleano, padrão=verdadeiro)
Definir esta sinalização como falsa filtra todos os resultados que não foram definidos explicitamente no do arquivo BUILD e, em vez disso, é definido pelo Bazel em outro lugar. Isso inclui filtros resolvidos de última geração.
--tool_deps
(booleano, padrão=verdadeiro)
Definir esse flag como "false" filtra todos os destinos configurados para os quais
caminho do destino consultado até eles cruzam uma transição entre o destino
e a configuração
configurações que não sejam de destino.
Se o destino consultado estiver na configuração de destino, a definição de --notool_deps
retorna apenas destinos que também estão na configuração de destino. Se o cliente
o destino está em uma configuração que não é de destino. Definir --notool_deps
retornará apenas
também em configurações que não são de segmentação. Essa configuração geralmente não afeta a filtragem
de conjuntos de ferramentas resolvidos.
--include_aspects
(booleano, padrão=verdadeiro)
Inclui as dependências adicionadas por aspects.
Se essa sinalização estiver desativada, cquery somepath(X, Y)
e
cquery deps(X) | grep 'Y'
omite Y se X só depender dele por um aspecto.
Formatos de saída
Por padrão, a saída do cquery resulta em uma lista ordenada por dependência de pares de rótulo e configuração. Há também outras opções para expor os resultados.
Transições
--transitions=lite --transitions=full
Transições de configuração são usados para criar destinos abaixo dos destinos de nível superior em diferentes do que os destinos de nível superior.
Por exemplo, um alvo pode impor uma transição à configuração "exec" em todos
dependências no atributo tools
. Elas são conhecidas como atributos
transições. As regras também podem impor transições nas próprias configurações,
conhecidas como transições de classe de regra. Esse formato de saída gera informações sobre
essas transições, como o tipo e o efeito que elas têm na criação
.
Esse formato de saída é acionado pela sinalização --transitions
, que, por padrão, é
Defina como NONE
. Ele pode ser definido no modo FULL
ou LITE
. FULL
de saídas do modo
informações sobre transições de classes de regras e de atributos, incluindo uma
a diferença detalhada entre as opções antes e depois da transição. Modo LITE
gera as mesmas informações sem a diferença de opções.
Saída de mensagem de protocolo
--output=proto
Essa opção faz com que os alvos resultantes sejam impressos em um protocolo binário forma de buffer. A definição do buffer de protocolo pode ser encontrada em src/main/protobuf/analysis_v2.proto.
CqueryResult
é a mensagem de nível superior que contém os resultados da cquery. Ela
tem uma lista de ConfiguredTarget
mensagens e uma lista de Configuration
mensagens. Cada ConfiguredTarget
tem uma configuration_id
com valor igual a
ao do campo id
da mensagem Configuration
correspondente.
--[no]proto:include_configurations
Por padrão, os resultados do cquery retornam informações de configuração como parte de cada destino configurado. Se você quiser omitir essas informações e receber a saída proto formatado exatamente como a saída proto da consulta, defina essa flag como falsa.
Consulte a documentação de saída .proto da consulta. para mais opções relacionadas a saídas de protótipos.
Saída de gráfico
--output=graph
Essa opção gera a saída como um arquivo .dot compatível com Graphviz. Consulte query
documentação de saída do gráfico (em inglês) para mais detalhes. cquery
também oferece suporte a --graph:node_limit
e
--graph:factored
Saída de arquivos
--output=files
Essa opção exibe uma lista dos arquivos de saída produzidos por cada destino correspondido
pela consulta semelhante à lista exibida no final de uma bazel build
invocação. A saída contém apenas os arquivos divulgados no arquivo
grupos de saída, conforme determinado
flag --output_groups
.
Ela inclui arquivos de origem.
Todos os caminhos emitidos por esse formato de saída são relativos ao
execroot, que pode ser obtido
via bazel info execution_root
. Se o link simbólico de conveniência bazel-out
existir,
os caminhos para arquivos no repositório principal também resolvem em relação ao espaço de trabalho
diretório.
Como definir o formato de saída usando o Starlark
--output=starlark
Esse formato de saída chama um Starlark
para cada destino configurado no resultado da consulta e exibe o valor
retornados pela chamada. A sinalização --starlark:file
especifica o local de um
Arquivo Starlark que define uma função chamada format
com um único parâmetro.
target
Essa função é chamada para cada objeto Target
no resultado da consulta. Como alternativa, por conveniência, você pode especificar apenas os
corpo de uma função declarada como def format(target): return expr
usando o
sinalização --starlark:expr
.
"cquery" Dialeto Starlark
O ambiente cquery Starlark é diferente de um arquivo BUILD ou .bzl. Inclui
Starlark completo
constantes e funções integradas,
além de outras específicas de cquery descritas abaixo, mas não (por exemplo) glob
,
native
ou rule
, e não oferece suporte a instruções de carregamento.
build_options(target)
build_options(target)
retorna um mapa com chaves que são identificadores de opção de build. Consulte
Configurações)
e cujos valores são os valores de Starlark. Opções de criação com valores que não são legais do Starlark
valores são omitidos deste mapa.
Se o destino for um arquivo de entrada, build_options(target)
retornará None, porque o arquivo de entrada
têm configuração nula.
provedores(destino)
providers(target)
retorna um mapa com chaves que são nomes de
provedores
(por exemplo, "DefaultInfo"
) e cujos valores são os valores de Starlark. Provedores
cujos valores não são valores de Starlark legais são omitidos deste mapa.
Exemplos
Mostre uma lista separada por espaços dos nomes de base de todos os arquivos produzidos por //foo
:
bazel cquery //foo --output=starlark \ --starlark:expr="' '.join([f.basename for f in target.files.to_list()])"
Mostre uma lista separada por espaços dos caminhos de todos os arquivos produzidos por destinos rule em
//bar
e os respectivos subpacotes:
bazel cquery 'kind(rule, //bar/...)' --output=starlark \ --starlark:expr="' '.join([f.path for f in target.files.to_list()])"
Mostra uma lista das mnemônicas de todas as ações registradas pelo //foo
.
bazel cquery //foo --output=starlark \ --starlark:expr="[a.mnemonic for a in target.actions]"
Mostre uma lista de saídas de compilação registradas por um //baz
cc_library
.
bazel cquery //baz --output=starlark \ --starlark:expr="[f.path for f in target.output_groups.compilation_outputs.to_list()]"
Mostre o valor da opção de linha de comando --javacopt
ao criar //foo
.
bazel cquery //foo --output=starlark \ --starlark:expr="build_options(target)['//command_line_option:javacopt']"
Imprima o rótulo de cada destino com exatamente uma saída. Este exemplo usa Funções do Starlark definidas em um arquivo.
$ cat example.cquery def has_one_output(target): return len(target.files.to_list()) == 1 def format(target): if has_one_output(target): return target.label else: return "" $ bazel cquery //baz --output=starlark --starlark:file=example.cquery
Mostre o rótulo de cada destino que é estritamente Python 3. Este exemplo usa Funções do Starlark definidas em um arquivo.
$ cat example.cquery def format(target): p = providers(target) py_info = p.get("PyInfo") if py_info and py_info.has_py3_only_sources: return target.label else: return "" $ bazel cquery //baz --output=starlark --starlark:file=example.cquery
Extraia um valor de um provedor definido pelo usuário.
$ cat some_package/my_rule.bzl MyRuleInfo = provider(fields={"color": "the name of a color"}) def _my_rule_impl(ctx): ... return [MyRuleInfo(color="red")] my_rule = rule( implementation = _my_rule_impl, attrs = {...}, ) $ cat example.cquery def format(target): p = providers(target) my_rule_info = p.get("//some_package:my_rule.bzl%MyRuleInfo'") if my_rule_info: return my_rule_info.color return "" $ bazel cquery //baz --output=starlark --starlark:file=example.cquery
cquery x query
cquery
e query
se complementam e se destacam em
a diferentes nichos. Considere o seguinte e decida qual é a melhor para você:
cquery
segue ramificações específicas doselect()
para e modelar o gráfico exato que você criar.query
não sabe qual ramificação escolhida pelo build, então aproximadamente inclui todas as ramificações.- A precisão de
cquery
exige a criação de mais gráficos do que Oquery
sim. Especificamente,cquery
avalia alvos configurados enquanto somentequery
avalia destinos. Isso leva mais tempo e usa mais memória. - Interpretação de
cquery
para a linguagem de consulta apresenta ambiguidade quequery
evita. Por exemplo: se"//foo"
existir em duas configurações, qual delascquery "deps(//foo)"
deve usar? A funçãoconfig
pode ajudar com isso. - Como uma ferramenta mais recente, o
cquery
não oferece suporte para determinados usos casos de uso diferentes. Consulte Problemas conhecidos para mais detalhes.
Problemas conhecidos
Todos os destinos que cquery
"cria" precisam ter a mesma configuração.
Antes de avaliar as consultas, cquery
aciona um build de apenas
antes do ponto em que as ações de build seriam executadas. O alvo
“construções” são selecionados por padrão entre todos os rótulos que aparecem na consulta
expressão (que pode ser substituído
com --universe_scope
). Esses
precisam ter a mesma configuração.
Embora geralmente compartilhem o "alvo" de nível superior configuração,
regras podem alterar a própria configuração
transições de borda de entrada.
É aqui que o cquery
fica aquém.
Alternativa: se possível, defina --universe_scope
como uma opção mais rigorosa.
do projeto. Exemplo:
# This command attempts to build the transitive closures of both //foo and # //bar. //bar uses an incoming edge transition to change its --cpu flag. $ bazel cquery 'somepath(//foo, //bar)' ERROR: Error doing post analysis query: Top-level targets //foo and //bar have different configurations (top-level targets with different configurations is not supported) # This command only builds the transitive closure of //foo, under which # //bar should exist in the correct configuration. $ bazel cquery 'somepath(//foo, //bar)' --universe_scope=//foo
Não há suporte para o --output=xml
.
Saída não determinista.
O cquery
não exclui permanentemente os dados do gráfico de build automaticamente
comandos anteriores e, portanto, está propenso a coletar resultados de
consultas. Por exemplo, genquery
realiza uma transição "exec" em
o atributo tools
, ou seja, configura as ferramentas na
configuração exec.
Você pode ver os efeitos duradouros dessa transição abaixo.
$ cat > foo/BUILD <<<EOF genrule( name = "my_gen", srcs = ["x.in"], outs = ["x.cc"], cmd = "$(locations :tool) $< >$@", tools = [":tool"], ) cc_library( name = "tool", ) EOF $ bazel cquery "//foo:tool" tool(target_config) $ bazel cquery "deps(//foo:my_gen)" my_gen (target_config) tool (exec_config) ... $ bazel cquery "//foo:tool" tool(exec_config)
Alternativa: altere qualquer opção de inicialização para forçar uma nova análise dos destinos configurados.
Por exemplo, adicione --test_arg=<whatever>
ao comando de build.
Solução de problemas
Padrões de destino recursivos (/...
)
Se você encontrar:
$ bazel cquery --universe_scope=//foo:app "somepath(//foo:app, //foo/...)" ERROR: Error doing post analysis query: Evaluation failed: Unable to load package '[foo]' because package is not in scope. Check that all target patterns in query expression are within the --universe_scope of this query.
isso sugere incorretamente que o pacote //foo
não está no escopo, mesmo que
--universe_scope=//foo:app
a inclui. Isso se deve a limitações de design
cquery
: Como solução alternativa, inclua //foo/...
explicitamente no universo
escopo:
$ bazel cquery --universe_scope=//foo:app,//foo/... "somepath(//foo:app, //foo/...)"
Se isso não funcionar, por exemplo, porque alguns destinos em //foo/...
não podem
com as flags de build escolhidas), desencapsular o padrão manualmente na
pacotes constituintes com uma consulta de pré-processamento:
# Replace "//foo/..." with a subshell query call (not cquery!) outputting each package, piped into # a sed call converting "<pkg>" to "//<pkg>:*", piped into a "+"-delimited line merge. # Output looks like "//foo:*+//foo/bar:*+//foo/baz". # $ bazel cquery --universe_scope=//foo:app "somepath(//foo:app, $(bazel query //foo/... --output=package | sed -e 's/^/\/\//' -e 's/$/:*/' | paste -sd "+" -))"