La especificación completa del protocolo del evento de compilación se puede encontrar en su protocolo definición del búfer. Sin embargo, podría ser útil desarrollar cierta intuición antes de mirar la especificación.
Considera un espacio de trabajo de Bazel simple que consta de dos secuencias de comandos de shell vacías, foo.sh
y foo_test.sh
, y el siguiente archivo BUILD
:
sh_library(
name = "foo_lib",
srcs = ["foo.sh"],
)
sh_test(
name = "foo_test",
srcs = ["foo_test.sh"],
deps = [":foo_lib"],
)
Cuando ejecutes bazel test ...
en este proyecto, el gráfico de compilación de los eventos de compilación generados se parecerá al siguiente gráfico. Las flechas indican
antes mencionada. Ten en cuenta que se omitieron algunos eventos de compilación y la mayoría de los campos para ahorrar espacio.
Figura 1: Gráfico de BEP
Inicialmente, se publica un evento BuildStarted
. El evento nos informa que el
Se invocó la compilación mediante el comando bazel test
y anuncia eventos secundarios:
OptionsParsed
WorkspaceStatus
CommandLine
UnstructuredCommandLine
BuildMetadata
BuildFinished
PatternExpanded
Progress
Los primeros tres eventos proporcionan información sobre cómo se invocó Bazel.
El evento de compilación PatternExpanded
proporciona información sobre los destinos específicos a los que se expandió el patrón ...
: //foo:foo_lib
y //foo:foo_test
. Para ello, declara dos
TargetConfigured
eventos como secundarios. Ten en cuenta que el evento TargetConfigured
declara el evento Configuration
como un evento secundario, aunque Configuration
se haya publicado antes que el evento TargetConfigured
.
Además de la relación entre padres e hijos, los eventos también pueden hacer referencia entre sí.
con identificadores de eventos de compilación. Por ejemplo, en el gráfico anterior la
El evento TargetComplete
hace referencia al evento NamedSetOfFiles
en su fileSets
.
Los eventos de compilación que hacen referencia a archivos no suelen incorporar los nombres ni las rutas de acceso de los archivos en el evento. En su lugar, contienen el identificador del evento de compilación
de un evento NamedSetOfFiles
, que contendrá los nombres de archivos reales y
rutas de ataque. El evento NamedSetOfFiles
permite que se informe un conjunto de archivos una vez y que muchos destinos hagan referencia a él. Esta estructura es necesaria porque, de lo contrario,
En algunos casos, el tamaño de salida del protocolo
de eventos de compilación crecería cuadráticamente con
la cantidad de archivos. Es posible que un evento NamedSetOfFiles
tampoco tenga todos sus archivos incorporados, sino que haga referencia a otros eventos NamedSetOfFiles
a través de sus identificadores de eventos de compilación.
A continuación, se muestra una instancia del evento TargetComplete
correspondiente al evento //foo:foo_lib
.
objetivo del gráfico anterior, impreso en la representación JSON del búfer de protocolo.
El identificador del evento de compilación contiene el objetivo como una cadena opaca y hace referencia a
El evento Configuration
mediante su identificador de evento de compilación El evento no
anunciar eventos secundarios. La carga útil contiene información sobre si el
el destino se compiló correctamente, el conjunto de archivos de salida y el tipo
construyen.
{
"id": {
"targetCompleted": {
"label": "//foo:foo_lib",
"configuration": {
"id": "544e39a7f0abdb3efdd29d675a48bc6a"
}
}
},
"completed": {
"success": true,
"outputGroup": [{
"name": "default",
"fileSets": [{
"id": "0"
}]
}],
"targetKind": "sh_library rule"
}
}
Resultados de los aspectos en BEP
Las compilaciones ordinarias evalúan las acciones asociadas con pares (target, configuration)
. Cuando se compila con aspectos habilitados, Bazel también evalúa los destinos asociados con triples (target, configuration,
aspect)
para cada destino afectado por un aspecto habilitado determinado.
Los resultados de la evaluación de los aspectos están disponibles en BEP a pesar de la ausencia de tipos de eventos específicos de los aspectos. Para cada par (target, configuration)
con un aspecto aplicable, Bazel publica un evento TargetConfigured
y TargetComplete
adicional que contiene el resultado de aplicar el aspecto al objetivo. Por ejemplo, si //:foo_lib
se compila con --aspects=aspects/myaspect.bzl%custom_aspect
, este evento también aparecerá en el BEP:
{
"id": {
"targetCompleted": {
"label": "//foo:foo_lib",
"configuration": {
"id": "544e39a7f0abdb3efdd29d675a48bc6a"
},
"aspect": "aspects/myaspect.bzl%custom_aspect"
}
},
"completed": {
"success": true,
"outputGroup": [{
"name": "default",
"fileSets": [{
"id": "1"
}]
}]
}
}
Cómo consumir NamedSetOfFiles
Determinar los artefactos producidos por un objetivo (o aspecto) determinado es una práctica
caso de uso de BEP que se puede hacer de manera eficiente con un poco de preparación. Esta sección
Se analiza la estructura recursiva y compartida que ofrece NamedSetOfFiles
.
evento, que coincide con la estructura de un Depset de Starlark.
Los consumidores deben evitar los algoritmos cuadráticos al procesar
NamedSetOfFiles
porque las compilaciones grandes pueden contener decenas de miles de
estos eventos, lo que requiere cientos de millones de operaciones en un recorrido con
complejidad cuadrática.
Figura 2: Gráfico de BEP de NamedSetOfFiles
.
Un evento NamedSetOfFiles
siempre aparece en la transmisión de BEP antes de
TargetComplete
o NamedSetOfFiles
que hace referencia a ella. Esto es lo opuesto a la relación de eventos "superior-secundario", en la que todos los eventos, excepto el primero, aparecen después de, al menos, un evento que lo anuncia. Un evento NamedSetOfFiles
es
anunciado por un evento Progress
sin semántica.
Dadas estas restricciones para ordenar y compartir, un consumidor típico debe almacenar en búfer todos
Eventos NamedSetOfFiles
hasta que se agote la transmisión de BEP. En el siguiente flujo de eventos JSON y código de Python, se muestra cómo propagar un mapa desde el objetivo o el aspecto a los artefactos compilados en el grupo de salida "predeterminado" y cómo procesar los resultados de un subconjunto de objetivos o aspectos compilados:
named_sets = {} # type: dict[str, NamedSetOfFiles]
outputs = {} # type: dict[str, dict[str, set[str]]]
for event in stream:
kind = event.id.WhichOneof("id")
if kind == "named_set":
named_sets[event.id.named_set.id] = event.named_set_of_files
elif kind == "target_completed":
tc = event.id.target_completed
target_id = (tc.label, tc.configuration.id, tc.aspect)
outputs[target_id] = {}
for group in event.completed.output_group:
outputs[target_id][group.name] = {fs.id for fs in group.file_sets}
for result_id in relevant_subset(outputs.keys()):
visit = outputs[result_id].get("default", [])
seen_sets = set(visit)
while visit:
set_name = visit.pop()
s = named_sets[set_name]
for f in s.files:
process_file(result_id, f)
for fs in s.file_sets:
if fs.id not in seen_sets:
visit.add(fs.id)
seen_sets.add(fs.id)