Esta página es el manual de referencia para el lenguaje de consulta de Bazel utilizado
cuando usas bazel query
para analizar dependencias de compilación También
describe los formatos de salida que admite bazel query
.
Para casos de uso prácticos, consulta la guía práctica de consultas de Bazel.
Referencia adicional de consulta
Además de query
, que se ejecuta en el gráfico de destino de la fase posterior a la carga,
Bazel incluye una consulta de gráfico de acciones y una consulta configurable.
Consulta de grafo de acción
La consulta de gráficos de acciones (aquery
) opera en el análisis posterior configurado
Gráfico de destino y expone información sobre Acciones, Artefactos y
sus relaciones. aquery
es útil cuando te interesa la
propiedades de las acciones o los artefactos generados a partir del gráfico de destino configurado.
Por ejemplo, los comandos reales se ejecutan y sus entradas, salidas y mnemotecnia.
Para obtener más detalles, consulta la referencia de BigQuery.
Consulta configurable
La consulta tradicional de Bazel se ejecuta en el grafo de destino de la fase de poscarga y
por lo tanto, no tiene un concepto de configuración ni sus conceptos relacionados. En particular,
no resuelve correctamente las sentencias selectas.
y, en su lugar, muestra todas las resoluciones posibles de selecciones. Sin embargo, el
un entorno de consulta configurable, cquery
, maneja los parámetros de configuración correctamente, pero
no proporciona todas las funcionalidades de esta consulta original.
Para obtener más detalles, consulta la referencia de cquery.
Ejemplos
¿Cómo usan las personas bazel query
? Estos son algunos ejemplos típicos:
¿Por qué el árbol //foo
depende de //bar/baz
?
Muestra una ruta:
somepath(foo/..., //bar/baz:all)
De eso dependen las bibliotecas de C++ que todas las pruebas de foo
dependen de él.
¿no es así el objetivo foo_bin
?
kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo:foo_bin))
Tokens: La sintaxis léxica
Las expresiones en el lenguaje de consulta se componen de los siguientes elementos: tokens:
Palabras clave, como
let
. Las palabras clave son palabras reservadas del y cada uno de ellos se describe a continuación. El conjunto completo de las palabras clave es:Palabras, como "
foo/...
" o ".*test rule
" o "//bar/baz:all
". Si un la secuencia de caracteres está "entre comillas" (comienza y termina con una comilla simple ' o comienza y termina con una comilla doble "), es una palabra. Si una secuencia de caracteres no está citado, se puede analizar como una palabra. Las palabras sin comillas son secuencias de caracteres extraídos de los caracteres del alfabeto A-Za-z, los números del 0 al 9, y los caracteres especiales*/@.-_:$~[]
(asterisco, barra diagonal, at, punto, guion, guion bajo, dos puntos, signo de dólar, tilde, llave izquierda, cuadrado derecho llave). Sin embargo, las palabras sin comillas no pueden comenzar con un guion-
o un asterisco*
. aunque los [target-name][(/concepts/labels#target-names) pueden empezar con esos caracteres.Las palabras sin comillas tampoco pueden incluir el signo más
+
o igual y=
, aunque esos caracteres estén permitidos en los nombres de los destinos. Cuándo escribir código que genere expresiones de consulta, los nombres de los destinos deben estar entre comillas.La citación es necesaria cuando se escriben secuencias de comandos que construyen consultas de Bazel. a partir de valores proporcionados por el usuario.
//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.
Tenga en cuenta que esta cita se suma a cualquier cita que pueda requerir tu shell, por ejemplo:
bazel query ' "//foo:bar=wiz" ' # single-quotes for shell, double-quotes for Bazel.
Cuando se citan las palabras clave, se consideran palabras comunes. Por ejemplo,
some
es un palabra clave, pero "algo" es una palabra.foo
y "foo" son palabras.Sin embargo, ten cuidado cuando uses comillas simples o dobles en los nombres de destino. Cuándo entre comillas uno o más nombres de destinos, usa solo un tipo de comillas (ya sea todas comillas dobles o simples).
A continuación, se muestran ejemplos de cómo será la cadena de consulta de 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
Elegimos esta sintaxis para que las comillas no sean necesarias en la mayoría de los casos. El (inusual) El ejemplo de
".*test rule"
necesita comillas: comienza con un punto y contiene un espacio. Citar a"cc_library"
es innecesario, pero inofensivo.Puntuación, como los paréntesis
()
, punto.
y coma,
Palabras que contenga signos de puntuación (excepto las excepciones mencionadas anteriormente) deben estar entre comillas.
Se ignoran los caracteres de espacio en blanco que se encuentren fuera de una palabra entrecomillada.
Conceptos del lenguaje de consulta de Bazel
El lenguaje de consulta de Bazel es un lenguaje de expresiones. Cada expresión se evalúa como un conjunto de objetivos parcialmente ordenado o, de manera equivalente, un gráfico (DAG) de objetivos. Esta es la única de cada tipo de dato.
El conjunto y el gráfico se refieren al mismo tipo de datos, pero enfatizan diferentes aspectos de ella, por ejemplo:
- Establecer: El orden parcial de los objetivos no es interesante.
- Gráfico: El orden parcial de los objetivos es significativo.
Ciclos en el gráfico de dependencia
Los grafos de dependencias de compilación deben ser acíclicos.
Los algoritmos utilizados por el lenguaje de consulta están destinados al uso en grafos acíclicos, pero son sólidos frente a los ciclos. Los detalles de cómo no se especifican y no se debe confiar en ellos.
Dependencias implícitas
Además de compilar dependencias que se definen de manera explícita en archivos BUILD
,
Bazel agrega dependencias implícitas adicionales a las reglas. Por ejemplo:
cada regla de Java depende implícitamente de JavaBuilder. Dependencias implícitas
se establecen con atributos que comienzan con $
no se puede anular en archivos BUILD
.
Según la configuración predeterminada, bazel query
tiene en cuenta las dependencias implícitas.
cuando se procesa el resultado de la consulta. Este comportamiento se puede cambiar con
la opción --[no]implicit_deps
. Ten en cuenta que, como la consulta no considera
de software, nunca se tienen en cuenta las posibles cadenas de herramientas.
Solidez
Las expresiones del lenguaje de consulta de Bazel operan en la compilación
gráfico de dependencia, que es el grafo definido implícitamente por todos
declaraciones de reglas en todos los archivos BUILD
. Es importante entender
que este gráfico es algo abstracto y no constituye una
es una descripción completa de cómo realizar todos los pasos de una compilación. En
Para realizar una compilación, también se requiere una configuración.
consulta los parámetros de configuración
de la Guía del usuario para obtener más información.
El resultado de evaluar una expresión en el lenguaje de consulta de Bazel es verdadera para todas las configuraciones, lo que significa que puede una aproximación conservadora y no precisa. Si usar la Herramienta de consultas para calcular el conjunto de todos los archivos de origen necesarios durante una compilación, es posible que informe más de lo necesario porque, por ejemplo, la Herramienta de consultas incluirá todos los archivos necesaria para admitir la traducción de mensajes, aunque no pretendes para usar esa función en tu compilación.
Sobre la preservación del orden de los gráficos
Las operaciones conservan cualquier orden
restricciones heredadas de sus subexpresiones. Puedes pensar en
esto como "la ley de conservación del orden parcial". Considera
ejemplo: si realizas una consulta para determinar el cierre transitivo de
dependencias de un destino en particular, el conjunto resultante se ordena
según el gráfico de dependencias. Si filtras ese conjunto de
incluir solo los destinos de tipo file
, el mismo
conservaciones de relaciones de orden parcial transitivas entre cada
de objetivos en el subconjunto resultante, aunque ninguno de
estos pares están directamente conectados
en el grafo original.
(No hay bordes de archivo de archivo en el gráfico de dependencia de compilación).
Sin embargo, aunque todos los operadores conservan el orden, algunos como las operaciones set no introduzcas ninguna restricción de orden propia. Considera esta expresión:
deps(x) union y
El orden del conjunto de resultados final garantiza la preservación
y ordenar las restricciones de sus subexpresiones,
las dependencias transitivas de x
se ordenan correctamente con
entre sí. Sin embargo, la consulta no garantiza nada
el orden de los objetivos en y
ni sobre el
de los objetivos de deps(x)
en relación con los de
y
(excepto esos objetivos en
y
que también están en deps(x)
).
Entre los operadores que introducen restricciones de ordenamiento, se incluyen los siguientes:
allpaths
, deps
, rdeps
, somepath
y los comodines del patrón de destino
package:*
, dir/...
, etcétera.
Consulta de Sky
Sky Query es un modo de consulta que opera sobre un alcance universal especificado.
Funciones especiales disponibles solo en SkyQuery
El modo Sky Query tiene las funciones de consulta adicionales allrdeps
y
rbuildfiles
Estas funciones operan en toda
alcance del universo (por eso no tienen sentido para una consulta normal).
Cómo especificar un alcance del universo
El modo de consulta de Sky se activa pasando las dos marcas siguientes:
(--universe_scope
o --infer_universe_scope
) y
--order_output=no
--universe_scope=<target_pattern1>,...,<target_patternN>
le indica a la consulta
precarga el cierre transitivo del patrón de objetivo especificado por los patrones de objetivo, que puede
ser tanto aditivas como sustractivas. Luego, todas las consultas se evalúan en este "alcance". En particular,
el allrdeps
y
Los operadores rbuildfiles
solo muestran resultados de este alcance.
--infer_universe_scope
le indica a Bazel que infiera un valor para --universe_scope
.
de la expresión de consulta. Este valor inferido es la lista de patrones objetivo únicos en la
expresión de consulta, pero tal vez esto no sea lo que deseas. Por ejemplo:
bazel query --infer_universe_scope --order_output=no "allrdeps(//my:target)"
La lista de patrones de destino únicos en esta expresión de consulta es ["//my:target"]
, así que
Bazel trata esto de la misma manera que a la invocación:
bazel query --universe_scope=//my:target --order_output=no "allrdeps(//my:target)"
Pero el resultado de esa consulta con --universe_scope
es solo //my:target
;
ninguna de las dependencias inversas de //my:target
está en el universo, por
en construcción. Por otro lado, considera lo siguiente:
bazel query --infer_universe_scope --order_output=no "tests(//a/... + b/...) intersect allrdeps(siblings(rbuildfiles(my/starlark/file.bzl)))"
Esta es una invocación de consulta significativa que intenta calcular los destinos de prueba en el
Expansión de tests
de los destinos en algunos directorios que
dependen transitivamente de los destinos cuya definición usa un determinado archivo .bzl
. Toma
--infer_universe_scope
es conveniente, en especial cuando se elige
De lo contrario, --universe_scope
requeriría que analices la expresión de consulta por tu cuenta.
Para las expresiones de consulta que usan operadores con alcance universal,
allrdeps
y
rbuildfiles
asegúrate de usar
--infer_universe_scope
solo si su comportamiento es el que deseas.
Sky Query tiene algunas ventajas y desventajas en comparación con la consulta predeterminada. El principal
desventaja es que no puede ordenar su resultado según el orden de grafo y, por lo tanto, cierta
no están permitidos los formatos de salida. Sus ventajas son que proporciona
dos operadores (allrdeps
y
rbuildfiles
) que no están disponibles en la consulta predeterminada.
Además, Sky Query hace su trabajo con la introspección de
gráfico de Skyframe, en lugar de crear un nuevo gráfico.
gráfico, que es lo que hace la implementación predeterminada. Por lo tanto, hay algunas circunstancias en las que
es más rápido y usa menos memoria.
Expresiones: Sintaxis y semántica de la gramática
Esta es la gramática del lenguaje de consulta de Bazel, expresada en notación 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 ... ')'
Las siguientes secciones describen cada una de las producciones de esta gramática en orden.
Patrones de destino
expr ::= word
Sintácticamente, un patrón de objetivo es solo una palabra. Se interpreta como un
(desordenado) de objetivos. El patrón objetivo más simple es una etiqueta,
identifica un único destino (archivo o regla). Por ejemplo, el patrón objetivo
//foo:bar
se evalúa como un conjunto que contiene un elemento, el objetivo y bar
.
.
Los patrones de destino generalizan las etiquetas para incluir comodines sobre los paquetes y
objetivos. Por ejemplo, foo/...:all
(o solo foo/...
) es un patrón de destino.
que se evalúa como un conjunto que contiene todas las reglas en cada paquete de manera recursiva.
debajo del directorio foo
; bar/baz:all
es un patrón de destino que evalúa
a un conjunto que contenga todas las reglas del paquete bar/baz
, pero no su
subpaquetes.
De manera similar, foo/...:*
es un patrón de destino que se evalúa como un conjunto que contiene
todos los destinos (reglas y archivos) en cada paquete de manera recurrente debajo de
directorio foo
; bar/baz:*
evalúa como un conjunto que contiene todos los destinos en
el paquete bar/baz
, pero no sus subpaquetes.
Debido a que el comodín :*
coincide con los archivos y las reglas, suele ser más
es más útil que :all
para las consultas. Por el contrario, el comodín :all
(implícito en
patrones de destino como foo/...
) suelen ser más útiles para las compilaciones.
Los patrones de destino bazel query
funcionan igual que los objetivos de compilación bazel build
.
Para obtener más detalles, consulta Patrones de destino.
escribe bazel help target-syntax
.
Los patrones objetivo pueden evaluarse como un conjunto singleton (en el caso de una etiqueta) o un
conjunto que contiene muchos elementos (como en el caso de foo/...
, que tiene miles
de elementos) o al conjunto vacío si el patrón del objetivo no coincide con ningún objetivo.
Todos los nodos como resultado de una expresión de patrón de destino están ordenados correctamente
en relación con los otros de acuerdo con la relación de dependencia. Entonces, el resultado de
foo:*
no es solo el conjunto de destinos en el paquete foo
, sino también
gráfico sobre esos objetivos. (No se garantiza el orden relativo
de los nodos resultantes en comparación con otros nodos). Para obtener más detalles, consulta la
orden de los gráficos.
Variables
expr ::= let name = expr1 in expr2
| $name
El lenguaje de consulta de Bazel permite definir y hacer referencia a
variables. El resultado de la evaluación de una expresión let
es el mismo que
el de expr2, con todos los casos gratuitos
de la variable name reemplazada por el valor de
expr1.
Por ejemplo, let v = foo/... in allpaths($v, //common) intersect $v
es
equivalente a allpaths(foo/...,//common) intersect foo/...
.
Un caso de una variable de referencia name
distinta de
una expresión let name = ...
que la contiene es una
. En otras palabras, las expresiones de consulta de nivel superior no pueden tener
variables.
En las producciones gramaticales anteriores, name
es como word, pero con el
restricción adicional de que sea un identificador legal en el campo C
idioma. Las referencias a la variable deben estar precedidas por "$". carácter.
Cada expresión let
define solo una variable, pero puedes anidarlas.
Tanto los patrones de destino como las referencias de variables consisten en un solo token, una palabra, lo que crea una ambigüedad sintáctica. Sin embargo, hay no hay ambigüedad semántica, ya que el subconjunto de palabras que son variables legales nombres es independiente del subconjunto de palabras que son patrones de segmentación legales.
En términos técnicos, las expresiones let
no aumentan.
la expresividad del lenguaje de consulta: cualquier consulta que se pueda expresar en
el lenguaje también se puede expresar sin ellos. Sin embargo,
mejorar la brevedad de muchas consultas y también puede llevar a que
una evaluación eficiente de consultas.
Expresiones entre paréntesis
expr ::= (expr)
Los paréntesis asocian subexpresiones para forzar un orden de evaluación. Una expresión entre paréntesis se evalúa como el valor de su argumento.
Operaciones de conjuntos algebraicos: intersección, unión, diferencia de conjunto
expr ::= expr intersect expr
| expr ^ expr
| expr union expr
| expr + expr
| expr except expr
| expr - expr
Estos tres operadores calculan las operaciones de conjunto habituales sobre sus argumentos.
Cada operador tiene dos formas, una nominal, como intersect
, y una
forma simbólica, como ^
. Ambas formas son equivalentes; las formas simbólicas son
más rápido de escribir. (Para mayor claridad, en el resto de esta página se utilizan las formas nominales).
Por ejemplo:
foo/... except foo/bar/...
Se evalúa como el conjunto de objetivos que coinciden con foo/...
, pero no con foo/bar/...
.
Puedes escribir la misma consulta de la siguiente manera:
foo/... - foo/bar/...
Las operaciones intersect
(^
) y union
(+
) son conmutativas (simétricas).
except
(-
) es asimétrico. El analizador trata a los tres operadores como
asociativo a la izquierda y de igual precedencia, por lo que quizás quieras paréntesis. Para
ejemplo, las dos primeras expresiones son equivalentes, pero la tercera no lo es:
x intersect y union z
(x intersect y) union z
x intersect (y union z)
Leer destinos de una fuente externa: conjunto
expr ::= set(word *)
El set(a b c ...)
calcula la unión de un conjunto de cero o más
patrones de destino, separados por espacios en blanco (sin comas).
Junto con la función $(...)
de la shell de Bourne, set()
proporciona una
medio para guardar los resultados de una consulta en un archivo de texto normal, manipular
ese archivo de texto con otros programas (como herramientas de shell de UNIX estándar) y, luego,
ingresando el resultado de vuelta en la Herramienta de consultas como un valor para más
el procesamiento de datos. Por ejemplo:
bazel query deps(//my:target) --output=label | grep ... | sed ... | awk ... > foo
bazel query "kind(cc_binary, set($(<foo)))"
En el siguiente ejemplo,kind(cc_library, deps(//some_dir/foo:main, 5))
es
Se calcula filtrando los valores maxrank
con un programa awk
.
bazel query 'deps(//some_dir/foo:main)' --output maxrank | awk '($1 < 5) { print $2;} ' > foo
bazel query "kind(cc_library, set($(<foo)))"
En estos ejemplos, $(<foo)
es una abreviatura de $(cat foo)
, pero shell
también se pueden usar comandos distintos de cat
, como el comando awk
anterior.
Funciones
expr ::= word '(' int | word | expr ... ')'
El lenguaje de consulta define varias funciones. El nombre de la función determina la cantidad y el tipo de argumentos que requiere. Lo siguiente funciones disponibles:
allpaths
attr
buildfiles
rbuildfiles
deps
filter
kind
labels
loadfiles
rdeps
allrdeps
same_pkg_direct_rdeps
siblings
some
somepath
tests
visible
Cierre transitivo de dependencias: dependencias
expr ::= deps(expr)
| deps(expr, depth)
El operador deps(x)
evalúa el grafo formado.
por el cierre transitivo de las dependencias del conjunto de argumentos
x Por ejemplo, el valor de deps(//foo)
es el
gráfico de dependencia con permisos de administrador en el único nodo foo
, incluidos todos sus
dependencias. El valor de deps(foo/...)
son los gráficos de dependencias cuyas raíces
hay reglas en cada paquete dentro del directorio foo
. En este contexto,
"dependencias" significa solo objetivos de regla y archivo; por lo tanto, BUILD
y
Los archivos de Starlark necesarios para crear estos destinos no se incluyen aquí. Para eso
debes usar el operador buildfiles
.
El grafo resultante se ordena de acuerdo con la relación de dependencia. Para ver más consulta la sección sobre orden de los gráficos.
El operador deps
acepta un segundo argumento opcional, que es un número entero
que especifica un límite superior en la profundidad de la búsqueda. De esta manera,
deps(foo:*, 0)
devuelve todos los objetivos en el paquete foo
, mientras que
Además, deps(foo:*, 1)
incluye los requisitos previos directos de cualquier destino en el
paquete foo
, y deps(foo:*, 2)
también incluye los nodos directamente
se puede acceder desde los nodos en deps(foo:*, 1)
, y así sucesivamente. (Estos números
corresponden a las clasificaciones que se muestran en el formato de salida minrank
).
Si se omite el parámetro depth, la búsqueda se realiza de la siguiente manera:
no delimitado: procesa el cierre transitivo reflexivo de los requisitos previos.
Cierre transitivo de dependencias inversas: rdeps
expr ::= rdeps(expr, expr)
| rdeps(expr, expr, depth)
El rdeps(u, x)
el operador evalúa las dependencias inversas del conjunto de argumentos
Conjunto de x en el cierre transitivo del universo
u
El grafo resultante se ordena de acuerdo con la relación de dependencia. Consulta la en orden de los gráficos para obtener más detalles.
El operador rdeps
acepta un tercer argumento opcional, que es un número entero
que especifica un límite superior en la profundidad de la búsqueda. El resultado
solo incluye nodos dentro de una distancia de la profundidad especificada de cualquier nodo
en el conjunto de argumentos. Por lo tanto, rdeps(//foo, //common, 1)
evalúa a todos los nodos.
en el cierre transitivo de //foo
que depende directamente de //common
. (Estos
Los números corresponden a las clasificaciones que se muestran en el resultado de minrank
.
format.) Si se omite el parámetro depth, el
la búsqueda es ilimitada.
Cierre transitivo de todas las dependencias inversas: allrdeps
expr ::= allrdeps(expr)
| allrdeps(expr, depth)
El operador allrdeps
se comporta como rdeps
con la excepción de que el “conjunto universal” es lo que sea la marca --universe_scope
en lugar de especificarse por separado. Por lo tanto, si
Se pasó --universe_scope=//foo/...
; por lo tanto, se superó allrdeps(//bar)
equivalente a rdeps(//foo/..., //bar)
.
Dependencias inversas directas en el mismo paquete: same_pkg_direct_rdeps
expr ::= same_pkg_direct_rdeps(expr)
El operador same_pkg_direct_rdeps(x)
evalúa el conjunto completo de objetivos.
que están en el mismo paquete que el destino del conjunto de argumentos y que dependen directamente de él.
Cómo tratar con el paquete de un objetivo: hermanos
expr ::= siblings(expr)
El operador siblings(x)
evalúa el conjunto completo de objetivos que se encuentran en
mismo paquete que un destino en el conjunto de argumentos.
Opción arbitraria: algunas
expr ::= some(expr)
| some(expr, count )
El operador some(x, k)
selecciona, como máximo, k objetivos de manera arbitraria de sus
de argumentos x y se evalúa como un conjunto que contiene
solo esos objetivos. El parámetro k es opcional. si
falta, el resultado será un conjunto singleton que contiene solo un objetivo
seleccionados de forma arbitraria. Si el tamaño del conjunto de argumentos x es
menor que k, todo el conjunto de argumentos
Se devolverá un valor de x.
Por ejemplo, la expresión some(//foo:main union //bar:baz)
se evalúa como un
conjunto singleton que contiene //foo:main
o //bar:baz
, aunque
uno no está definido. La expresión some(//foo:main union //bar:baz, 2)
o
some(//foo:main union //bar:baz, 3)
muestra //foo:main
y
//bar:baz
Si el argumento es un singleton, entonces some
.
calcula la función de identidad: some(//foo:main)
es
equivalente a //foo:main
.
Es un error si el conjunto de argumentos especificado está vacío, como en el
la expresión some(//foo:main intersect //bar:baz)
.
Operadores de ruta de acceso: somepath, allpaths
expr ::= somepath(expr, expr)
| allpaths(expr, expr)
Los operadores somepath(S, E)
y
Los operadores allpaths(S, E)
procesan
rutas entre dos conjuntos de objetivos. Ambas consultas aceptan dos
argumentos, un conjunto S de puntos de partida y un conjunto
E de los puntos de finalización. somepath
devuelve el
gráfico de nodos en alguna ruta arbitraria de un objetivo en
S a un destino en E; allpaths
devuelve el gráfico de nodos en todas las rutas desde cualquier destino en
S a cualquier destino en E.
Los grafos resultantes se ordenan según la relación de dependencia. Para obtener más detalles, consulta la sección sobre el orden de los gráficos.
Filtrado de tipos de objetivos: similares
expr ::= kind(word, expr)
El kind(pattern, input)
aplica un filtro a un conjunto de objetivos y descarta esos destinos
que no son del tipo esperado. El pattern
especifica qué tipo de objetivo debe coincidir.
Por ejemplo, los tipos para los cuatro destinos definidos por el archivo BUILD
(para el paquete p
) que se muestran a continuación se ilustran en la tabla:
Código | Objetivo | Tipo |
---|---|---|
genrule( name = "a", srcs = ["a.in"], outs = ["a.out"], cmd = "...", ) |
//p:a |
regla genrule |
//p:a.in |
archivo fuente | |
//p:a.out |
archivo generado | |
//p:BUILD |
archivo fuente |
Por lo tanto, kind("cc_.* rule", foo/...)
se evalúa como el conjunto.
de todos los cc_library
, cc_binary
, etcétera
la regla se orienta por debajo de foo
y kind("source file", deps(//foo))
evalúa el conjunto de todos los archivos de origen en el cierre transitivo
de las dependencias del objetivo //foo
.
A menudo, se requiere la cuota del argumento pattern
porque sin ella, el analizador no considera palabras a muchas expresiones regulares, como source
file
y .*_test
.
Cuando se establece la coincidencia para package group
, los objetivos que terminan en
Es posible que :all
no arroje ningún resultado. Utiliza :all-targets
en lugar de esta función.
Filtro de nombres de destino: filtro
expr ::= filter(word, expr)
El filter(pattern, input)
aplica un filtro a un conjunto de objetivos y descarta aquellos cuyo
las etiquetas (en forma absoluta) no coinciden con el patrón; it
evalúa a un subconjunto de su entrada.
El primer argumento, pattern, es una palabra que contiene un
expresión regular sobre los nombres de destino. Una expresión filter
evalúa el conjunto que contiene todos los destinos x de modo que
x es miembro del conjunto input y la
etiqueta (en forma absoluta, como //foo:bar
)
de x contiene una coincidencia (no anclada)
para la expresión regular pattern. Ya que todos
Los nombres de destino comienzan con //
, se pueden usar como alternativa.
al ancla de expresión regular ^
.
Este operador suele proporcionar una alternativa mucho más rápida y sólida al
Operador intersect
. Por ejemplo, para ver todos
bar
dependencias del objetivo //foo:foo
, se podría
evaluar
deps(//foo) intersect //bar/...
Sin embargo, esta sentencia requerirá el análisis de todos los archivos BUILD
en el
Árbol de bar
, que será lento y propenso a errores en
BUILD
irrelevantes. Una alternativa podría ser la siguiente:
filter(//bar, deps(//foo))
que primero calcularía el conjunto de dependencias //foo
y
filtraría solo los objetivos que coincidan con el patrón proporcionado; en otros
palabras, objetivos con nombres que contienen //bar
como substring.
Otro uso común del operador filter(pattern,
expr)
es filtrar archivos específicos por su
nombre o extensión. Por ejemplo:
filter("\.cc$", deps(//foo))
proporcionará una lista de todos los archivos .cc
usados para compilar //foo
.
Filtrado de atributos de la regla: attr
expr ::= attr(word, word, expr)
El
attr(name, pattern, input)
aplica un filtro a un conjunto de objetivos y descarta aquellos que no se
reglas, objetivos de reglas que no tienen el atributo name
o reglas definidas cuando el valor del atributo no coincide con el
expresión regular pattern; que evalúa
a un subconjunto de su entrada.
El primer argumento, name, es el nombre de la regla.
que debe coincidir con los valores proporcionados
expresión regular. El segundo argumento,
pattern es una expresión regular sobre el atributo.
de salida. Una expresión attr
se evalúa como el conjunto que contiene todos los destinos.
x de modo que x es un
miembro del conjunto input, es una regla con el
el atributo name, y el valor del atributo contiene un
(sin ancla) para la expresión regular
pattern Si name es un
el atributo opcional y la regla no los especifica explícitamente; entonces, establece la
se usará para la comparación. Por ejemplo:
attr(linkshared, 0, deps(//foo))
seleccionará todas las dependencias //foo
que pueden tener un
el atributo linkshared [por ejemplo, una regla cc_binary
] y lo tendrás
establecerlo explícitamente en 0 o no establecerlo en absoluto, pero el valor predeterminado es 0 (como para
cc_binary
reglas).
Los atributos de tipo de lista (como srcs
, data
, etc.) son los siguientes:
convertidos en cadenas con el formato [value<sub>1</sub>, ..., value<sub>n</sub>]
,
que comienza con un corchete [
y termina con un corchete ]
y usando ",
" (coma, espacio) para delimitar varios valores.
Las etiquetas se convierten en cadenas usando la forma absoluta de la
etiqueta. Por ejemplo, un atributo deps=[":foo",
"//otherpkg:bar", "wiz"]
se convertiría en el
la cadena [//thispkg:foo, //otherpkg:bar, //thispkg:wiz]
.
Los corchetes siempre están presentes, por lo que la lista vacía usaría el valor de cadena []
.
con fines de coincidencia. Por ejemplo:
attr("srcs", "\[\]", deps(//foo))
seleccionará todas las reglas de //foo
dependencias que tengan un
el atributo srcs
vacío, mientras que
attr("data", ".{3,}", deps(//foo))
seleccionará todas las reglas de //foo
dependencias que se especifiquen en
como mínimo un valor en el atributo data
(cada etiqueta tiene un valor mínimo de
Debe tener 3 caracteres debido a //
y :
).
Para seleccionar todas las reglas entre dependencias de //foo
con una value
específica en una
atributo list-type, utilice
attr("tags", "[\[ ]value[,\]]", deps(//foo))
Esto funciona porque el carácter que está antes de value
será [
o un espacio, y el
carácter después de value
será una coma o ]
.
Filtrado de visibilidad de reglas: visible
expr ::= visible(expr, expr)
El operador visible(predicate, input)
aplica un filtro a un conjunto de objetivos y descarta los que no tienen el ícono
la visibilidad requerida.
El primer argumento, predicate, es un conjunto de objetivos que todos los objetivos la salida debe ser visible. Una expresión visible evalúa el conjunto que contiene todos los destinos x, de modo que x es miembro del conjunto input y, para todos los destinos, y de y puede ver predicate x. Por ejemplo:
visible(//foo, //bar:*)
seleccionará todos los destinos en el paquete //bar
que //foo
en las que pueden confiar sin infringir las restricciones de visibilidad.
Evaluación de los atributos de la regla de tipo "label"
expr ::= labels(word, expr)
El labels(attr_name, inputs)
operador muestra el conjunto de objetivos especificados en el
atributo attr_name de tipo “label” o "lista de sellos discográficos" en
alguna regla en el conjunto inputs.
Por ejemplo, labels(srcs, //foo)
muestra el conjunto de
objetivos que aparezcan en el atributo srcs
de
la regla //foo
. Si hay varias reglas
con atributos srcs
en el conjunto inputs,
de su srcs
.
Expande y filtra test_suites: pruebas
expr ::= tests(expr)
El operador tests(x)
muestra el conjunto de todas las pruebas
del conjunto x, expandiendo las reglas test_suite
a
el conjunto de pruebas individuales al que hacen referencia y aplicar el filtrado
tag
y size
.
De forma predeterminada, la evaluación de consultas
ignora cualquier objetivo que no sea de prueba en todas las reglas test_suite
. Puede ser
Se cambió por errores con la opción --strict_test_suite
.
Por ejemplo, la consulta kind(test, foo:*)
enumera todos
las reglas *_test
y test_suite
en el paquete foo
. Todos los resultados son (por
del paquete foo
. En cambio,
la consulta tests(foo:*)
devolverá todos los
pruebas individuales que ejecutaría bazel test
foo:*
(esto puede incluir pruebas que pertenezcan a otros paquetes)
a las que se hace referencia directa o indirectamente
mediante reglas test_suite
.
Archivos de definición del paquete: buildfiles
expr ::= buildfiles(expr)
El operador buildfiles(x)
muestra el conjunto
de archivos que definen los paquetes de cada objetivo en
establecer x; En otras palabras, para cada paquete, su archivo BUILD
además de cualquier archivo .bzl al que haga referencia mediante load
. Ten en cuenta que esta
También muestra los archivos BUILD
de los paquetes que contienen estas
load
.
Este operador generalmente se usa al determinar qué archivos o
paquetes para crear un destino específico, a menudo junto con
la opción --output package
que aparece a continuación). Por ejemplo:
bazel query 'buildfiles(deps(//foo))' --output package
Muestra el conjunto de todos los paquetes de los que //foo
depende transitivamente.
Archivos de definición del paquete: rbuildfiles
expr ::= rbuildfiles(word, ...)
El operador rbuildfiles
toma una lista separada por comas de fragmentos de ruta y muestra
El conjunto de archivos BUILD
que dependen de forma transitiva de estos fragmentos de rutas de acceso. Por ejemplo, si
//foo
es un paquete, entonces rbuildfiles(foo/BUILD)
devolverá el
Objetivo de //foo:BUILD
. Si el archivo foo/BUILD
tiene
load('//bar:file.bzl'...
en él, luego rbuildfiles(bar/file.bzl)
el destino //foo:BUILD
, así como los destinos de cualquier otro archivo BUILD
que
cargar //bar:file.bzl
El alcance del operador --universe_scope
. Archivos que no corresponden directamente a archivos BUILD
y .bzl
no afectan los resultados. Por ejemplo, se ignoran los archivos de origen (como foo.cc
).
incluso si se mencionan de forma explícita en el archivo BUILD
. Sin embargo, los enlaces simbólicos se respetan, de modo que
si foo/BUILD
es un symlink a bar/BUILD
, entonces
rbuildfiles(bar/BUILD)
incluirá a //foo:BUILD
en sus resultados.
El operador rbuildfiles
es casi moralmente la inversa de
Operador buildfiles
. Sin embargo, esta inversión moral
se mantiene más fuerte en una dirección: los resultados de rbuildfiles
son como los
entradas de buildfiles
; el primero solo contendrá BUILD
objetivos de archivo en paquetes,
y este último puede contener esos objetivos. En la otra dirección, la correspondencia es más débil. El
Las salidas del operador buildfiles
son objetivos correspondientes a todos los paquetes ybzl
archivos que necesita una entrada determinada. Sin embargo, las entradas del operador rbuildfiles
son
pero no a esos objetivos, sino a fragmentos de rutas de acceso que corresponden a ellos.
Archivos de definición del paquete: loadfiles
expr ::= loadfiles(expr)
El operador loadfiles(x)
muestra el conjunto de
Archivos de Starlark necesarios para cargar los paquetes de cada destino en
establecer x. En otras palabras, para cada paquete, devuelve el
Archivos .bzl a los que se hace referencia en los archivos BUILD
Formatos de salida
bazel query
genera un gráfico.
Tú especificas el contenido, el formato y el orden en que
bazel query
presenta este gráfico
mediante la opción de línea de comandos --output
.
Cuando se ejecuta con Sky Query, solo los formatos de salida compatibles con
se permiten los resultados desordenados. Específicamente, graph
, minrank
y
No están permitidos los formatos de salida maxrank
.
Algunos de los formatos de salida aceptan opciones adicionales. Nombre de
cada opción de salida tiene el prefijo del formato de salida al que
se aplica, por lo que --graph:factored
solo se aplica
Cuando se usa --output=graph
no tiene efecto si
se usa un formato de salida distinto de graph
. De forma similar,
--xml:line_numbers
se aplica solo cuando --output=xml
está en uso.
Orden de los resultados
Aunque las expresiones de consulta siempre siguen la ley de
conservación del orden de los grafos", presentar los resultados
de forma desordenada o de dependencia. Esto no
influir en los objetivos en el conjunto de resultados o en cómo se calcula la consulta. Solo
afecta la forma en que se imprimen los resultados en stdout. Además, los nodos que son
equivalente en el orden de dependencia puede o no ordenarse alfabéticamente.
Se puede usar la marca --order_output
para controlar este comportamiento.
(La marca --[no]order_results
tiene un subconjunto de la funcionalidad
de la marca --order_output
y dejó de estar disponible).
El valor predeterminado de esta marca es auto
, que imprime resultados en lexicográficos
según el pedido. Sin embargo, cuando se use somepath(a,b)
, los resultados se imprimirán en
Pedido de deps
.
Cuando esta marca es no
y --output
es uno de
build
, label
, label_kind
, location
, package
, proto
o
xml
, los resultados se imprimirán en un orden arbitrario. Este es
suelen ser la opción más rápida. Sin embargo, no se admite cuando
--output
es uno de graph
, minrank
o
maxrank
: Con estos formatos, Bazel siempre imprime los resultados.
ordenados por el orden o clasificación de la dependencia.
Cuando esta marca es deps
, Bazel imprime los resultados en algún orden topológico, es decir,
las dependencias. Sin embargo, los nodos que no están ordenados según el orden de dependencia
(porque no hay ruta de una a otra) se pueden imprimir en cualquier orden.
Cuando esta marca es full
, Bazel imprime los nodos en un orden completamente determinista (total).
Primero, todos los nodos se ordenan alfabéticamente. Luego, cada nodo de la lista se usa como el inicio de una
una búsqueda en profundidad con prioridad posterior al pedido, en la que las aristas salientes hacia los nodos no visitados se recorren en
de los nodos sucesores. Por último, los nodos se imprimen a la inversa del orden
en los que se los visitó.
Imprimir nodos en este orden puede ser más lento, por lo que se debe usar solo cuando el determinismo es importante.
Imprime el formulario de origen de las orientaciones como aparecerían en CREAR.
--output build
Con esta opción, la representación de cada objetivo es como si estuviera
escritas a mano en el lenguaje BUILD. Todas las variables y llamadas a funciones
(como glob o macros), lo que es útil para ver el efecto
de los macros de Starlark. Además, cada regla eficaz informa
generator_name
o generator_function
),
que dan el nombre de la macro que se evaluó para producir la regla efectiva.
Aunque el resultado usa la misma sintaxis que los archivos BUILD
, no es
que producirá un archivo BUILD
válido.
Imprimir la etiqueta de cada destino
--output label
Con esta opción, el conjunto de nombres (o etiquetas) de cada objetivo
del gráfico resultante se imprime, una etiqueta por línea, en
orden topológico (a menos que se especifique --noorder_results
, consulta
notas sobre el orden de los resultados).
(un ordenamiento topológico es aquel en el que un gráfico
aparece antes que todos sus sucesores). Por supuesto,
hay muchos ordenamientos topológicos posibles de un gráfico (revertir
postorder es solo uno); no se especifica cuál se elige.
Cuando imprimes el resultado de una consulta somepath
, el orden
en el que se imprimen los nodos es el orden de la ruta.
Advertencia: En algunos casos excepcionales, puede haber dos objetivos distintos con
la misma etiqueta; Por ejemplo, una regla sh_binary
y su
el único archivo srcs
(implícito) tanto
foo.sh
Si el resultado de una consulta contiene
estos destinos, aparecerá el resultado (en formato label
)
que contenga un duplicado. Cuando uses label_kind
(consulta
a continuación), la distinción queda clara: los dos objetivos tienen
con el mismo nombre, pero uno tiene el tipo sh_binary rule
y la
otro tipo source file
.
Imprime la etiqueta y el tipo de cada objetivo
--output label_kind
Al igual que label
, este formato de salida imprime las etiquetas de
cada objetivo en el gráfico resultante, en orden topológico, pero
además, antecede a la etiqueta por el tipo del destino.
Imprimir la etiqueta de cada objetivo, en orden de clasificación
--output minrank --output maxrank
Al igual que label
, la minrank
y los formatos de salida maxrank
imprimen las etiquetas de cada
en el gráfico resultante, pero en lugar de aparecer en
topológico, aparecen en orden de clasificación, precedidos por su
el número de clasificación. Estos no se ven afectados por el orden de los resultados
Marca --[no]order_results
(consulta las notas sobre
el orden de los resultados).
Hay dos variantes de este formato: clasificaciones de minrank
cada nodo por la longitud de la ruta más corta desde un nodo raíz hasta él.
“Raíz” (los que no tienen aristas entrantes) son de rango 0,
sus sucesores son de rango 1, etc. (como siempre, las aristas apuntan desde un
el objetivo con sus requisitos previos: los destinos de los que depende).
maxrank
clasifica cada nodo por la longitud del más largo
desde un nodo raíz hasta él. Una vez más, "raíces" tienen clasificación 0, todas las demás
los nodos tienen un rango que es uno mayor que el rango máximo de todos
de sus predecesores.
Todos los nodos de un ciclo se consideran de igual rango. (La mayoría de los gráficos son
acíclico, pero los ciclos ocurren
simplemente porque los archivos BUILD
contienen ciclos erróneos).
Estos formatos de salida son útiles para descubrir qué tan profundo es un gráfico.
Si se usa para el resultado de deps(x)
, rdeps(x)
,
o allpaths
, el número de rango es igual al
longitud del más corto (con minrank
) o el más largo
(con maxrank
) ruta de acceso de x
a un nodo en
esa clasificación. Se puede usar maxrank
para determinar la
la secuencia de pasos de compilación más larga necesaria para crear un destino.
Por ejemplo, el gráfico de la izquierda muestra los resultados de la derecha.
cuando --output minrank
y --output maxrank
se especifican, respectivamente.
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 |
Imprimir la ubicación de cada destino
--output location
Al igual que label_kind
, esta opción se imprime para cada
objetivo en el resultado, el tipo y la etiqueta del destino, pero es
precedido por una cadena que describe la ubicación del objetivo, como un
nombre de archivo y número de línea. El formato se asemeja al resultado de
grep
Así, las herramientas que pueden analizar estos últimos (como Emacs
o vi) también pueden usar el resultado de la consulta para revisar una serie de
coincidencias, lo que permite usar la herramienta
de consultas de Bazel como
"grep para archivos BUILD" de dependencia-graph-aware.
La información de la ubicación varía según el tipo de objetivo (consulta el operador kind). Para las reglas, la
Se imprime la ubicación de la declaración de la regla dentro del archivo BUILD
.
Para los archivos fuente, la ubicación de la línea 1 del archivo real es
imprimirlo. Para un archivo generado, la ubicación de la regla que
lo genera se imprime. (La Herramienta de consultas no tiene suficientes
información para encontrar la ubicación real del archivo generado
en cualquier caso, es posible que no exista si aún no se realizó una compilación).
Imprime el conjunto de paquetes.
--output package
Esta opción imprime el nombre de todos los paquetes en los que pertenece algún objetivo en el conjunto de resultados. Los nombres se imprimen en orden lexicográfico; se excluyen los duplicados. De manera formal, este es una proyección del conjunto de etiquetas (paquete, objetivo) en paquetes.
Los paquetes de repositorios externos tienen el siguiente formato:
@repo//foo/bar
, mientras que los paquetes del repositorio principal no son
con el formato foo/bar
.
Junto con la consulta deps(...)
, este resultado
para encontrar el conjunto de paquetes que deben marcarse
para crear un conjunto dado de objetivos.
Cómo mostrar un gráfico del resultado
--output graph
Esta opción hace que el resultado de la consulta se imprima como una dirección
en el popular formato GraphViz de AT&T. Por lo general, el
El resultado se guarda en un archivo, como .png
o .svg
.
(Si el programa dot
no está instalado en tu estación de trabajo, puedes
puedes instalarlo con el comando sudo apt-get install graphviz
).
Consulta la sección de ejemplo a continuación para ver una invocación de muestra.
Este formato de salida es particularmente útil para allpaths
,
las consultas deps
o rdeps
, en las que el resultado
incluye un conjunto de rutas que no se pueden visualizar fácilmente cuando
se renderiza de forma lineal, como con --output label
.
De forma predeterminada, el gráfico se renderiza en formato factorizado. Es decir,
los nodos topológicamente equivalentes se fusionan en una sola
nodo con varias etiquetas. Esto hace que el gráfico sea más compacto
y legibles, porque los gráficos de resultados típicos contienen
repetitivos. Por ejemplo, una regla java_library
puede depender de cientos de archivos fuente de Java generados por el
mismo genrule
; en el gráfico factorizado, todos estos archivos
están representados por un solo nodo. Es posible que este comportamiento esté inhabilitado
con la opción --nograph:factored
.
--graph:node_limit n
Esta opción especifica la longitud máxima de la cadena de etiqueta para un
de grafo en el resultado. Las etiquetas más largas se truncarán. −1
inhabilita el truncamiento. Debido a la forma factorizada en la que los gráficos
se imprimen, las etiquetas del nodo pueden ser muy largas. GraphViz no puede
etiquetas de controlador que superan los 1,024 caracteres, que es el valor predeterminado
de esta opción. Esta opción no tiene efecto, a menos que
--output=graph
está en uso.
--[no]graph:factored
De forma predeterminada, los gráficos se muestran en formato factorizado, como se explica.
más arriba.
Cuando se especifica --nograph:factored
, los gráficos
sin factorizar. Esto hace que la visualización con GraphViz
poco práctico, pero el formato más simple puede facilitar el procesamiento de otras
herramientas de la nube (como grep). Esta opción no tiene efecto
a menos que se use --output=graph
.
XML
--output xml
Esta opción hace que los destinos resultantes se impriman en un archivo XML. formulario. El resultado comienza con un encabezado XML como este
<?xml version="1.0" encoding="UTF-8"?>
<query version="2">
y luego continúa con un elemento XML para cada destino en el gráfico de resultados, en orden topológico (a menos que resultados desordenados), y luego termina con una solicitud
</query>
Se emiten entradas simples para objetivos de tipo file
:
<source-file name='//foo:foo_main.cc' .../>
<generated-file name='//foo:libfoo.so' .../>
Pero para las reglas, el XML está estructurado y contiene definiciones de todos
los atributos de la regla, incluidos aquellos cuyo valor no se
especificado de forma explícita en el archivo BUILD
de la regla.
Además, el resultado incluye rule-input
y
elementos rule-output
para que la topología del
el gráfico de dependencia se pueden reconstruir sin tener que saber que,
Por ejemplo, los elementos del atributo srcs
se
reenviar las dependencias (requisitos previos) y los contenidos de la
outs
son dependencias inversas (consumidores).
Los elementos rule-input
para las dependencias implícitas se suprimen si
Se especifica --noimplicit_deps
.
<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 un destino contiene un name
.
atributo cuyo valor es la etiqueta del objetivo, y
un atributo location
, cuyo valor es el
ubicación impresa por --output location
.
--[no]xml:line_numbers
De forma predeterminada, las ubicaciones que se muestran en el resultado del archivo XML incluyen números de línea.
Cuando se especifica --noxml:line_numbers
, no se imprimen los números de línea.
--[no]xml:default_values
De forma predeterminada, el archivo de salida XML no incluye los atributos de regla cuyo valor
es el valor predeterminado para ese tipo de atributo (por ejemplo, si
no se especificaron en el archivo BUILD
o el valor predeterminado fue
se proporcionan explícitamente). Esta opción hace que los valores de este atributo
al formato de salida XML.
Expresiones regulares
Las expresiones regulares en el lenguaje de consulta usan la biblioteca de regex de Java, por lo que puedes usar la
la sintaxis completa para
java.util.regex.Pattern
Consulta con repositorios externos
Si la compilación depende de reglas de repositorios externos (definidas en el
WORKSPACE), los resultados de las consultas incluirán estas dependencias. Para
Por ejemplo, si //foo:bar
depende de //external:some-lib
y //external:some-lib
está vinculado a @other-repo//baz:lib
, luego
bazel query 'deps(//foo:bar)'
mostrará @other-repo//baz:lib
y
//external:some-lib
como dependencias.
Los repositorios externos en sí no son dependencias de una compilación. Es decir, en
En el ejemplo anterior, //external:other-repo
no es una dependencia. Integra
se puede consultar como miembro del paquete //external
.
por ejemplo:
# 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