ตัวอย่างโปรโตคอลเหตุการณ์การสร้าง

รายงานปัญหา ดูแหล่งที่มา

ดูข้อกำหนดทั้งหมดของโปรโตคอลเหตุการณ์บิลด์ได้ในคำจำกัดความบัฟเฟอร์โปรโตคอล อย่างไรก็ตาม การสัญชาตญาณก่อนดูข้อกำหนดอาจมีประโยชน์

ลองพิจารณาพื้นที่ทํางาน Bazel แบบง่ายที่ประกอบด้วยสคริปต์ Shell เปล่า 2 รายการ foo.sh และ foo_test.sh และไฟล์ BUILD ต่อไปนี้

sh_library(
    name = "foo_lib",
    srcs = ["foo.sh"],
)

sh_test(
    name = "foo_test",
    srcs = ["foo_test.sh"],
    deps = [":foo_lib"],
)

เมื่อเรียกใช้ bazel test ... ในโปรเจ็กต์นี้ กราฟบิลด์ของเหตุการณ์บิลด์ที่สร้างขึ้นจะคล้ายกับกราฟด้านล่าง ลูกศรแสดงถึงความสัมพันธ์ ระหว่างพ่อแม่และลูกที่ระบุไว้ข้างต้น โปรดทราบว่าได้มีการละเหตุการณ์บิลด์บางรายการและ ช่องส่วนใหญ่ไว้เพื่อให้สั้นกระชับ

กราฟ Bep

รูปที่ 1 กราฟ BEP

ในขั้นต้น มีการเผยแพร่กิจกรรม BuildStarted เหตุการณ์แจ้งให้เราทราบว่ามีการเรียกใช้บิลด์ผ่านคําสั่ง bazel test และประกาศเหตุการณ์ย่อย:

  • OptionsParsed
  • WorkspaceStatus
  • CommandLine
  • UnstructuredCommandLine
  • BuildMetadata
  • BuildFinished
  • PatternExpanded
  • Progress

3 เหตุการณ์แรกให้ข้อมูลเกี่ยวกับวิธีเรียกใช้ Bazel

เหตุการณ์บิลด์ PatternExpanded ให้ข้อมูลเชิงลึกเกี่ยวกับเป้าหมายที่เฉพาะเจาะจงซึ่งรูปแบบ ... ขยายเป็น //foo:foo_lib และ //foo:foo_test โดยจะประกาศ TargetConfigured เหตุการณ์ 2 รายการเป็นเหตุการณ์ย่อย โปรดทราบว่าเหตุการณ์ TargetConfigured จะประกาศกิจกรรม Configuration เป็นกิจกรรมย่อย แม้ว่าเหตุการณ์ Configuration จะโพสต์ก่อนกิจกรรม TargetConfigured ก็ตาม

นอกเหนือจากความสัมพันธ์แบบผู้ปกครองและเด็กแล้ว เหตุการณ์ยังอาจอ้างอิงถึงกันโดยใช้ตัวระบุเหตุการณ์ของบิลด์ ตัวอย่างเช่น ในกราฟด้านบน เหตุการณ์ TargetComplete หมายถึงเหตุการณ์ NamedSetOfFiles ในช่อง fileSets

โดยปกติเหตุการณ์การสร้างที่อ้างอิงไฟล์มักไม่ได้ฝังชื่อไฟล์และเส้นทางในเหตุการณ์ แต่จะมีตัวระบุเหตุการณ์ของบิลด์ของเหตุการณ์ NamedSetOfFiles ซึ่งจะมีชื่อไฟล์และเส้นทางจริง เหตุการณ์ NamedSetOfFiles ช่วยให้รายงานชุดไฟล์ได้ 1 ครั้งและหลายเป้าหมายอ้างอิงถึง โครงสร้างนี้จำเป็นเนื่องจากมิฉะนั้นในบางกรณี ขนาดเอาต์พุตของโปรโตคอลเหตุการณ์บิลด์จะขยายเป็นสี่เท่าพร้อมกับจำนวนไฟล์ นอกจากนี้ เหตุการณ์ NamedSetOfFiles อาจไม่ได้ฝังไฟล์ทั้งหมดไว้ แต่อ้างอิงเหตุการณ์ NamedSetOfFiles อื่นๆ ผ่านตัวระบุเหตุการณ์บิลด์แทน

ด้านล่างนี้คืออินสแตนซ์ของเหตุการณ์ TargetComplete สำหรับเป้าหมาย //foo:foo_lib จากกราฟด้านบน ซึ่งพิมพ์ลงในการแสดง JSON ของบัฟเฟอร์โปรโตคอล ตัวระบุเหตุการณ์ของบิลด์มีเป้าหมายเป็นสตริงทึบแสงและอ้างอิงถึงเหตุการณ์ Configuration โดยใช้ตัวระบุเหตุการณ์ของบิลด์ กิจกรรมนี้จะไม่ประกาศ กิจกรรมย่อยใดๆ เพย์โหลดประกอบด้วยข้อมูลเกี่ยวกับว่าสร้างเป้าหมายสำเร็จหรือไม่ ชุดไฟล์เอาต์พุต และประเภทเป้าหมายที่สร้าง

