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