Referência de consulta do Bazel

Informar um problema Mostrar fonte Por noite · 7,4 do Google. 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Esta página contém o manual de referência da Linguagem de consulta do Bazel usada. quando você usa bazel query para analisar dependências de build. Ela também descreve os formatos de saída compatíveis com o bazel query.

Para casos de uso práticos, consulte as Instruções de consulta do Bazel.

Referência de consulta adicional

Além de query, que é executado no gráfico de destino da fase de pós-carregamento, O Bazel inclui uma consulta do gráfico de ações e uma consulta configurável.

Consulta de gráfico de ação

A consulta do gráfico de ações (aquery) opera no gráfico de destino configurado pós-análise e expõe informações sobre ações, artefatos e as relações deles. aquery é útil quando você está interessado nos das ações/artefatos gerados pelo gráfico de destino configurado. Por exemplo, os comandos reais são executados e as entradas, saídas e mnemônicas deles.

Para mais detalhes, consulte a referência de aquery.

Consulta configurável

A consulta tradicional do Bazel é executada no gráfico de destino da fase pós-carregamento e portanto, não tem o conceito de configurações nem os conceitos relacionados. Ele não resolve corretamente as instruções de seleção e, em vez disso, retorna todas as resoluções possíveis de seleção. No entanto, ambiente de consulta configurável, cquery, processa as configurações corretamente, mas não fornece toda a funcionalidade da consulta original.

Para mais detalhes, consulte a referência de cquery.

Exemplos

Como as pessoas usam o bazel query? Confira alguns exemplos:

Por que a árvore //foo depende de //bar/baz? Mostrar um caminho:

somepath(foo/..., //bar/baz:all)

Quais bibliotecas C++ fazem todos os testes foo dependem disso o destino foo_bin não tem?

kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo:foo_bin))

Tokens: a sintaxe léxica

