Spesifikasi lengkap Build Event Protocol dapat ditemukan dalam definisi buffer protokolnya. Namun, mungkin akan berguna untuk membangun intuisi sebelum melihat spesifikasinya.
Pertimbangkan ruang kerja Bazel sederhana yang terdiri dari dua skrip shell kosong
foo.sh dan foo_test.sh serta file BUILD berikut:
sh_library(
name = "foo_lib",
srcs = ["foo.sh"],
)
sh_test(
name = "foo_test",
srcs = ["foo_test.sh"],
deps = [":foo_lib"],
)
Saat menjalankan bazel test ... di project ini, grafik build peristiwa build yang dihasilkan
akan menyerupai grafik di bawah. Panah menunjukkan hubungan induk dan turunan yang disebutkan di atas. Perhatikan bahwa beberapa peristiwa build dan
sebagian besar kolom telah dihilangkan untuk mempersingkat.

Gambar 1. Grafik BEP.
Awalnya, peristiwa BuildStarted dipublikasikan. Peristiwa ini memberi tahu kita bahwa
build dipanggil melalui perintah bazel test dan mengumumkan peristiwa turunan:
OptionsParsedWorkspaceStatusCommandLineUnstructuredCommandLineBuildMetadataBuildFinishedPatternExpandedProgress
Tiga peristiwa pertama memberikan informasi tentang cara Bazel dipanggil.
Peristiwa build PatternExpanded memberikan insight
tentang target spesifik yang diperluas oleh pola ... ke:
//foo:foo_lib dan //foo:foo_test. Hal ini dilakukan dengan mendeklarasikan dua
TargetConfigured peristiwa sebagai turunan. Perhatikan bahwa peristiwa TargetConfigured
mendeklarasikan peristiwa Configuration sebagai peristiwa turunan, meskipun Configuration
telah diposting sebelum peristiwa TargetConfigured.
Selain hubungan induk dan turunan, peristiwa juga dapat merujuk satu sama lain
menggunakan ID peristiwa build-nya. Misalnya, dalam grafik di atas, peristiwa
TargetComplete merujuk ke peristiwa NamedSetOfFiles di kolom fileSets.
Peristiwa build yang merujuk ke file biasanya tidak menyematkan nama dan jalur file dalam peristiwa. Sebagai gantinya, peristiwa build tersebut berisi ID peristiwa build
peristiwa NamedSetOfFiles, yang kemudian akan berisi nama dan jalur file sebenarnya. Peristiwa NamedSetOfFiles memungkinkan sekumpulan file dilaporkan satu kali dan
dirujuk oleh banyak target. Struktur ini diperlukan karena jika tidak, dalam
beberapa kasus, ukuran output Build Event Protocol akan bertambah secara kuadrat dengan
jumlah file. Peristiwa NamedSetOfFiles mungkin juga tidak menyematkan semua filenya, tetapi merujuk ke peristiwa NamedSetOfFiles lainnya melalui ID peristiwa build-nya.
Di bawah ini adalah instance peristiwa TargetComplete untuk //foo:foo_lib
target dari grafik di atas, yang dicetak dalam representasi JSON buffer protokol.
ID peristiwa build berisi target sebagai string buram dan merujuk ke
peristiwa Configuration menggunakan ID peristiwa build-nya. Peristiwa ini tidak
mengumumkan peristiwa turunan apa pun. Payload berisi informasi tentang apakah target berhasil dibuat, kumpulan file output, dan jenis target yang dibuat.
{
"id": {
"targetCompleted": {
"label": "//foo:foo_lib",
"configuration": {
"id": "544e39a7f0abdb3efdd29d675a48bc6a"
}
}
},
"completed": {
"success": true,
"outputGroup": [{
"name": "default",
"fileSets": [{
"id": "0"
}]
}],
"targetKind": "sh_library rule"
}
}
Hasil Aspek di BEP
Build biasa mengevaluasi tindakan yang terkait dengan (target, configuration)
pasangan. Saat membuat dengan aspek yang diaktifkan, Bazel
juga mengevaluasi target yang terkait dengan (target, configuration,
aspect) tiga kali lipat, untuk setiap target yang terpengaruh oleh aspek yang diaktifkan.
Hasil evaluasi untuk aspek tersedia di BEP meskipun tidak ada
jenis peristiwa khusus aspek. Untuk setiap pasangan (target, configuration) dengan aspek
yang berlaku, Bazel memublikasikan peristiwa TargetConfigured dan
TargetComplete tambahan yang berisi hasil dari penerapan aspek ke
target. Misalnya, jika //:foo_lib dibuat dengan
--aspects=aspects/myaspect.bzl%custom_aspect, peristiwa ini juga akan muncul di
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"
}]
}]
}
}
Menggunakan NamedSetOfFiles
Menentukan artefak yang dihasilkan oleh target (atau aspek) tertentu adalah kasus penggunaan BEP umum
yang dapat dilakukan secara efisien dengan beberapa persiapan. Bagian ini
membahas struktur rekursif bersama yang ditawarkan oleh NamedSetOfFiles
peristiwa, yang cocok dengan struktur Starlark Depset.
Konsumen harus berhati-hati untuk menghindari algoritma kuadrat saat memproses
NamedSetOfFiles peristiwa karena build besar dapat berisi puluhan ribu
peristiwa tersebut, yang memerlukan ratusan juta operasi dalam traversal dengan
kompleksitas kuadrat.

Gambar 2. NamedSetOfFiles Grafik BEP.
Peristiwa NamedSetOfFiles selalu muncul di aliran BEP sebelum peristiwa
TargetComplete atau NamedSetOfFiles yang mereferensikannya. Ini adalah
kebalikan dari hubungan peristiwa "induk-turunan", yang mana semua peristiwa kecuali peristiwa pertama
muncul setelah setidaknya satu peristiwa yang mengumumkannya. Peristiwa NamedSetOfFiles diumumkan oleh peristiwa Progress tanpa semantik.
Mengingat batasan pengurutan dan berbagi ini, konsumen biasa harus menyimpan semua
NamedSetOfFiles peristiwa dalam buffer hingga aliran BEP habis. Aliran peristiwa JSON
dan kode Python berikut menunjukkan cara mengisi peta dari
target/aspek ke artefak yang dibuat dalam grup output "default", dan cara
memproses output untuk subset target/aspek yang dibuat:
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)