{
  "id": {
    "targetCompleted": {
      "label": "//foo:foo_lib",
      "configuration": {
        "id": "544e39a7f0abdb3efdd29d675a48bc6a"
      }
    }
  },
  "completed": {
    "success": true,
    "outputGroup": [{
      "name": "default",
      "fileSets": [{
        "id": "0"
      }]
    }],
    "targetKind": "sh_library rule"
  }
}

ผลลัพธ์ใน BEP

บิลด์ทั่วไปจะประเมินการดำเนินการที่เชื่อมโยงกับคู่ (target, configuration) เมื่อสร้างโดยเปิดใช้องค์ประกอบ Bazel จะประเมินเป้าหมายที่เกี่ยวข้องกับ 3 ระยะ (target, configuration, aspect) เพิ่มเติมสำหรับแต่ละเป้าหมายที่ได้รับผลกระทบจากด้านที่เปิดใช้หนึ่งๆ

ผลการประเมินสำหรับแง่มุมต่างๆ จะแสดงใน BEP แม้ว่าจะไม่มีประเภทเหตุการณ์ที่เฉพาะเจาะจงในด้านต่างๆ ก็ตาม สำหรับ (target, configuration) แต่ละคู่ที่มีแง่มุมที่เกี่ยวข้อง Bazel จะเผยแพร่เหตุการณ์ TargetConfigured และ TargetComplete เพิ่มเติม ซึ่งเป็นผลมาจากการนำลักษณะดังกล่าวไปใช้กับเป้าหมาย ตัวอย่างเช่น หาก //:foo_lib สร้างด้วย --aspects=aspects/myaspect.bzl%custom_aspect เหตุการณ์นี้จะปรากฏใน 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"
      }]
    }]
  }
}

กำลังใช้ NamedSetOfFiles

การพิจารณาสิ่งประดิษฐ์ที่สร้างขึ้นโดยเป้าหมาย (หรือลักษณะ) เป็นกรณีการใช้งานของ BEP ที่พบได้ทั่วไปซึ่งสามารถทำได้อย่างมีประสิทธิภาพด้วยการเตรียมการบางอย่าง ส่วนนี้จะพูดถึงโครงสร้างที่ใช้ร่วมกันที่เกิดซ้ำซึ่งนำเสนอโดยเหตุการณ์ NamedSetOfFiles ซึ่งตรงกับโครงสร้างของ Depset Starlark

ผู้บริโภคต้องระมัดระวังเพื่อหลีกเลี่ยงอัลกอริทึมกำลังสองเมื่อประมวลผลเหตุการณ์ NamedSetOfFiles เนื่องจากบิลด์ขนาดใหญ่อาจมีเหตุการณ์ดังกล่าวได้หลายหมื่นเหตุการณ์ ซึ่งต้องใช้การดำเนินการหลายร้อยล้านครั้งในการดำเนินการข้ามผ่านซึ่งมีความซับซ้อนแบบกำลังสอง

กราฟที่มีชื่อ

รูปที่ 2 NamedSetOfFiles กราฟ BEP

เหตุการณ์ NamedSetOfFiles จะปรากฏในสตรีม BEP เสมอก่อนเหตุการณ์ TargetComplete หรือ NamedSetOfFiles ที่อ้างอิงเหตุการณ์ดังกล่าว นี่คือค่าผกผันของความสัมพันธ์ของเหตุการณ์ "หลัก-ย่อย" ซึ่งทั้งหมดยกเว้นเหตุการณ์แรกปรากฏขึ้นหลังจากที่ประกาศเหตุการณ์อย่างน้อย 1 เหตุการณ์ จะมีการประกาศเหตุการณ์ NamedSetOfFiles โดยเหตุการณ์ Progress ที่ไม่มีความหมาย

ด้วยข้อจำกัดในการจัดลำดับและการแชร์เหล่านี้ ผู้บริโภคทั่วไปจึงต้องบัฟเฟอร์เหตุการณ์ NamedSetOfFiles ทั้งหมดจนกว่าสตรีม BEP จะหมด สตรีมเหตุการณ์ JSON และโค้ด Python ต่อไปนี้สาธิตวิธีสร้างแผนที่จากเป้าหมาย/มุมไปจนถึงอาร์ติแฟกต์ที่สร้างขึ้นในกลุ่มเอาต์พุต "ค่าเริ่มต้น" และวิธีประมวลผลเอาต์พุตสำหรับเป้าหมาย/มุมที่สร้างขึ้นบางส่วน

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)