Spesifikasi lengkap Build Event Protocol dapat ditemukan di protokol-nya definisi buffer. Namun, membangun beberapa intuisi mungkin dapat membantu 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 dari hasil
peristiwa build akan menyerupai grafik di bawah ini. Tanda panah menunjukkan
hubungan orang tua dan anak yang disebutkan di atas. Perhatikan bahwa beberapa peristiwa build dan
sebagian besar {i>field<i} telah
dihilangkan agar lebih singkat.
Gambar 1. Grafik BEP.
Awalnya, peristiwa BuildStarted
dipublikasikan. Peristiwa ini memberi tahu kita bahwa
build dipanggil melalui perintah bazel test
dan mengumumkan peristiwa turunan:
OptionsParsed
WorkspaceStatus
CommandLine
UnstructuredCommandLine
BuildMetadata
BuildFinished
PatternExpanded
Progress
Tiga peristiwa pertama memberikan informasi tentang bagaimana Bazel dipanggil.
Peristiwa build PatternExpanded
memberikan insight
tempat target spesifik yang diperluas pola ...
:
//foo:foo_lib
dan //foo:foo_test
. Hal ini dilakukan dengan
mendeklarasikan dua
Peristiwa TargetConfigured
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 saling merujuk
menggunakan ID peristiwa build-nya. Misalnya, pada grafik di atas
Peristiwa TargetComplete
merujuk ke peristiwa NamedSetOfFiles
di fileSets
kolom tersebut.
Peristiwa build yang merujuk ke file biasanya tidak menyematkan file
serta nama dan jalur dalam peristiwa. Sebagai gantinya, ID tersebut berisi ID peristiwa build
peristiwa NamedSetOfFiles
, yang kemudian akan berisi nama file sebenarnya dan
. Peristiwa NamedSetOfFiles
memungkinkan serangkaian file dilaporkan satu kali dan
yang dirujuk oleh banyak target. Struktur ini diperlukan karena
jika tidak, dalam
dalam beberapa kasus, ukuran output {i>Build Event Protocol<i}
akan tumbuh secara kuadrat dengan
jumlah file. Peristiwa NamedSetOfFiles
mungkin juga tidak memiliki semua filenya
disematkan, tetapi merujuk ke peristiwa NamedSetOfFiles
lain melalui
membuat ID peristiwa build.
Berikut adalah instance peristiwa TargetComplete
untuk //foo:foo_lib
target dari grafik di atas, yang dicetak dalam representasi JSON buffering protokol.
ID peristiwa build berisi target sebagai string buram dan merujuk pada
peristiwa Configuration
menggunakan ID peristiwa build-nya. Acara tidak
mengumumkan kejadian turunan. {i>Payload<i} berisi informasi
tentang apakah
target berhasil dibuat, kumpulan file output, dan jenis
dibuat.
{
"id": {
"targetCompleted": {
"label": "//foo:foo_lib",
"configuration": {
"id": "544e39a7f0abdb3efdd29d675a48bc6a"
}
}
},
"completed": {
"success": true,
"outputGroup": [{
"name": "default",
"fileSets": [{
"id": "0"
}]
}],
"targetKind": "sh_library rule"
}
}
Hasil Aspect di BEP
Build biasa mengevaluasi tindakan yang terkait dengan (target, configuration)
pasangan. Saat membangun dengan mengaktifkan aspek, Bazel
juga mengevaluasi target yang terkait dengan (target, configuration,
aspect)
tiga kali lipat, untuk setiap target yang terpengaruh oleh aspek yang diaktifkan tertentu.
Hasil evaluasi untuk aspek tersedia di BEP meskipun
jenis peristiwa khusus aspek. Untuk setiap pasangan (target, configuration)
dengan
aspek yang berlaku, Bazel memublikasikan TargetConfigured
tambahan
TargetComplete
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"
}]
}]
}
}
Memakai NamedSetOfFiles
Menentukan artefak yang dihasilkan oleh target (atau aspek) tertentu adalah hal yang umum
Kasus penggunaan BEP yang dapat dilakukan secara efisien dengan beberapa persiapan. Bagian ini
membahas struktur bersama rekursif yang ditawarkan oleh NamedSetOfFiles
yang cocok dengan struktur Depset Starlark.
Konsumen harus berhati-hati untuk menghindari algoritma kuadrat saat memproses
Peristiwa NamedSetOfFiles
karena build besar dapat berisi puluhan ribu peristiwa
peristiwa seperti itu, membutuhkan ratusan juta
operasi dalam sebuah traversal dengan
kompleksitas kuadratnya.
Gambar 2. Grafik BEP NamedSetOfFiles
.
Peristiwa NamedSetOfFiles
selalu muncul di aliran BEP sebelum
Peristiwa TargetComplete
atau NamedSetOfFiles
yang mereferensikannya. Ini adalah
kebalikan dari "parent-child" hubungan peristiwa, di mana semua kecuali peristiwa pertama
muncul setelah setidaknya satu peristiwa yang mengumumkannya. Peristiwa NamedSetOfFiles
yang diumumkan oleh peristiwa Progress
tanpa semantik.
Dengan adanya batasan pengurutan dan pembagian ini, konsumen pada umumnya harus mem-buffer semua
NamedSetOfFiles
acara hingga streaming BEP habis. JSON berikut
aliran peristiwa dan kode Python
menunjukkan cara mengisi peta dari
target/aspek pada artefak yang dibangun di "default" kelompok {i>output<i}, dan bagaimana
memproses output untuk subset target/aspek yang telah 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)