बिल्ड इवेंट प्रोटोकॉल के उदाहरण

समस्या की शिकायत करें स्रोत देखें

बिल्ड इवेंट प्रोटोकॉल की पूरी खास जानकारी, इसके प्रोटोकॉल बफ़र डेफ़िनिशन में देखी जा सकती है. हालांकि, स्पेसिफ़िकेशन के बारे में जानने से पहले, कुछ नया समझने से मदद मिल सकती है.

एक आसान Bazel फ़ाइल फ़ोल्डर बनाएं, जिसमें दो खाली शेल स्क्रिप्ट 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 ... चलाते समय, जनरेट किए गए बिल्ड इवेंट का बिल्ड ग्राफ़, नीचे दिए गए ग्राफ़ जैसा दिखेगा. तीरों से ऊपर बताए गए अभिभावक और बच्चे के संबंध का पता चलता है. ध्यान दें कि कम शब्दों में जानकारी देने की वजह से, कुछ बिल्ड इवेंट और ज़्यादातर फ़ील्ड को छोड़ दिया गया है.

बीप-ग्राफ़

पहला डायग्राम. बीईपी ग्राफ़.

शुरुआत में, BuildStarted इवेंट पब्लिश होता है. इस इवेंट से हमें पता चलता है कि bazel test कमांड से बिल्ड को शुरू किया गया था और यह चाइल्ड इवेंट के बारे में बताता है:

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

पहले तीन इवेंट में यह जानकारी मिलती है कि Bazel को कैसे शुरू किया गया.

PatternExpanded बिल्ड इवेंट से यह अहम जानकारी मिलती है कि ... पैटर्न को किन खास टारगेट के लिए बढ़ाया गया है. जैसे, //foo:foo_lib और //foo:foo_test. ऐसा दो TargetConfigured इवेंट को बच्चों के तौर पर करके किया जाता है. ध्यान दें कि TargetConfigured इवेंट, Configuration इवेंट को चाइल्ड इवेंट के तौर पर बताता है, भले ही Configuration को TargetConfigured इवेंट से पहले पोस्ट किया गया हो.

माता-पिता और बच्चे के संबंध के अलावा, इवेंट अपने बिल्ड इवेंट आइडेंटिफ़ायर का इस्तेमाल करके एक-दूसरे की जानकारी भी दे सकते हैं. उदाहरण के लिए, ऊपर दिए गए ग्राफ़ में, TargetComplete इवेंट अपने fileSets फ़ील्ड में NamedSetOfFiles इवेंट की जानकारी देता है.

फ़ाइलों को रेफ़र करने वाले बिल्ड इवेंट, आम तौर पर इवेंट में फ़ाइल के नाम और पाथ को एम्बेड नहीं करते. इसके बजाय, उनमें NamedSetOfFiles इवेंट का बिल्ड इवेंट आइडेंटिफ़ायर शामिल होता है. इसमें असल फ़ाइल के नाम और पाथ शामिल होते हैं. NamedSetOfFiles इवेंट, फ़ाइलों के सेट को एक बार रिपोर्ट करने और कई टारगेट को रेफ़र करने की अनुमति देता है. यह संरचना इसलिए ज़रूरी है, क्योंकि कुछ मामलों में बिल्ड इवेंट प्रोटोकॉल आउटपुट साइज़, फ़ाइलों की संख्या के साथ-साथ एक चौथाई क्रम में बढ़ता है. किसी NamedSetOfFiles इवेंट में भी उसकी सभी फ़ाइलें एम्बेड नहीं की जा सकती हैं, लेकिन इसके बजाय अन्य NamedSetOfFiles इवेंट को उनके बिल्ड इवेंट आइडेंटिफ़ायर की मदद से रेफ़र किया जा सकता है.

