Contoh Protokol Peristiwa Build

Laporkan masalah Lihat sumber Per malam · 7,2 · 7,1 · 7,0 · 6,5 · 6,4

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.

bep-graph

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 kejadian 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.

namedsetoffiles-bep-graph

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)