बिल्ड इवेंट प्रोटोकॉल की पूरी जानकारी, प्रोटोकॉल के बफ़र की परिभाषा में मिल सकती है. हालांकि, स्पेसिफ़िकेशन को देखने से पहले जानकारी हासिल करना मददगार हो सकता है.
एक आसान 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
पहले तीन इवेंट से यह जानकारी मिलती है कि बेज़ल को कैसे शुरू किया गया था.
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"
}
}
BEP में आसपेक्ट रेशियो के नतीजे
ऑर्डिनरी बिल्ड, (target, configuration)
पेयर से जुड़ी कार्रवाइयों का आकलन करते हैं. आसपेक्ट को चालू करके तैयार करते समय, Baze, (target, configuration,
aspect)
तीन गुना से जुड़े टारगेट का भी आकलन करता है. ऐसा हर टारगेट के लिए किया जाता है जिस पर किसी दिए गए आसपेक्ट रेशियो में असर पड़ा हो.
BEP में, अलग-अलग पहलुओं के लिए आकलन के नतीजे उपलब्ध होते हैं. भले ही, उनमें पहलु के हिसाब से इवेंट टाइप न हों. लागू होने वाले आसपेक्ट रेशियो वाले हर (target, configuration)
पेयर के लिए, Baze, एक और 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
इवेंट के रीक्यूर्सिव और शेयर किए गए स्ट्रक्चर के बारे में बताया गया है. यह स्ट्रक्चर, Starlark Depset के स्ट्रक्चर से मेल खाता है.
NamedSetOfFiles
इवेंट को प्रोसेस करते समय, उपभोक्ताओं को क्वाड्रैटिक एल्गोरिदम से बचना चाहिए. ऐसा इसलिए, क्योंकि बड़े बिल्ड में ऐसे 10 हज़ार इवेंट हो सकते हैं. साथ ही, क्वाड्रैटिक कॉम्प्लेक्सिटी वाले ट्रैवल के लिए, करोड़ों ऑपरेशन की ज़रूरत होती है.
दूसरी इमेज. NamedSetOfFiles
बीईपी ग्राफ़.
NamedSetOfFiles
इवेंट, BEP स्ट्रीम में हमेशा उस 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)