Bazel मॉड्यूल एक Bazel प्रोजेक्ट है, जिसके कई वर्शन हो सकते हैं. इनमें से हर वर्शन, उन अन्य मॉड्यूल के बारे में मेटाडेटा पब्लिश करता है जिन पर वह निर्भर करता है. यह, डिपेंडेंसी मैनेजमेंट के अन्य सिस्टम में मौजूद, जाने-पहचाने कॉन्सेप्ट के जैसा है. जैसे, Maven आर्टफ़ैक्ट, npm पैकेज, Go मॉड्यूल या Cargo क्रेट.
किसी मॉड्यूल के रेपो रूट में, MODULE.bazel फ़ाइल होनी चाहिए. यह फ़ाइल, मॉड्यूल का मेनिफ़ेस्ट होती है. इसमें उसका नाम, वर्शन, सीधे तौर पर निर्भरता की सूची, और अन्य जानकारी होती है. यहां एक सामान्य उदाहरण दिया गया है:
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "protobuf", version = "3.19.0")
निर्देशों की पूरी सूची देखें जो
MODULE.bazel फ़ाइलों में उपलब्ध हैं.
मॉड्यूल रिज़ॉल्यूशन करने के लिए, Bazel सबसे पहले रूट मॉड्यूल की
MODULE.bazel फ़ाइल को पढ़ता है. इसके बाद, वह Bazel रजिस्ट्री से, किसी भी डिपेंडेंसी की
MODULE.bazel फ़ाइल के लिए बार-बार अनुरोध करता है. यह प्रोसेस तब तक चलती है, जब तक उसे
पूरी डिपेंडेंसी ग्राफ़ नहीं मिल जाता.
डिफ़ॉल्ट तौर पर, Bazel इसके बाद इस्तेमाल करने के लिए, हर मॉड्यूल का एक वर्शनचुनता है. Bazel, हर मॉड्यूल को एक रेपो के तौर पर दिखाता है. साथ ही, हर रेपो को कैसे तय किया जाए, यह जानने के लिए वह रजिस्ट्री से फिर से संपर्क करता है.
वर्शन का फ़ॉर्मैट
Bazel का एक बड़ा ईकोसिस्टम है और प्रोजेक्ट, वर्शनिंग की अलग-अलग स्कीम का इस्तेमाल करते हैं. इनमें सबसे ज़्यादा लोकप्रिय SemVer है. हालांकि, Abseil जैसे अहम प्रोजेक्ट भी हैं जो अलग-अलग स्कीम का इस्तेमाल करते हैं. इसके वर्शन, तारीख पर आधारित होते हैं. उदाहरण के लिए, 20210324.2).
इस वजह से, Bazel, SemVer स्पेसिफ़िकेशन के ज़्यादा आसान वर्शन का इस्तेमाल करता है. इनमें ये अंतर शामिल हैं:
- SemVer के मुताबिक, वर्शन के "रिलीज़" वाले हिस्से में तीन सेगमेंट होने चाहिए:
MAJOR.MINOR.PATCH. Bazel में, इस ज़रूरत को कम कर दिया गया है, ताकि सेगमेंट की कोई भी संख्या इस्तेमाल की जा सके. - SemVer में, "रिलीज़" वाले हिस्से के हर सेगमेंट में सिर्फ़ अंक होने चाहिए. Bazel में, इस ज़रूरत को कम कर दिया गया है, ताकि अक्षरों का भी इस्तेमाल किया जा सके. साथ ही, तुलना के सिमैंटिक, "प्रिरिलीज़" वाले हिस्से में मौजूद "आइडेंटिफ़ायर" से मेल खाते हैं.
- इसके अलावा, मेजर, माइनर, और पैच वर्शन में बढ़ोतरी के सिमैंटिक लागू नहीं किए जाते.
SemVer का कोई भी मान्य वर्शन, Bazel मॉड्यूल का मान्य वर्शन होता है. इसके अलावा, SemVer के दो
वर्शन a और b की तुलना करने पर, a < b तब और सिर्फ़ तब होता है, जब
Bazel मॉड्यूल के वर्शन के तौर पर उनकी तुलना करने पर भी ऐसा ही होता है.
आखिर में, मॉड्यूल वर्शनिंग के बारे में ज़्यादा जानने के लिए, अक्सर पूछे जाने वाले सवाल देखेंMODULE.bazel.
वर्शन चुनना
डायमंड डिपेंडेंसी की समस्या के बारे में जानें. यह, वर्शन वाली डिपेंडेंसी मैनेजमेंट स्पेस में एक अहम समस्या है. मान लें कि आपके पास यह डिपेंडेंसी ग्राफ़ है:
A 1.0
/ \
B 1.0 C 1.1
| |
D 1.0 D 1.1
D का कौनसा वर्शन इस्तेमाल किया जाना चाहिए? इस सवाल का जवाब पाने के लिए, Bazel, Go मॉड्यूल सिस्टम में पेश किए गए
मिनिमल वर्शन सिलेक्शन
(एमवीएस) एल्गोरिदम का इस्तेमाल करता है. एमवीएस यह मानता है कि किसी मॉड्यूल के सभी नए वर्शन, पुराने वर्शन के साथ काम करते हैं. इसलिए, यह किसी भी डिपेंडेंट (D 1.1 हमारे उदाहरण में) के बताए गए सबसे नए वर्शन को चुनता है. इसे "मिनिमल" इसलिए कहा जाता है, क्योंकि D 1.1 वह सबसे पुराना वर्शन है जो हमारी ज़रूरतों को पूरा कर सकता है. भले ही, D 1.2 या इससे नया वर्शन मौजूद हो, हम उसे नहीं चुनते. एमवीएस का इस्तेमाल करने से, वर्शन चुनने की एक ऐसी प्रोसेस बनती है जो ज़्यादा सटीक और दोहराई जा सकती है.
हटाए गए वर्शन
रजिस्ट्री, कुछ वर्शन को हटाए गए के तौर पर तय कर सकती है. ऐसा तब किया जाता है, जब उनसे बचना चाहिए. जैसे, सुरक्षा से जुड़ी कमज़ोरियों के लिए. किसी मॉड्यूल का हटाया गया वर्शन चुनने पर, Bazel एक गड़बड़ी दिखाता है. इस गड़बड़ी को ठीक करने के लिए, किसी नए,
न हटाए गए वर्शन पर अपग्रेड करें या हटाए गए वर्शन को साफ़ तौर पर अनुमति देने के लिए, --allow_yanked_versions
फ़्लैग का इस्तेमाल करें.
बदली गई कीमत
Bazel मॉड्यूल रिज़ॉल्यूशन के व्यवहार में बदलाव करने के लिए, MODULE.bazel फ़ाइल में ओवरराइड तय करें. सिर्फ़ रूट मॉड्यूल के ओवरराइड लागू होते हैं. अगर किसी मॉड्यूल का इस्तेमाल डिपेंडेंसी के तौर पर किया जाता है, तो उसके ओवरराइड अनदेखा कर दिए जाते हैं.
हर ओवरराइड, किसी खास मॉड्यूल के नाम के लिए तय किया जाता है. इससे डिपेंडेंसी ग्राफ़ में मौजूद उसके सभी वर्शन पर असर पड़ता है. हालांकि, सिर्फ़ रूट मॉड्यूल के ओवरराइड लागू होते हैं, लेकिन वे ट्रांज़िटिव डिपेंडेंसी के लिए हो सकते हैं जिन पर रूट मॉड्यूल सीधे तौर पर निर्भर नहीं करता.
सिंगल-वर्शन ओवरराइड
The single_version_override
कई मकसद पूरे करता है:
versionएट्रिब्यूट की मदद से, किसी डिपेंडेंसी को किसी खास वर्शन पर पिन किया जा सकता है. भले ही, डिपेंडेंसी ग्राफ़ में डिपेंडेंसी के कौनसे वर्शन का अनुरोध किया गया हो.registryएट्रिब्यूट की मदद से, इस डिपेंडेंसी को सामान्य रजिस्ट्री चुनने की प्रोसेस के बजाय, किसी खास रजिस्ट्री से लाने के लिए मजबूर किया जा सकता है.patch*एट्रिब्यूट की मदद से, डाउनलोड किए गए मॉड्यूल पर लागू करने के लिए, पैच का सेट तय किया जा सकता है.
ये सभी एट्रिब्यूट ज़रूरी नहीं हैं. इन्हें आपस में मिलाकर इस्तेमाल किया जा सकता है.
मल्टीपल-वर्शन ओवरराइड
रिज़ॉल्व किए गए डिपेंडेंसी ग्राफ़ में, एक ही मॉड्यूल के कई वर्शन को एक साथ मौजूद रहने की अनुमति देने के लिए, एक multiple_version_override
तय किया जा सकता है.
अगर डिपेंडेंसी ग्राफ़ में एक ही मॉड्यूल के कई वर्शन मौजूद हैं, तो Bazel, हर डिपेंडेंट के लिए, अनुमति वाले सबसे नए वर्शन को चुनेगा.
उदाहरण के लिए, अगर रिज़ॉल्यूशन से पहले, डिपेंडेंसी ग्राफ़ में वर्शन 1.1, 1.3, 1.5, 1.7, और 2.0 मौजूद हैं:
- मल्टीपल-वर्शन ओवरराइड की मदद से,
1.3,1.7, और2.0की अनुमति देने पर,1.1को1.3पर,1.5को1.7पर अपग्रेड किया जाएगा. साथ ही, अन्य वर्शन में कोई बदलाव नहीं होगा. - मल्टीपल-वर्शन ओवरराइड की मदद से,
1.9और2.0की अनुमति देने पर, एक गड़बड़ी होगी. ऐसा इसलिए, क्योंकि रिज़ॉल्यूशन से पहले, डिपेंडेंसी ग्राफ़ में1.9मौजूद नहीं है.
इसके अलावा, उपयोगकर्ता registry एट्रिब्यूट का इस्तेमाल करके, रजिस्ट्री को भी ओवरराइड कर सकते हैं. यह सुविधा, सिंगल-वर्शन ओवरराइड की तरह ही काम करती है.
नॉन-रजिस्ट्री ओवरराइड
नॉन-रजिस्ट्री ओवरराइड की मदद से, किसी मॉड्यूल को वर्शन रिज़ॉल्यूशन से पूरी तरह हटाया जा सकता है. Bazel, रजिस्ट्री से इन MODULE.bazel फ़ाइलों का अनुरोध नहीं करता. इसके बजाय, वह रेपो से ही इनका अनुरोध करता है.
Bazel, नॉन-रजिस्ट्री ओवरराइड के इन टाइप के साथ काम करता है:
ध्यान दें कि सोर्स आर्काइव MODULE.bazel में वर्शन की वैल्यू सेट करने से, कुछ समस्याएं हो सकती हैं. ऐसा तब होता है, जब मॉड्यूल को नॉन-रजिस्ट्री ओवरराइड से ओवरराइड किया जा रहा हो. इस बारे में ज़्यादा जानने के लिए, अक्सर पूछे जाने वाले सवाल देखें.MODULE.bazel
ऐसे रेपो तय करना जो Bazel मॉड्यूल नहीं हैं
bazel_dep की मदद से, ऐसे रेपो तय किए जा सकते हैं जो अन्य Bazel मॉड्यूल को दिखाते हैं.
कभी-कभी, ऐसा रेपो तय करने की ज़रूरत होती है जो Bazel मॉड्यूल नहीं होता. उदाहरण के लिए, ऐसा रेपो जिसमें डेटा के तौर पर पढ़ी जाने वाली सामान्य JSON फ़ाइल होती है.
ऐसे में, रेपो नियम को लागू करके, सीधे तौर पर रेपो तय करने के लिए, use_repo_rule
डायरेक्टिव का इस्तेमाल किया जा सकता है. यह रेपो, सिर्फ़ उस मॉड्यूल को दिखेगा जिसमें इसे तय किया गया है.
बैकग्राउंड में, इसे मॉड्यूल एक्सटेंशन वाले उसी मैकेनिज़्म का इस्तेमाल करके लागू किया जाता है. इससे, ज़्यादा फ़्लेक्सिबिलिटी के साथ रेपो तय किए जा सकते हैं.
रिपॉज़िटरी के नाम और स्ट्रिक्ट डिप्स
किसी मॉड्यूल को बैकअप देने वाले रेपो का ज़ाहिर नाम, सीधे तौर पर निर्भर रहने वाले मॉड्यूल के लिए डिफ़ॉल्ट तौर पर उसके मॉड्यूल का नाम होता है. हालांकि, ऐसा तब होता है, जब repo_name एट्रिब्यूट के bazel_dep डायरेक्टिव में कोई दूसरा नाम न दिया गया हो. ध्यान दें कि इसका मतलब है कि कोई मॉड्यूल, सीधे तौर पर निर्भर रहने वाले मॉड्यूल को ही ढूंढ सकता है. इससे, ट्रांज़िटिव डिपेंडेंसी में होने वाले बदलावों की वजह से, अनजाने में होने वाली गड़बड़ियों से बचा जा सकता है.
किसी मॉड्यूल को बैकअप देने वाले रेपो का कैननिकल नाम, module_name+version (उदाहरण के लिए, bazel_skylib+1.0.3) या module_name+ (उदाहरण के लिए, bazel_features+) होता है. यह इस बात पर निर्भर करता है कि पूरे डिपेंडेंसी ग्राफ़ में मॉड्यूल के कई वर्शन हैं या नहीं (देखें multiple_version_override). ध्यान दें कि कैननिकल नाम का फ़ॉर्मैट कोई ऐसा एपीआई नहीं है जिस पर आपको निर्भर रहना चाहिए. साथ ही, इसमें कभी भी बदलाव किया जा सकता है. कैननिकल नाम को हार्ड-कोड करने के बजाय, इसे सीधे Bazel से पाने के लिए, किसी ऐसे तरीके का इस्तेमाल करें जो काम करता हो:
- BUILD और
.bzlफ़ाइलों में, रेपो के नाम से बनाए गए लेबल स्ट्रिंग से बनाए गएLabelइंस्टेंस परLabel.repo_nameका इस्तेमाल करें. जैसे,Label("@bazel_skylib").repo_name. - रनफ़ाइल ढूंढते समय,
$(rlocationpath ...)या@bazel_tools//tools/{bash,cpp,java}/runfilesमें रनफ़ाइल लाइब्रेरी में से किसी एक का इस्तेमाल करें. इसके अलावा, नियमसेटrules_fooके लिए,@rules_foo//foo/runfilesमें इसका इस्तेमाल करें. - Bazel के साथ इंटरैक्ट करते समय, किसी बाहरी टूल का इस्तेमाल करें. जैसे, आईडीई या लैंग्वेज
सर्वर. इसके लिए, दिए गए रिपॉज़िटरी के सेट के लिए, नामों से कैननिकल नामों की मैपिंग पाने के लिए,
bazel mod dump_repo_mappingकमांड का इस्तेमाल करें.
मॉड्यूल एक्सटेंशन की मदद से, किसी मॉड्यूल के दिखने वाले स्कोप में अतिरिक्त रेपो भी जोड़े जा सकते हैं.