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