नीचे ऊपर दिए गए ग्राफ़ से //foo:foo_lib टारगेट के लिए TargetComplete इवेंट का एक इंस्टेंस दिया गया है, जिसे प्रोटोकॉल बफ़र के JSON फ़ॉर्मैट में प्रिंट किया गया है. बिल्ड इवेंट आइडेंटिफ़ायर में टारगेट को एक ओपेक स्ट्रिंग के तौर पर शामिल किया जाता है और Configuration इवेंट के बारे में बताने के लिए, बिल्ड इवेंट आइडेंटिफ़ायर का इस्तेमाल किया जाता है. इवेंट में बच्चों के किसी भी इवेंट के बारे में नहीं बताया गया है. पेलोड में यह जानकारी शामिल होती है कि टारगेट सही तरीके से बनाया गया है या नहीं, आउटपुट फ़ाइलों का सेट, और किस तरह का टारगेट बनाया गया है.

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

बीईपी में आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात)

सामान्य बिल्ड, (target, configuration) पेयर से जुड़ी कार्रवाइयों का आकलन करते हैं. लक्ष्यों के हिसाब से डेटा तैयार करने पर, Bazel किसी भी चालू आसपेक्ट से प्रभावित हर टारगेट के लिए, (target, configuration, aspect) तीन गुना से जुड़े टारगेट का भी आकलन करता है.

आसपेक्ट पर आधारित इवेंट टाइप मौजूद न होने के बावजूद, बीईपी में पहलुओं के आकलन के नतीजे उपलब्ध होते हैं. लागू होने वाले हर (target, configuration) जोड़े के लिए, Bazel एक और TargetConfigured और TargetComplete इवेंट पब्लिश करता है. उदाहरण के लिए, अगर //:foo_lib को --aspects=aspects/myaspect.bzl%custom_aspect की मदद से बनाया गया है, तो यह इवेंट बीईपी में भी दिखेगा:

{
  "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 का इस्तेमाल कर रहे हैं

किसी दिए गए टारगेट (या पहलू) से बने आर्टफ़ैक्ट की पहचान करना, बीईपी का सामान्य इस्तेमाल है. इसे कुछ तैयारी करके, बेहतर तरीके से किया जा सकता है. इस सेक्शन में, NamedSetOfFiles इवेंट के ऑफ़र किए गए बार-बार आने वाले और शेयर किए गए स्ट्रक्चर पर चर्चा की गई है. यह स्टारलार्क डेपसेट के स्ट्रक्चर से मेल खाता है.

NamedSetOfFiles इवेंट को प्रोसेस करते समय, उपभोक्ताओं को क्वाड्रेटिक एल्गोरिदम से बचने का ध्यान रखना चाहिए. ऐसा इसलिए, क्योंकि बड़े बिल्ड में हज़ारों इवेंट हो सकते हैं. ऐसे में, क्वाड्रेटिक जटिलता वाले ट्रैवर्सल में करोड़ों ऑपरेशन की ज़रूरत होती है.

namesetoffiles-bep-graph

दूसरी इमेज. NamedSetOfFiles बीईपी ग्राफ़.

BEP स्ट्रीम में, NamedSetOfFiles इवेंट हमेशा TargetComplete या NamedSetOfFiles इवेंट से पहले दिखता है, जिसमें उसका रेफ़रंस होता है. यह "पैरंट-चाइल्ड" इवेंट संबंध के उलट है, जहां कम से कम एक इवेंट का एलान करने के बाद, पहले इवेंट को छोड़कर बाकी सभी दिखते हैं. NamedSetOfFiles इवेंट का एलान, Progress इवेंट से किया जाता है. इसमें कोई सिमेंटिक नहीं होता.

ऑर्डर और शेयर करने से जुड़ी इन सीमाओं को देखते हुए, एक आम उपभोक्ता को सभी NamedSetOfFiles इवेंट को तब तक बफ़र करना होगा, जब तक बीईपी स्ट्रीम खत्म नहीं हो जाती. नीचे दिए गए 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)