cquery
es una variante de query
que se procesa correctamente
"select()
y opciones de compilación" efectos en la compilación
gráfico.
Para lograrlo, ejecuta los resultados del análisis de Bazel
fase avanzada,
que integra estos efectos. query
, por el contrario, se ejecuta sobre los resultados de
Fase de carga de Bazel, antes de que se evalúen las opciones
Por ejemplo:
$ cat > tree/BUILD <<EOF sh_library( name = "ash", deps = select({ ":excelsior": [":manna-ash"], ":americana": [":white-ash"], "//conditions:default": [":common-ash"], }), ) sh_library(name = "manna-ash") sh_library(name = "white-ash") sh_library(name = "common-ash") config_setting( name = "excelsior", values = {"define": "species=excelsior"}, ) config_setting( name = "americana", values = {"define": "species=americana"}, ) EOF
# Traditional query: query doesn't know which select() branch you will choose, # so it conservatively lists all of possible choices, including all used config_settings. $ bazel query "deps(//tree:ash)" --noimplicit_deps //tree:americana //tree:ash //tree:common-ash //tree:excelsior //tree:manna-ash //tree:white-ash # cquery: cquery lets you set build options at the command line and chooses # the exact dependencies that implies (and also the config_setting targets). $ bazel cquery "deps(//tree:ash)" --define species=excelsior --noimplicit_deps //tree:ash (9f87702) //tree:manna-ash (9f87702) //tree:americana (9f87702) //tree:excelsior (9f87702)
Cada resultado incluye un identificador único (9f87702)
de
la configuración
con los que se crea el destino.
Dado que cquery
se ejecuta en el gráfico de destino configurado. no tiene estadísticas
en artefactos como acciones de compilación o acceso a [test_suite](/versions/6.0.0/reference/be/general#test_suite)
ya que no son objetivos configurados. Para obtener información sobre lo primero, consulta [aquery](/versions/6.0.0/query/aquery)
.
Sintaxis básica
Una llamada a cquery
simple se ve de la siguiente manera:
bazel cquery "function(//target)"
La expresión de consulta "function(//target)"
consta de lo siguiente:
function(...)
es la función que se ejecutará en el destino.cquery
admite la mayoría de las funciones dequery
, más un algunas nuevas.//target
es la expresión que se ingresa a la función. En este ejemplo, expresión es un objetivo simple. Pero el lenguaje de consulta también permite anidar funciones. Revisa el Instructivo de consulta para ver ejemplos.
cquery
requiere un destino para ejecutar la carga y el análisis.
fases. A menos que se especifique lo contrario, cquery
analiza los destinos enumerados en
expresión de consulta. Consulta --universe_scope
para consultar dependencias de objetivos de compilación de nivel superior.
Configuraciones
La línea:
//tree:ash (9f87702)
significa que //tree:ash
se compiló en una configuración con el ID 9f87702
. Para la mayoría
objetivo, se trata de un hash opaco de los valores de las opciones de compilación que definen la
configuración.
Para ver el contenido completo de la configuración, ejecuta el siguiente comando:
$ bazel config 9f87702
La configuración del host usa el ID especial (HOST)
. Archivos de origen no generados, como
los que se encuentran comúnmente en srcs
, usa el ID especial (null)
(porque
no es necesario configurar).
9f87702
es un prefijo del ID completo. Esto se debe a que los IDs completos
Hashes SHA-256 que son largos y difíciles de seguir. cquery
comprende todas las
prefijo de un ID completo, similar a
Hashes cortos de Git.
Para ver los IDs completos, ejecuta $ bazel config
.
Evaluación del patrón de destino
//foo
tiene un significado diferente para cquery
que para query
. Esto se debe a que
cquery
evalúa los destinos configurados, y el gráfico de compilación puede tener varios
versiones configuradas de //foo
.
Para cquery
, un patrón de destino en la expresión de consulta evalúa
a cada destino configurado
con una etiqueta que coincida con ese patrón. El resultado es
determinístico, pero cquery
no ofrece ninguna garantía de orden más allá de
contrato de ordenamiento de consultas principales.
Esto produce resultados más sutiles para las expresiones de consulta que con query
.
Por ejemplo, lo siguiente puede producir varios resultados:
# Analyzes //foo in the target configuration, but also analyzes # //genrule_with_foo_as_tool which depends on a host-configured # //foo. So there are two configured target instances of //foo in # the build graph. $ bazel cquery //foo --universe_scope=//foo,//genrule_with_foo_as_tool //foo (9f87702) //foo (HOST)
Si quieres declarar con precisión sobre qué instancia consultar, usa
La función config
Consulta el patrón de destino de query
documentación para obtener más información sobre patrones de objetivos.
Funciones
Del conjunto de funciones
compatible con query
, cquery
admite todo excepto
allrdeps
,
buildfiles
,
rbuildfiles
,
siblings
:
tests
y
visible
.
cquery
también incluye las siguientes funciones nuevas:
config
expr ::= config(expr, word)
El operador config
intenta encontrar el destino configurado para
la etiqueta indicada por el primer argumento y la configuración especificados por el
segundo argumento.
Los valores válidos para el segundo argumento son target
, host
, null
o una
hash de configuración personalizado. Los hash se pueden recuperar desde $
bazel config
o desde el resultado de cquery
anterior.
Ejemplos:
$ bazel cquery "config(//bar, host)" --universe_scope=//foo
$ bazel cquery "deps(//foo)" //bar (HOST) //baz (3732cc8) $ bazel cquery "config(//baz, 3732cc8)"
Si no se pueden encontrar todos los resultados del primer argumento en el campo de la aplicación, solo se devuelven aquellos que se pueden encontrar. Si no hay resultados en la configuración especificada, la consulta falla.
Opciones
Opciones de compilación
cquery
se ejecuta en una compilación normal de Bazel y, por lo tanto, hereda el conjunto de
options disponibles durante la compilación.
Usa opciones de cquery
--universe_scope
(lista separada por comas)
A menudo, las dependencias de los destinos configurados pasan transiciones, lo que hace que su configuración difiera de su dependiente. Esta marca te permite consultar un destino como si se hubiera construido como una dependencia o una la dependencia de otro objetivo. Por ejemplo:
# x/BUILD genrule( name = "my_gen", srcs = ["x.in"], outs = ["x.cc"], cmd = "$(locations :tool) $< >$@", tools = [":tool"], ) cc_library( name = "tool", )
Las genrules configuran sus herramientas en el configuración del host por lo que las siguientes consultas producirán los siguientes resultados:
Consulta | Objetivo compilado | Salida |
---|---|---|
cquery de bazel “//x:tool” | //x:tool | //x:tool(targetconfig) |
cquery de bazel “//x:tool” --universe_scope="//x:my_gen" | //x:my_gen | //x:tool(hostconfig) |
Si se establece esta marca, se compila su contenido. Si no se establece, todos los objetivos
que se mencionan en la expresión de consulta en su lugar. El cierre transitivo del
los destinos creados se usan como el universo de la búsqueda. De cualquier manera, los objetivos
deben poder compilarse en el nivel superior (es decir, compatibles con
opciones). cquery
muestra resultados en el cierre transitivo de estos
objetivos de nivel superior.
Incluso si es posible compilar todos los destinos en una expresión de consulta en la parte superior
puede ser beneficioso no hacerlo. Por ejemplo, configurar explícitamente
--universe_scope
podría impedir crear objetivos varias veces en
configuraciones que no te interesan. También podría ayudar a especificar qué versión de configuración de un
objetivo que está buscando (ya que actualmente no es posible
para especificarlo de forma completa de otra manera). Debes establecer esta marca
si la expresión de tu consulta es más compleja que deps(//foo)
.
--implicit_deps
(booleano, predeterminado=Verdadero)
Si estableces esta marca como falsa, se filtrarán todos los resultados que no se establezcan explícitamente en el archivo Build y, en su lugar, lo establece en otro lugar de Bazel. Esto incluye el filtrado resuelto cadenas de herramientas.
--tool_deps
(booleano, predeterminado=Verdadero)
Si estableces esta marca como falsa, se filtrarán todos los destinos configurados para los que
la ruta desde el objetivo consultado hasta el objetivo cruza una transición entre el objetivo
de Terraform y la
parámetros de configuración que no son de destino.
Si el destino consultado se encuentra en la configuración de destino, establecer --notool_deps
Solo mostrar destinos que también están en la configuración de destino. Si el estado
el destino está en una configuración ajena al objetivo, por lo que el valor de --notool_deps
solo se mostrará
objetivos también en configuraciones que no son objetivos. Por lo general, este parámetro de configuración no afecta el filtrado
de cadenas de herramientas resueltas.
--include_aspects
(booleano, predeterminado=Verdadero)
Los aspectos pueden agregar
dependencias adicionales a una compilación. De forma predeterminada, cquery
no sigue aspectos porque
hacen que el grafo consultable sea más grande, que usa más memoria. Pero seguirlos produce más
resultados precisos.
Si no te preocupa el impacto que tienen las consultas grandes en la memoria, habilita esta marca de forma predeterminada en tu Bazelrc.
Si realizas una consulta con aspectos inhabilitados, puedes tener un problema donde el destino X falla mientras
Si se compila el destino Y, cquery somepath(Y, X)
y cquery deps(Y) | grep 'X'
no muestran resultados porque la dependencia se produce a través de un aspecto.
Formatos de salida
De forma predeterminada, cquery genera una lista ordenada por dependencias de pares de etiquetas y configuración. También hay otras opciones para exponer los resultados.
Transiciones
--transitions=lite --transitions=full
Transiciones de configuración se usan para crear objetivos debajo de los objetivos de nivel superior en diferentes que los objetivos de nivel superior.
Por ejemplo, un destino podría imponer una transición a la configuración del host en todos
dependencias en su atributo tools
. Estos se conocen como atributos
las transiciones. Las reglas también pueden imponer transiciones en sus propios parámetros
conocidos como transiciones de clase de reglas. Este formato de salida da como resultado información sobre
estas transiciones, como su tipo y el efecto que tienen en la
opciones de estado.
Este formato de salida se activa con la marca --transitions
que, de forma predeterminada, es
Se establece en NONE
. Se puede establecer en el modo FULL
o LITE
. Salidas del modo FULL
información sobre transiciones de clase de regla y transiciones de atributos, incluida una
la diferencia detallada de las opciones antes y después de la transición. LITE
modo
genera la misma información sin las diferencias de opciones.
Resultado del mensaje de protocolo
--output=proto
Esta opción hace que los destinos resultantes se impriman en un protocolo binario. formulario de reserva. La definición del búfer de protocolo se encuentra src/main/protobuf/analysis.proto.
CqueryResult
es el mensaje de nivel superior que contiene los resultados de la consulta. Integra
tiene una lista de ConfiguredTarget
mensajes y una lista de Configuration
mensajes nuevos. Cada ConfiguredTarget
tiene una configuration_id
cuyo valor es igual.
al del campo id
del mensaje Configuration
correspondiente.
--[no]proto:include_configurations
De forma predeterminada, los resultados de cquery muestran información de configuración como parte de cada objetivo configurado. Si quieres omitir esta información y obtener el resultado del protocolo que tenga el mismo formato que el resultado de proto de la consulta, establece esta marca como false.
Consulta la documentación de resultados de proto de la consulta para obtener más opciones relacionadas con los resultados de proto.
Resultado del gráfico
--output=graph
Esta opción genera un resultado como un archivo .dot compatible con Graphviz. Ver query
documentación de resultados de grafos para obtener más detalles. cquery
También admite --graph:node_limit
y
--graph:factored
Salida de archivos
--output=files
Esta opción imprime una lista de los archivos de salida producidos por cada destino coincidente.
por la consulta, similar a la lista impresa al final de una bazel build
invocación. El resultado contiene solo los archivos anunciados en la
de salida según lo determinado por la
--output_groups
.
Sí incluye archivos fuente.
Define el formato de salida con Starlark
--output=starlark
Este formato de salida llama a Starlark.
para cada destino configurado en el resultado de la consulta y, luego, imprime el valor
que devuelve la llamada. La marca --starlark:file
especifica la ubicación de una
Archivo de Starlark que define una función llamada format
con un solo parámetro.
target
Se llama a esta función para cada Target
en el resultado de la consulta. De forma alternativa, para mayor comodidad, puedes especificar solo el
de una función declarada como def format(target): return expr
con el
--starlark:expr
.
“cquery” Dialecto de Starlark
El entorno de cquery Starlark difiere de un archivo COMPILAR o .bzl. Incluye
todo el centro de Starlark
constantes y funciones integradas,
además de algunas específicas de cquery que se describen a continuación, pero no glob
(por ejemplo),
native
o rule
, y no admite sentencias de carga.
build_options(target)
build_options(target)
muestra un mapa cuyas claves son identificadores de opciones de compilación (consulta la sección
Configuraciones)
y cuyos valores son sus valores de Starlark. Opciones de compilación cuyos valores no sean legales para Starlark
se omiten de este mapa.
Si el destino es un archivo de entrada, build_options(target)
muestra Ninguno como archivo de entrada.
o destinos tienen una configuración nula.
proveedores(objetivo)
providers(target)
devuelve un mapa cuyas claves son nombres de
proveedores
(por ejemplo, "DefaultInfo"
) y cuyos valores son sus valores de Starlark. Proveedores
cuyos valores no sean valores legales de Starlark se omiten de este mapa.
Ejemplos
Muestra una lista separada por espacios de los nombres base de todos los archivos que produce //foo
:
bazel cquery //foo --output=starlark \ --starlark:expr="' '.join([f.basename for f in target.files.to_list()])"
Imprime una lista separada por espacios de las rutas de todos los archivos que producen los objetivos rule en
//bar
y sus subpaquetes:
bazel cquery 'kind(rule, //bar/...)' --output=starlark \ --starlark:expr="' '.join([f.path for f in target.files.to_list()])"
Imprime una lista de los mnemónicos de todas las acciones registradas por //foo
.
bazel cquery //foo --output=starlark \ --starlark:expr="[a.mnemonic for a in target.actions]"
Imprime una lista de resultados de compilación registrados por un //baz
cc_library
.
bazel cquery //baz --output=starlark \ --starlark:expr="[f.path for f in target.output_groups.compilation_outputs.to_list()]"
Muestra el valor de la opción de línea de comandos --javacopt
cuando compilas //foo
.
bazel cquery //foo --output=starlark \ --starlark:expr="build_options(target)['//command_line_option:javacopt']"
Imprime la etiqueta de cada objetivo con exactamente un resultado. En este ejemplo, se usa Funciones de Starlark definidas en un archivo.
$ cat example.cquery def has_one_output(target): return len(target.files.to_list()) == 1 def format(target): if has_one_output(target): return target.label else: return "" $ bazel cquery //baz --output=starlark --starlark:file=example.cquery
Imprime la etiqueta de cada destino, que es estrictamente Python 3. En este ejemplo, se usa Funciones de Starlark definidas en un archivo.
$ cat example.cquery def format(target): p = providers(target) py_info = p.get("PyInfo") if py_info and py_info.has_py3_only_sources: return target.label else: return "" $ bazel cquery //baz --output=starlark --starlark:file=example.cquery
Extrae un valor de un proveedor definido por el usuario.
$ cat some_package/my_rule.bzl MyRuleInfo = provider(fields={"color": "the name of a color"}) def _my_rule_impl(ctx): ... return [MyRuleInfo(color="red")] my_rule = rule( implementation = _my_rule_impl, attrs = {...}, ) $ cat example.cquery def format(target): p = providers(target) my_rule_info = p.get("//some_package:my_rule.bzl%MyRuleInfo'") if my_rule_info: return my_rule_info.color return "" $ bazel cquery //baz --output=starlark --starlark:file=example.cquery
cquery y query
cquery
y query
se complementan y se destacan en
nichos diferentes. Ten en cuenta la siguiente información para decidir cuál es la más adecuada para ti:
cquery
sigue ramasselect()
específicas para modelar el grafo exacto que crees.query
no sabe cuál que la compilación elige, por lo que se sobreestima incluyendo todas las ramas.- La precisión de
cquery
requiere compilar más del gráfico quequery
sí lo hace. Específicamente,cquery
evalúa los destinos configurados, mientras quequery
solo evalúa objetivos. Esto lleva más tiempo y utiliza más memoria. - La interpretación de
cquery
de El lenguaje de consulta presenta ambigüedades. que evitaquery
. Por ejemplo: si"//foo"
existe en dos configuraciones, ¿cuál ¿cquery "deps(//foo)"
debe usar? La función[config](#config)
puede ayudar con esto. - Como herramienta más reciente,
cquery
no es compatible con ciertos usos diferentes. Consulta Problemas conocidos para obtener más detalles.
Problemas conocidos
Todas las orientaciones que "desarrolla" cquery
deben tener la misma configuración.
Antes de evaluar las consultas, cquery
activa una compilación de solo
antes del punto en el que se ejecutarían las acciones de compilación. El objetivo es
“compilaciones” se seleccionan de forma predeterminada entre todas las etiquetas que aparecen en la consulta.
expresión (esto se puede anular
con --universe_scope
). Estos
deben tener la misma configuración.
Si bien estos generalmente comparten el "objetivo" de nivel superior configuración,
pueden cambiar su propia configuración con
transiciones perimetrales entrantes.
Aquí es donde cquery
no cumple con los requisitos.
Solución alternativa: Si es posible, establece --universe_scope
en un valor más estricto.
del proyecto. Por ejemplo:
# This command attempts to build the transitive closures of both //foo and # //bar. //bar uses an incoming edge transition to change its --cpu flag. $ bazel cquery 'somepath(//foo, //bar)' ERROR: Error doing post analysis query: Top-level targets //foo and //bar have different configurations (top-level targets with different configurations is not supported) # This command only builds the transitive closure of //foo, under which # //bar should exist in the correct configuration. $ bazel cquery 'somepath(//foo, //bar)' --universe_scope=//foo
No se admite --output=xml
.
Resultado no determinista.
cquery
no borra automáticamente el gráfico de compilación de
de comandos anteriores y, por lo tanto, es propenso a captar resultados pasados
para tus consultas. Por ejemplo, genquery
ejerce una transición de host en
su atributo tools
, es decir, configura sus herramientas en el
configuración del host.
A continuación, puedes ver los efectos persistentes de esa transición.
$ cat > foo/BUILD <<<EOF genrule( name = "my_gen", srcs = ["x.in"], outs = ["x.cc"], cmd = "$(locations :tool) $< >$@", tools = [":tool"], ) cc_library( name = "tool", ) EOF $ bazel cquery "//foo:tool" tool(target_config) $ bazel cquery "deps(//foo:my_gen)" my_gen (target_config) tool (host_config) ... $ bazel cquery "//foo:tool" tool(host_config)
Solución alternativa: Cambia cualquier opción de inicio para forzar un nuevo análisis de los destinos configurados.
Por ejemplo, agrega --test_arg=<whatever>
al comando de compilación.
Soluciona problemas
Patrones de objetivos recurrentes (/...
)
Si encuentras lo siguiente:
$ bazel cquery --universe_scope=//foo:app "somepath(//foo:app, //foo/...)" ERROR: Error doing post analysis query: Evaluation failed: Unable to load package '[foo]' because package is not in scope. Check that all target patterns in query expression are within the --universe_scope of this query.
esto sugiere de manera incorrecta que el paquete //foo
no está dentro del alcance aunque
--universe_scope=//foo:app
lo incluye. Esto se debe a las limitaciones de diseño
cquery
Como solución alternativa, incluye explícitamente //foo/...
en el universo.
alcance:
$ bazel cquery --universe_scope=//foo:app,//foo/... "somepath(//foo:app, //foo/...)"
Si eso no funciona (por ejemplo, porque algún destino en //foo/...
no puede
compila con las marcas de compilación elegidas), desenvuelve manualmente el patrón en su
paquetes constituyentes con una consulta de procesamiento previo:
# Replace "//foo/..." with a subshell query call (not cquery!) outputting each package, piped into # a sed call converting "<pkg>" to "//<pkg>:*", piped into a "+"-delimited line merge. # Output looks like "//foo:*+//foo/bar:*+//foo/baz". # $ bazel cquery --universe_scope=//foo:app "somepath(//foo:app, $(bazel query //foo/... --output=package | sed -e 's/^/\/\//' -e 's/$/:*/' | paste -sd "+" -))"