As expressões na linguagem de consulta são compostas pelos seguintes tokens:

  • Palavras-chave, como let. Palavras-chave são as palavras reservadas do e cada uma delas é descrita abaixo. O conjunto completo de palavras-chave é:

  • Palavras, como "foo/..." ou ".*test rule" ou "//bar/baz:all". Se uma sequência de caracteres estiver "entre aspas" (começa e termina com aspas simples ' ou começa e termina com aspas duplas "), ela é uma palavra. Se uma sequência de caracteres não estiver entre aspas, ela ainda poderá ser analisada como uma palavra. Palavras sem aspas são sequências de caracteres retirados dos caracteres do alfabeto A-Za-z, os numerais de 0 a 9, e os caracteres especiais */@.-_:$~[] (asterisco, barra, a, ponto, hífen, sublinhado, dois-pontos, cifrão, til, chave quadrada esquerda, quadrado à direita chave. No entanto, as palavras sem aspas não podem começar com hífen - ou asterisco * mesmo que nomes de destino relativos possam começar com esses caracteres.

    As palavras sem aspas também não podem incluir os caracteres de sinal de adição + ou de igualdade =, mesmo que esses caracteres sejam permitidos nos nomes de destino. Quando escrever o código que gera expressões de consulta, os nomes dos destinos devem estar entre aspas.

    As aspas são necessárias ao escrever scripts que constroem expressões de consulta do Bazel com base em valores fornecidos pelo usuário.

     //foo:bar+wiz    # WRONG: scanned as //foo:bar + wiz.
     //foo:bar=wiz    # WRONG: scanned as //foo:bar = wiz.
     "//foo:bar+wiz"  # OK.
     "//foo:bar=wiz"  # OK.
    

    Essa citação é adicional a qualquer citação que possa ser exigida pelo shell, como:

    bazel query ' "//foo:bar=wiz" '   # single-quotes for shell, double-quotes for Bazel.
    

    Palavras-chave e operadores, quando citados, são tratados como palavras comuns. Por exemplo, some é uma palavra-chave, mas "algumas" é uma palavra. foo e "foo" são palavras.

    No entanto, tenha cuidado ao usar aspas simples ou duplas nos nomes de destino. Quando citando um ou mais nomes de alvos, use somente um tipo de aspas (todas aspas simples ou todas as duplas).

    Confira abaixo exemplos de como será a string de consulta Java:

      'a"'a'         # WRONG: Error message: unclosed quotation.
      "a'"a"         # WRONG: Error message: unclosed quotation.
      '"a" + 'a''    # WRONG: Error message: unexpected token 'a' after query expression '"a" + '
      "'a' + "a""    # WRONG: Error message: unexpected token 'a' after query expression ''a' + '
      "a'a"          # OK.
      'a"a'          # OK.
      '"a" + "a"'    # OK
      "'a' + 'a'"    # OK
    

    Escolhemos essa sintaxe para que as aspas não sejam necessárias na maioria dos casos. O (incomum) ".*test rule" exemplo precisa de aspas: começa com um ponto e contém um espaço. Citar "cc_library" é desnecessário, mas inofensivo.

  • Pontuação, como parênteses (), ponto . e vírgula ,. Palavras que contenham pontuação (exceto as exceções listadas acima) precisam estar entre aspas.

Os caracteres de espaço em branco fora de uma palavra entre aspas são ignorados.

Conceitos da linguagem de consulta do Bazel

A linguagem de consulta do Bazel é uma linguagem de expressões. Cada expressão é avaliada como um conjunto parcialmente ordenado de destinos, ou equivalentemente, um gráfico (DAG) de destinos. Esta é a única tipo de dados.

O conjunto e o gráfico se referem ao mesmo tipo de dados, mas enfatizam aspectos diferentes dele, por exemplo:

  • Conjunto: a ordem parcial das metas não é interessante.
  • Gráfico:a ordem parcial das metas é significativa.

Ciclos no gráfico de dependência

Os gráficos de dependência do build precisam ser acíclicos.

Os algoritmos usados pela linguagem de consulta são destinados ao uso em gráficos acíclicos, mas são robustos contra ciclos. Os detalhes de como são tratados não são especificados e não devem ser considerados confiáveis.

Dependências implícitas

Além de criar dependências que são definidas explicitamente em arquivos BUILD, O Bazel adiciona outras dependências implícitas às regras. Por exemplo, cada regra Java depende implicitamente do JavaBuilder. As dependências implícitas são estabelecidas usando atributos que começam com $ e não podem ser substituídas em arquivos BUILD.

Por padrão, bazel query considera dependências implícitas em consideração. ao calcular o resultado da consulta. Esse comportamento pode ser alterado a opção --[no]implicit_deps. Como a consulta não considera possíveis, os conjuntos de ferramentas nunca serão considerados.

Integridade

As expressões da linguagem de consulta do Bazel operam na versão gráfico de dependências, que é o gráfico definido implicitamente por todos os declarações de regra em todos os arquivos BUILD. É importante entender que o gráfico é um pouco abstrato e não constitui um descrição completa de como executar todas as etapas de um build. Para realizar um build, também é necessária uma configuração. Consulte a seção configurações do guia do usuário para mais detalhes.

O resultado da avaliação de uma expressão na linguagem de consulta do Bazel for verdadeiro para todas as configurações, o que significa que ele pode ser uma superaproximação conservadora, e não é exatamente precisa. Se você usar a ferramenta de consulta para calcular o conjunto de todos os arquivos de origem necessários durante a criação, eles podem relatar mais do que o necessário porque, por exemplo, a ferramenta de consulta incluirá todos os arquivos necessário para oferecer suporte à tradução de mensagens, mesmo que você não pretenda de usar esse recurso no seu build.

Sobre a preservação da ordem do gráfico

As operações preservam qualquer ordem e restrições herdadas das subexpressões delas. Pense nisso como "a lei da conservação da ordem parcial". Considere um exemplo: se você emitir uma consulta para determinar o fechamento transitivo de dependências de um destino específico, o conjunto resultante será ordenado de acordo com o gráfico de dependência. Se você filtrar esse conjunto incluir apenas os destinos do tipo file, o mesmo relação de ordenação parcial transitiva é mantida entre cada par de destinos no subconjunto resultante, mesmo que nenhum esses pares estão diretamente conectados no gráfico original. Não há arestas de arquivo no gráfico de dependência de build.

No entanto, enquanto todos os operadores preservam a ordem, alguns operações, como as operações de conjunto não introduzem restrições de ordenação próprias. Considere esta expressão:

deps(x) union y

A ordem do conjunto de resultados finais é garantida para preservar todas as restrições de ordenação das subexpressões, ou seja, que todas as dependências transitivas de x sejam ordenadas corretamente em relação umas às outras. No entanto, a consulta não garante nada sobre a ordem dos destinos em y, nem sobre os ordem dos destinos em deps(x) em relação àqueles em y (exceto as segmentações em y que também estão em deps(x)).

Os operadores que introduzem restrições de ordenação incluem: allpaths, deps, rdeps, somepath e os caracteres curinga do padrão de destino package:*, dir/... etc.

Consulta do Sky

A consulta Sky é um modo de consulta que opera em um escopo de universo especificado.

Funções especiais disponíveis apenas no SkyQuery

O modo de consulta Sky tem as funções de consulta adicionais allrdeps e rbuildfiles. Essas funções operam em toda escopo universal (por isso, não fazem sentido em consultas normais).

Como especificar um escopo de universo

O modo de consulta do Sky é ativado transmitindo as duas flags a seguir: (--universe_scope ou --infer_universe_scope) e --order_output=no. --universe_scope=<target_pattern1>,...,<target_patternN> informa à consulta para carregar previamente o fechamento transitivo do padrão de destino especificado pelos padrões de destino, que podem ser aditivos e subtrativos. Todas as consultas são avaliadas nesse "escopo". Em particular, os operadores allrdeps e rbuildfiles só retornam resultados desse escopo. --infer_universe_scope diz ao Bazel para inferir um valor para --universe_scope. da expressão de consulta. Esse valor inferido é a lista de padrões de segmentação exclusivos no expressão de consulta, mas talvez não seja o ideal para você. Exemplo:

bazel query --infer_universe_scope --order_output=no "allrdeps(//my:target)"

A lista de padrões de destino exclusivos nessa expressão de consulta é ["//my:target"]. Portanto, O Bazel trata isso da mesma forma que a invocação:

bazel query --universe_scope=//my:target --order_output=no "allrdeps(//my:target)"

No entanto, o resultado dessa consulta com --universe_scope é apenas //my:target. Nenhuma das dependências reversas de //my:target está no universo, por construção. Por outro lado, considere o seguinte:

bazel query --infer_universe_scope --order_output=no "tests(//a/... + b/...) intersect allrdeps(siblings(rbuildfiles(my/starlark/file.bzl)))"

Essa é uma invocação de consulta significativa que está tentando calcular os destinos de teste na expansão tests dos destinos em alguns diretórios que dependem transitivamente de destinos cuja definição usa um determinado arquivo .bzl. Aqui, --infer_universe_scope é uma conveniência, especialmente no caso em que a escolha de Caso contrário, --universe_scope exigiria que você analisasse a expressão de consulta por conta própria.

Portanto, para expressões de consulta que usam operadores de escopo universal, como allrdeps e rbuildfiles, use --infer_universe_scope somente se o comportamento for o que você quer.

O Sky Query tem algumas vantagens e desvantagens em comparação com a consulta padrão. O principal A desvantagem é que ela não pode ordenar sua saída de acordo com a ordem do grafo e, assim, certas formatos de saída são proibidos. As vantagens são que ele fornece dois operadores (allrdeps e rbuildfiles) que não estão disponíveis na consulta padrão. Além disso, a Sky Query faz seu trabalho introspectivamente gráfico Skyframe, em vez de criar um novo gráfico, que é o que a implementação padrão faz. Portanto, há algumas circunstâncias em que ele é mais rápido e usa menos memória.

Expressões: sintaxe e semântica da gramática

Esta é a gramática da linguagem de consulta do Bazel, expressa na notação EBNF:

expr ::= word
       | let name = expr in expr
       | (expr)
       | expr intersect expr
       | expr ^ expr
       | expr union expr
       | expr + expr
       | expr except expr
       | expr - expr
       | set(word *)
       | word '(' int | word | expr ... ')'

As seções a seguir descrevem cada uma das produções dessa gramática em ordem.

Padrões de destino

expr ::= word

Sintaticamente, um padrão de destino é apenas uma palavra. Ela é interpretada como uma (não ordenadas) de segmentações. O padrão de destino mais simples é um rótulo, que identifica um único destino (arquivo ou regra). Por exemplo, o padrão de destino //foo:bar é avaliado como um conjunto que contém um elemento, o destino, a regra bar.

Os padrões de destino generalizam rótulos para incluir caracteres curinga sobre pacotes e de destino. Por exemplo, foo/...:all (ou apenas foo/...) é um padrão de destino. que retorna um conjunto contendo todas as rules em cada pacote de forma recursiva abaixo do diretório foo. bar/baz:all é um padrão de destino que avalia como um conjunto que contém todas as regras no pacote bar/baz, mas não seu subpacotes.

Da mesma forma, foo/...:* é um padrão de destino avaliado como um conjunto que contém todos os destinos (regras e arquivos) em cada pacote, recursivamente abaixo da foo diretório; bar/baz:* retorna um conjunto que contém todos os destinos em o pacote bar/baz, mas não os subpacotes dele.

Como o caractere curinga :* corresponde a arquivos e regras, muitas vezes é útil que :all para consultas. Por outro lado, o caractere curinga :all (implícito em padrões de destino como foo/...) costuma ser mais útil para builds.

Os padrões de destino bazel query funcionam da mesma forma que os destinos de build bazel build. Para mais detalhes, consulte Padrões de destino ou digite bazel help target-syntax.

Os padrões de destino podem ser avaliados como um conjunto único (no caso de um rótulo), um conjunto com muitos elementos (como no caso de foo/..., que tem milhares de elementos) ou um conjunto vazio, se o padrão de destino não corresponder a nenhum destino.

Todos os nós no resultado de uma expressão de padrão de destino estão ordenados corretamente estão relacionados entre si de acordo com a relação de dependência. Então, o resultado foo:* não é apenas o conjunto de destinos no pacote foo, é também o gráfico acima dessas metas. (Nenhuma garantia é feita sobre a ordem relativa dos nós de resultados em relação a outros nós. Para mais detalhes, consulte a seção ordem do gráfico.

Variáveis

expr ::= let name = expr1 in expr2
       | $name

A linguagem de consulta do Bazel permite definições e referências a variáveis. O resultado da avaliação de uma expressão let é o mesmo que a de expr2, com todas as ocorrências livres da variável name substituída pelo valor de expr1.

Por exemplo, let v = foo/... in allpaths($v, //common) intersect $v é equivalente ao allpaths(foo/...,//common) intersect foo/....

Uma ocorrência de uma referência de variável name que não esteja em uma expressão let name = ... externa é um erro. Em outras palavras, as expressões de consulta de nível superior não podem ter variáveis.

Nas produções gramaticais acima, name é semelhante a palavra, mas com a restrição adicional de ser um identificador válido na linguagem de programação C. As referências à variável precisam ter o caractere "$" no início.

Cada expressão let define apenas uma única variável, mas é possível aninhá-las.

Tanto os padrões de destino quanto as referências de variáveis consistem em um único token, uma palavra, criando uma ambiguidade sintática. No entanto, não há ambiguidade semântica, porque o subconjunto de palavras que são nomes de variáveis legais é disjunto do subconjunto de palavras que são padrões de destino válidos.

Tecnicamente falando, as expressões let não aumentam a expressividade da linguagem de consulta: qualquer consulta expressada no idioma também pode ser expressa sem elas. No entanto, elas melhoram a concisão de muitas consultas e também podem levar a uma avaliação mais eficiente.

Expressões entre parênteses

expr ::= (expr)

Os parênteses associam subexpressões para forçar uma ordem de avaliação. Uma expressão entre parênteses é avaliada como o valor do argumento.

Operações de conjuntos algébricos: interseção, união, diferença definida

expr ::= expr intersect expr
       | expr ^ expr
       | expr union expr
       | expr + expr
       | expr except expr
       | expr - expr

Esses três operadores calculam as operações de conjunto habituais sobre os argumentos. Cada operador tem duas formas, uma nominal, como intersect, e uma forma simbólica, como ^. As duas formas são equivalentes; as formas simbólicas digitar rapidamente. Para maior clareza, o restante desta página usa as formas nominais.

Por exemplo,

foo/... except foo/bar/...

avalia o conjunto de destinos que correspondem a foo/..., mas não a foo/bar/....

Você pode escrever a mesma consulta como:

foo/... - foo/bar/...

As operações intersect (^) e union (+) são comutativas (simétricas); except (-) é assimétrica. O analisador trata os três operadores como associativa à esquerda e de igual precedência, então use parênteses. Por exemplo, as duas primeiras dessas expressões são equivalentes, mas a terceira não:

x intersect y union z
(x intersect y) union z
x intersect (y union z)

Ler destinos de uma fonte externa: definir

expr ::= set(word *)

O set(a b c ...) operador calcula a união de um conjunto de zero ou mais padrões de segmentação, separados por espaços em branco (sem vírgulas).

Em conjunto com o recurso $(...) do shell Bourne, o set() fornece uma significa salvar os resultados de uma consulta em um arquivo de texto normal, manipular esse arquivo de texto usando outros programas (como ferramentas de shell padrão do UNIX) e, em seguida, introduzir o resultado de volta na ferramenta de consulta como um valor para processamento. Exemplo:

bazel query deps(//my:target) --output=label | grep ... | sed ... | awk ... > foo
bazel query "kind(cc_binary, set($(<foo)))"

No próximo exemplo, kind(cc_library, deps(//some_dir/foo:main, 5)) é calculado filtrando os valores de maxrank usando um programa awk.

bazel query 'deps(//some_dir/foo:main)' --output maxrank | awk '($1 < 5) { print $2;} ' > foo
bazel query "kind(cc_library, set($(<foo)))"

Nesses exemplos, $(<foo) é uma abreviação de $(cat foo), mas o shell comandos diferentes de cat também podem ser usados, como o comando awk anterior.

Funções

expr ::= word '(' int | word | expr ... ')'

A linguagem de consulta define várias funções. O nome da função determina o número e o tipo de argumentos necessários. O seguinte estão disponíveis:

Fechamento transitivo de dependências: dependências

expr ::= deps(expr)
       | deps(expr, depth)

O operador deps(x) é avaliado como o gráfico formado pela interseção transitiva das dependências do conjunto de argumentos x. Por exemplo, o valor de deps(//foo) é gráfico de dependência com raízes no nó único foo, incluindo todos os seus dependências. O valor de deps(foo/...) são os gráficos de dependência cujas raízes são todas as regras em todos os pacotes abaixo do diretório foo. Nesse contexto, "dependências" significa apenas regras e destinos de arquivo. Portanto, os arquivos BUILD e Starlark necessários para criar esses destinos não estão incluídos aqui. Para isso, use o operador buildfiles.

O gráfico resultante é ordenado de acordo com a relação de dependência. Para mais detalhes, consulte a seção sobre a ordem do gráfico.

O operador deps aceita um segundo argumento opcional, que é um literal inteiro que especifica um limite superior na profundidade da pesquisa. Então, deps(foo:*, 0) retorna todos os destinos no pacote foo, enquanto deps(foo:*, 1) inclui ainda mais os pré-requisitos diretos de qualquer destino no pacote foo, e deps(foo:*, 2) inclui ainda mais os nós diretamente acessíveis pelos nós em deps(foo:*, 1) e assim por diante. Esses números correspondem às classificações mostradas no formato de saída minrank. Se o parâmetro depth for omitido, a pesquisa será ilimitada: calcula o fechamento transitivo reflexivo de pré-requisitos.

Fechamento transitivo de dependências reversas: rdeps

expr ::= rdeps(expr, expr)
       | rdeps(expr, expr, depth)

O rdeps(u, x) operador avalia as dependências inversas do argumento set x no fechamento transitivo do universo u

O gráfico resultante é ordenado de acordo com a relação de dependência. Consulte a seção sobre a ordem do gráfico para mais detalhes.

O operador rdeps aceita um terceiro argumento opcional, que é um número inteiro literal que especifica um limite superior na profundidade da pesquisa. O resultado gráfico inclui apenas nós a uma distância da profundidade especificada de qualquer no argumento definido. Portanto, rdeps(//foo, //common, 1) é avaliada para todos os nós. no fechamento transitivo de //foo que dependem diretamente de //common. Esses números correspondem às classificações mostradas no formato de saída minrank. Se o parâmetro depth for omitido, a a pesquisa é ilimitada.

Fechamento transitivo de todas as dependências reversas: allrdeps

expr ::= allrdeps(expr)
       | allrdeps(expr, depth)

O operador allrdeps se comporta exatamente como o operador rdeps, exceto que o "conjunto do universo" é o que a flag --universe_scope avalia, em vez de ser especificado separadamente. Assim, se --universe_scope=//foo/... foi transmitido, depois allrdeps(//bar) é equivalente a rdeps(//foo/..., //bar).

Dependências reversas diretas no mesmo pacote: same_pkg_direct_rdeps

expr ::= same_pkg_direct_rdeps(expr)

O operador same_pkg_direct_rdeps(x) é avaliado como o conjunto completo de destinos que estão no mesmo pacote que um destino no conjunto de argumentos e que dependem diretamente dele.

Como lidar com o pacote de um destino: irmãos

expr ::= siblings(expr)

O operador siblings(x) avalia o conjunto completo de destinos que estão em mesmo pacote que um destino no argumento definido.

Escolha arbitrária: alguns

expr ::= some(expr)
       | some(expr, count )

O operador some(x, k) seleciona no máximo k alvos de forma arbitrária do conjunto de argumentos x e avalia um conjunto que contém apenas esses alvos. O parâmetro k é opcional. Se ele estiver ausente, o resultado será um conjunto único contendo apenas um destino selecionado arbitrariamente. Se o tamanho do conjunto de argumentos x for menor que k, todo o conjunto de argumentos x será retornado.

Por exemplo, a expressão some(//foo:main union //bar:baz) é avaliada como um conjunto único contendo //foo:main ou //bar:baz, mas qual não está definido. A expressão some(//foo:main union //bar:baz, 2) ou some(//foo:main union //bar:baz, 3) retorna //foo:main e //bar:baz.

Se o argumento for um singleton, some calculará a função de identidade: some(//foo:main) é equivalente a //foo:main.

Ocorrerá um erro se o conjunto de argumentos especificado estiver vazio, como na expressão some(//foo:main intersect //bar:baz).

Operadores de caminho: somepath, allpaths

expr ::= somepath(expr, expr)
       | allpaths(expr, expr)

Os métodos somepath(S, E) e Operadores allpaths(S, E) computam entre dois conjuntos de destinos. Ambas as consultas aceitam duas argumentos, um conjunto S de pontos de partida e um conjunto E de pontos finais. somepath retorna o gráfico de nós em algum caminho arbitrário de um destino na S para uma meta em E allpaths retorna o gráfico de nós em todos os caminhos de qualquer destino no S para qualquer destino em E.

Os gráficos resultantes são ordenados de acordo com a relação de dependência. Consulte a seção sobre ordem do gráfico para mais detalhes.

Somepath
somepath(S1 + S2, E), um resultado possível.
Algum caminho
somepath(S1 + S2, E), outro resultado possível.
Todos os caminhos
allpaths(S1 + S2, E)

Filtragem de tipo de destino: tipo

expr ::= kind(word, expr)

O kind(pattern, input) aplica um filtro a um conjunto de destinos e os descarta. que não são do tipo esperado. O parâmetro pattern especifica o tipo de meta a ser correspondido.

Por exemplo, os tipos dos quatro destinos definidos pelo arquivo BUILD. (para o pacote p) mostradas abaixo estão ilustradas na tabela:

Código Destino Tipo
        genrule(
            name = "a",
            srcs = ["a.in"],
            outs = ["a.out"],
            cmd = "...",
        )
      
//p:a Regra genrule
//p:a.in arquivo de origem
//p:a.out arquivo gerado
//p:BUILD arquivo de origem

Assim, kind("cc_.* rule", foo/...) avalia para o conjunto de todos os cc_library, cc_binary etc, segmentações por regra abaixo de foo e kind("source file", deps(//foo)) avalia o conjunto de todos os arquivos de origem no fechamento transitivo de dependências do destino //foo.

Muitas vezes, é necessário usar uma aspa do argumento pattern porque, sem ele, muitas expressões regulares, como source file e .*_test, não são consideradas palavras pelo analisador.

Ao fazer a correspondência para package group, as segmentações que terminam em É possível que :all não tenha resultados. Em vez disso, use :all-targets.

Filtragem de nome de destino: filtro

expr ::= filter(word, expr)

O filter(pattern, input) aplica um filtro a um conjunto de destinos e descarta destinos cujos rótulos (em forma absoluta) não correspondem ao padrão; avalia para um subconjunto da entrada.

O primeiro argumento, pattern, é uma palavra que contém expressão regular sobre nomes de destino. Uma expressão filter avalia para o conjunto que contém todos os destinos x, de modo que x é um membro do conjunto input, e o rótulo (em forma absoluta, como //foo:bar) de x contém uma correspondência (não ancorada) para a expressão regular pattern. Como todos os nomes de destino começam com //, ele pode ser usado como à âncora de expressão regular ^.

Esse operador geralmente oferece uma alternativa muito mais rápida e robusta ao operador intersect. Por exemplo, para conferir todas as dependências bar do destino //foo:foo, é possível avaliar

deps(//foo) intersect //bar/...

Essa instrução, no entanto, exigirá a análise de todos os arquivos BUILD na bar, que será lenta e propensa a erros em arquivos BUILD irrelevantes. Uma alternativa seria:

filter(//bar, deps(//foo))

que primeiro calcularia o conjunto de dependências de //foo e filtraria apenas os destinos que correspondem ao padrão fornecido. Em outras palavras, destinos com nomes que contêm //bar como uma substring.

Outro uso comum do operador filter(pattern, expr) é filtrar arquivos específicos pelo nome ou pela extensão. Por exemplo,

filter("\.cc$", deps(//foo))

fornecerá uma lista de todos os arquivos .cc usados para criar o //foo.

Filtragem de atributos de regra: attr

expr ::= attr(word, word, expr)

O operador attr(name, pattern, input) aplica um filtro a um conjunto de destinos e descarta destinos que não são regras, destinos de regras que não têm o atributo name definido ou destinos de regras em que o valor do atributo não corresponde à expressão regular pattern fornecida. Ele avalia um subconjunto da entrada.

O primeiro argumento, name, é o nome da regra que deve corresponder ao atributo padrão de expressão regular. O segundo argumento, pattern, é uma expressão regular sobre os valores do atributo. Uma expressão attr é avaliada como o conjunto que contém todos os alvos x, de modo que x seja um membro do conjunto input, seja uma regra com o atributo name definido e o valor do atributo contenha uma correspondência (não ancorada) para a expressão regular pattern. Se name for um atributo opcional e regra não o especifica explicitamente, então o padrão será usado para comparação. Por exemplo,

attr(linkshared, 0, deps(//foo))

vai selecionar todas as //foo dependências que têm permissão para atributo linkshared (como a regra cc_binary) e definir explicitamente definido como 0 ou não o defina, mas o valor padrão é 0 (como no cc_binary).

Atributos do tipo lista (como srcs, data etc.) são convertidos em strings do formulário [value<sub>1</sub>, ..., value<sub>n</sub>], começando com um colchete [, terminando com um colchete ] e usando "," (vírgula, espaço) para delimitar vários valores. Os rótulos são convertidos em strings usando a forma absoluta da rótulo. Por exemplo, um atributo deps=[":foo", "//otherpkg:bar", "wiz"] seria convertido na string [//thispkg:foo, //otherpkg:bar, //thispkg:wiz]. Os colchetes estão sempre presentes. Portanto, a lista vazia usaria o valor de string [] para fins de correspondência. Por exemplo,

attr("srcs", "\[\]", deps(//foo))

selecionará todas as regras entre as dependências de //foo que tenham um atributo srcs vazio, enquanto

attr("data", ".{3,}", deps(//foo))

vai selecionar todas as regras entre as dependências //foo que especificam pelo menos um valor no atributo data. Cada rótulo tem pelo menos três caracteres devido ao // e ao :.

Para selecionar todas as regras entre as dependências de //foo com um value específico em um atributo do tipo lista, use

attr("tags", "[\[ ]value[,\]]", deps(//foo))

Isso funciona porque o caractere antes de value será [ ou um espaço, e o caractere depois de value será uma vírgula ou ].

Filtragem da visibilidade da regra: visível

expr ::= visible(expr, expr)

O operador visible(predicate, input) aplica um filtro a um conjunto de destinos e descarta os destinos sem o visibilidade necessária.

O primeiro argumento, predicate, é um conjunto de destinos que todos na saída precisam ser visíveis. Uma expressão visible avalia para o conjunto que contém todos os destinos x, de modo que x é um membro do conjunto input e, para todos os destinos y em predicate x está visível para y. Exemplo:

visible(//foo, //bar:*)

vai selecionar todos os destinos no pacote //bar de que //foo pode depender sem violar as restrições de visibilidade.

Avaliação dos atributos de regra do tipo rótulo: rótulos

expr ::= labels(word, expr)

O operador labels(attr_name, inputs) retorna o conjunto de destinos especificados no atributo attr_name do tipo "rótulo" ou "lista de rótulos" em alguma regra no conjunto inputs.

Por exemplo, labels(srcs, //foo) retorna o conjunto de alvos que aparecem no atributo srcs da regra //foo. Se houver várias regras com os atributos srcs no conjunto inputs, o a união da srcs é retornada.

Expandir e filtrar test_suites: tests

expr ::= tests(expr)

O operador tests(x) retorna o conjunto de todas as regras de teste no conjunto x, expandindo todas as regras test_suite para o conjunto de testes individuais a que elas se referem e aplicando a filtragem por tag e size.

Por padrão, a avaliação de consultas ignora todos os destinos que não sejam de teste em todas as regras test_suite. Isso pode ser alterado para erros com a opção --strict_test_suite.

Por exemplo, a consulta kind(test, foo:*) lista todas as regras *_test e test_suite no pacote foo. Todos os resultados são (por definição) membros do pacote foo. Por outro lado, a consulta tests(foo:*) vai retornar todos os testes individuais que seriam executados por bazel test foo:*: isso pode incluir testes pertencentes a outros pacotes, que são referenciados diretamente ou indiretamente por regras test_suite.

Arquivos de definição de pacotes: buildfiles

expr ::= buildfiles(expr)

O operador buildfiles(x) retorna o conjunto de arquivos que definem os pacotes de cada destino no definir x; Em outras palavras, para cada pacote, o arquivo BUILD correspondente, além de todos os arquivos .bzl aos quais ela faz referência via load. Isso também retorna os arquivos BUILD dos pacotes que contêm esses arquivos load.

Esse operador geralmente é usado para determinar quais arquivos ou pacotes são necessários para criar um destino especificado, geralmente em conjunto com a opção --output package abaixo). Por exemplo,

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

retorna o conjunto de todos os pacotes dos quais //foo depende transitivamente.

Arquivos de definição de pacote: rbuildfiles

expr ::= rbuildfiles(word, ...)

O operador rbuildfiles recebe uma lista separada por vírgulas de fragmentos de caminho e retorna o conjunto de arquivos BUILD que dependem transitivamente desses fragmentos de caminho. Por exemplo, se //foo for um pacote, rbuildfiles(foo/BUILD) vai retornar o alvo //foo:BUILD. Se o arquivo foo/BUILD tiver load('//bar:file.bzl'... nela, então rbuildfiles(bar/file.bzl) vai retornar o destino //foo:BUILD, bem como os destinos de qualquer outro arquivo BUILD que carregar //bar:file.bzl

O escopo do operador rbuildfiles é o universo especificado pela flag --universe_scope. Os arquivos que não correspondem diretamente a arquivos BUILD e .bzl não afetam os resultados. Por exemplo, os arquivos de origem (como foo.cc) são ignorados, mesmo que elas sejam explicitamente mencionadas no arquivo BUILD. Os links simbólicos, no entanto, são respeitados, para que se foo/BUILD for um link simbólico para bar/BUILD, rbuildfiles(bar/BUILD) vai incluir //foo:BUILD nos resultados.

O operador rbuildfiles é quase o inverso do operador buildfiles. No entanto, essa inversão moral tem mais fortemente em uma direção: as saídas de rbuildfiles são exatamente entradas de buildfiles o primeiro terá apenas BUILD destinos de arquivo em pacotes, e o último pode conter esses destinos. Na outra direção, a correspondência é mais fraca. O As saídas do operador buildfiles são destinos correspondentes a todos os pacotes e .bzl necessários para uma determinada entrada. No entanto, as entradas do operador rbuildfiles não são essas metas, mas sim os fragmentos de caminho que correspondem a elas.

Arquivos de definição de pacote: loadfiles

expr ::= loadfiles(expr)

O operador loadfiles(x) retorna o conjunto de Arquivos do Starlark necessários para carregar os pacotes de cada destino no defina x. Em outras palavras, para cada pacote, ele retorna os arquivos .bzl que são referenciados pelos arquivos BUILD.

Formatos de saída

bazel query gera um gráfico. Você especifica o conteúdo, o formato e a ordem em que bazel query apresenta esse gráfico usando a opção de linha de comando --output.

Quando executado com a Sky Query, apenas formatos de saída compatíveis com saída não ordenada são permitidos. Especificamente, graph, minrank e maxrank formatos de saída são proibidos.

Alguns formatos de saída aceitam outras opções. O nome de cada opção de saída tem o prefixo do formato de saída a que se aplica. Portanto, --graph:factored só é aplicado quando --output=graph está sendo usado. Ele não tem efeito se um formato de saída diferente de graph for usado. Da mesma forma, --xml:line_numbers é aplicado apenas quando --output=xml está sendo usado.

Sobre a ordenação dos resultados

Embora as expressões de consulta sempre sigam a "lei da conservação da ordem do gráfico", apresentar os resultados pode ser feito de maneira desordenada ou desordenada. Isso não influencia os destinos no conjunto de resultados nem como a consulta é calculada. Isso só afeta a forma como os resultados são impressos no stdout. Além disso, os nós equivalentes na ordem das dependências podem ou não estar em ordem alfabética. A flag --order_output pode ser usada para controlar esse comportamento. A flag --[no]order_results tem um subconjunto da funcionalidade da flag --order_output e foi descontinuada.

O valor padrão desta sinalização é auto, que imprime resultados lexicográficos ordem. No entanto, quando somepath(a,b) é usado, os resultados são mostrados deps pedido.

Quando essa flag é no e --output é um dos build, label, label_kind, location, package, proto ou xml, as saídas serão impressas em ordem arbitrária. Isto é geralmente a opção mais rápida. No entanto, não há suporte quando --output é graph, minrank ou maxrank: com esses formatos, o Bazel sempre imprime resultados ordenados pela ordem ou classificação de dependência.

Quando essa flag é deps, o Bazel imprime os resultados em alguma ordem topológica, ou seja, as dependências primeiro. No entanto, os nós que não estão ordenados pela ordem das dependências (porque não há caminho de um para o outro) pode ser impresso em qualquer ordem.

Quando essa flag é full, o Bazel imprime nós em uma ordem totalmente determinística (total). Primeiro, todos os nós são classificados em ordem alfabética. Em seguida, cada nó na lista é usado como o início de uma pesquisa em profundidade pós-ordem em que as arestas de saída para nós não visitados são percorridas em ordem alfabética dos nós sucessores. Finalmente, os nós são impressos na ordem inversa em que foram visitados.

A impressão de nós nessa ordem pode ser mais lenta, por isso use-a somente quando o determinismo é muito importante.

Imprime a forma de origem das metas conforme elas aparecem no BUILD

--output build

Com essa opção, a representação de cada destino é como se fosse escritos à mão na linguagem BUILD. Todas as variáveis e chamadas de função (como glob, macros) são expandidas, o que é útil para ver o efeito de macros Starlark. Além disso, cada regra efetiva informa um valor de generator_name e/ou generator_function, indicando o nome da macro que foi avaliada para produzir a regra efetiva.

Embora a saída use a mesma sintaxe dos arquivos BUILD, não é garantido que ela produza um arquivo BUILD válido.

--output label

Com essa opção, o conjunto de nomes (ou rótulos) de cada alvo no gráfico resultante é impresso, um rótulo por linha, em ordem topológica (a menos que --noorder_results seja especificado. Consulte notas sobre a ordenação dos resultados). Uma ordenação topológica é aquela em que um nó de gráfico aparece antes de todos os sucessores. É claro que há muitas ordenações topológicas possíveis de um gráfico (a postordem inversa é apenas uma). A escolha não é especificada.

Ao imprimir a saída de uma consulta somepath, a ordem em que os nós são impressos é a ordem do caminho.

Advertência: em alguns casos específicos, pode haver dois alvos distintos com o mesmo rótulo; por exemplo, uma regra sh_binary e o arquivo srcs único (implícito) podem ser chamados foo.sh Se o resultado de uma consulta contiver as duas metas, a saída (no formato label) vai mostrar uma cópia. Ao usar o label_kind (consulte abaixo), a distinção fica clara: os dois objetivos têm o mesmo nome, mas uma delas tem o tipo sh_binary rule, e o outro tipo source file.

--output label_kind

Como label, esse formato de saída imprime os rótulos de cada destino no gráfico resultante, em ordem topológica, mas isso também precede o rótulo pelo tipo do destino.

--output proto

Imprime a saída da consulta como um buffer de protocolo QueryResult.

--output streamed_proto

Imprime um fluxo delimitado por comprimento de buffers de protocolo Target. Isso é útil para (i) contornar limitações de tamanho de buffers de protocolo quando há muitos destinos para caber em um QueryResult ou (ii) para iniciar o processamento enquanto o Bazel ainda está sendo gerado.

--output textproto

Semelhante a --output proto, imprime o buffer de protocolo QueryResult, mas no formato de texto.

--output streamed_jsonproto

Semelhante a --output streamed_proto, exibe um stream de Target buffers de protocolo, mas no formato ndjson.

--output minrank --output maxrank

Assim como label, os formatos de saída minrank e maxrank imprimem os rótulos de cada alvo no gráfico resultante, mas, em vez de aparecer em ordem topológica, eles aparecem em ordem de classificação, precedidos pelo número de classificação. Eles não são afetados pela ordem dos resultados Sinalização --[no]order_results (consulte as observações sobre a ordem dos resultados).

Há duas variantes desse formato: minrank classifica cada nó pelo comprimento do caminho mais curto de um nó raiz até ele. "Raiz" nós (que não têm arestas de entrada) têm classificação 0, seus sucessores são de classificação 1 etc. (Como sempre, as arestas apontam de um aos pré-requisitos: os destinos dos quais ele depende.

maxrank classifica cada nó pelo comprimento do maior caminho de um nó raiz até ela. Novamente, "roots" tem classificação 0, todos os outros nós têm uma classificação que é um maior do que a classificação máxima de todos os predecessores.

Todos os nós em um ciclo são considerados com a mesma classificação. A maioria dos gráficos é não cíclica, mas os ciclos ocorrem simplesmente porque os arquivos BUILD contêm ciclos incorretos.

Esses formatos de saída são úteis para descobrir a profundidade de um gráfico. Se usado para o resultado de uma consulta deps(x), rdeps(x) ou allpaths, o número de classificação é igual ao comprimento do caminho mais curto (com minrank) ou mais longo (com maxrank) de x para um nó nessa classificação. O maxrank pode ser usado para determinar a sequência mais longa de etapas de build necessárias para criar um destino.

Por exemplo, o gráfico à esquerda gera as saídas à direita quando --output minrank e --output maxrank são especificados, respectivamente.

Fora do ranking
      minrank

      0 //c:c
      1 //b:b
      1 //a:a
      2 //b:b.cc
      2 //a:a.cc
      
      maxrank

      0 //c:c
      1 //b:b
      2 //a:a
      2 //b:b.cc
      3 //a:a.cc
      
--output location

Como em label_kind, essa opção mostra, para cada destino no resultado, o tipo e rótulo do destino, mas não tem como prefixo uma string que descreve a localização desse alvo, como nome do arquivo e número da linha. O formato é semelhante à saída de grep. Assim, as ferramentas que podem analisar essa última (como o Emacs) ou vi) também podem usar a saída da consulta para percorrer uma série de permitindo que a ferramenta de consulta do Bazel seja usada como "grep para arquivos BUILD" com reconhecimento de gráfico de dependência.

As informações de local variam de acordo com o tipo de destino (consulte o operador kind). Para regras, o local da declaração da regra no arquivo BUILD é impresso. Para arquivos de origem, o local da linha 1 do arquivo real é impresso. Para um arquivo gerado, o local da regra que o gera é impresso. A ferramenta de consulta não tem informações informações para encontrar a localização real do arquivo gerado; e de qualquer forma, ele pode não existir se um build ainda não tiver sido executado.)

--output package

Essa opção mostra o nome de todos os pacotes aos quais alguns destinos no conjunto de resultados pertencem. Os nomes são impressos em ordem alfabética e as duplicatas são excluídas. Formalmente, essa é uma projeção do conjunto de rótulos (pacote, destino) para pacotes.

Os pacotes em repositórios externos são formatados como @repo//foo/bar enquanto os pacotes no repositório principal estão formatado como foo/bar.

Em conjunto com a consulta deps(...), essa opção de saída pode ser usada para encontrar o conjunto de pacotes que precisam ser verificados para criar um determinado conjunto de destinos.

Exibir um gráfico do resultado

--output graph

Essa opção faz com que o resultado da consulta seja impresso como um gráfico direcionado no formato GraphViz da AT&T. Normalmente, o resultado é salvo em um arquivo, como .png ou .svg. Se o programa dot não estiver instalado na sua estação de trabalho, instale-o usando o comando sudo apt-get install graphviz. Consulte a seção de exemplo abaixo para conferir um exemplo de invocação.

Esse formato de saída é particularmente útil para consultas allpaths, deps ou rdeps, em que o resultado inclui um conjunto de caminhos que não podem ser visualizados facilmente quando renderizados de forma linear, como com --output label.

Por padrão, o gráfico é renderizado em uma forma fatoração. Ou seja, nós topologicamente equivalentes são mesclados em um único nó com vários rótulos. Isso torna o gráfico mais compacto e legível, porque os gráficos de resultados típicos contêm e repetitivos. Por exemplo, uma regra java_library pode depender de centenas de arquivos de origem Java, todos gerados pelo mesmo genrule; no gráfico fatorado, todos esses arquivos são representados por um único nó. Esse comportamento pode ser desativado com a opção --nograph:factored.

--graph:node_limit n

A opção especifica o comprimento máximo da string de rótulo para um nó do gráfico na saída. Rótulos mais longos serão truncados. -1 desativa o truncamento. Devido à forma fatorada em que os gráficos são geralmente impressos, os rótulos do nó podem ser muito longos. O GraphViz não consegue identificadores com mais de 1.024 caracteres, que é o valor padrão dessa opção. Essa opção não tem efeito, a menos que --output=graph está sendo usado.

--[no]graph:factored

Por padrão, os gráficos são mostrados na forma fatorada, conforme explicado acima. Quando --nograph:factored é especificado, os gráficos são impressos sem fatoração. Isso torna a visualização usando o GraphViz impraticável, mas o formato mais simples pode facilitar o processamento por outras ferramentas (como grep). Essa opção não tem efeito a menos que --output=graph esteja sendo usado.

XML

--output xml

Essa opção faz com que os destinos resultantes sejam impressos em um XML forma A saída começa com um cabeçalho XML, como este:

  <?xml version="1.0" encoding="UTF-8"?>
  <query version="2">

e continua com um elemento XML para cada segmento no gráfico do resultado, em ordem topológica (a menos que resultados não ordenados são solicitados), e, em seguida, termina com uma

</query>

As entradas simples são emitidas para destinos do tipo file:

  <source-file name='//foo:foo_main.cc' .../>
  <generated-file name='//foo:libfoo.so' .../>

Mas, para regras, o XML é estruturado e contém definições de todos os atributos da regra, incluindo aqueles cujo valor não foi explicitamente especificado no arquivo BUILD da regra.

Além disso, o resultado inclui rule-input e elementos rule-output para que a topologia da o gráfico de dependência pode ser reconstruído sem precisar saber isso, Por exemplo, os elementos do atributo srcs são as dependências (pré-requisitos) e o conteúdo do outs são dependências de versões anteriores (consumidores).

Os elementos rule-input para dependências implícitas são suprimidos se --noimplicit_deps for especificado.

  <rule class='cc_binary rule' name='//foo:foo' ...>
    <list name='srcs'>
      <label value='//foo:foo_main.cc'/>
      <label value='//foo:bar.cc'/>
      ...
    </list>
    <list name='deps'>
      <label value='//common:common'/>
      <label value='//collections:collections'/>
      ...
    </list>
    <list name='data'>
      ...
    </list>
    <int name='linkstatic' value='0'/>
    <int name='linkshared' value='0'/>
    <list name='licenses'/>
    <list name='distribs'>
      <distribution value="INTERNAL" />
    </list>
    <rule-input name="//common:common" />
    <rule-input name="//collections:collections" />
    <rule-input name="//foo:foo_main.cc" />
    <rule-input name="//foo:bar.cc" />
    ...
  </rule>

Cada elemento XML de um destino contém um atributo name, cujo valor é o rótulo do destino, e um atributo location, cujo valor é o local do destino, conforme impresso pelo --output location.

--[no]xml:line_numbers

Por padrão, os locais mostrados na saída XML contêm números de linha. Quando --noxml:line_numbers é especificado, os números de linha não são impressos.

--[no]xml:default_values

Por padrão, a saída XML não inclui o atributo de regra cujo valor é o padrão para esse tipo de atributo (por exemplo, se ele não foi especificado no arquivo BUILD ou se o valor padrão foi fornecido explicitamente). Essa opção faz com que esses valores de atributo ser incluído na saída XML.

Expressões regulares

As expressões regulares na linguagem de consulta usam a biblioteca de regex Java, para que você possa usar a sintaxe completa de java.util.regex.Pattern.

Como consultar repositórios externos

Se o build depender de regras de repositórios externos (definidos no WORKSPACE), os resultados da consulta incluirão essas dependências. Para exemplo, se //foo:bar depender de //external:some-lib e //external:some-lib estiver vinculado a @other-repo//baz:lib, então bazel query 'deps(//foo:bar)' listará @other-repo//baz:lib e //external:some-lib como dependências.

Os repositórios externos não são dependências de um build. Ou seja, no exemplo acima, //external:other-repo não é uma dependência. Ela pode ser consultado como membro do pacote //external. Por exemplo:

  # Querying over all members of //external returns the repository.
  bazel query 'kind(http_archive, //external:*)'
  //external:other-repo

  # ...but the repository is not a dependency.
  bazel query 'kind(http_archive, deps(//foo:bar))'
  INFO: Empty results