Bazel का मॉड्यूल एक ऐसा Bazel प्रोजेक्ट हो सकता है जिसके कई वर्शन हो सकते हैं. इनमें से हर प्रोजेक्ट उन मॉड्यूल के बारे में मेटाडेटा पब्लिश करता है जिन पर निर्भर होता है. यह अन्य डिपेंडेंसी मैनेजमेंट सिस्टम में काम करने वाले सिद्धांतों के जैसा ही है, जैसे कि एक Maven आर्टफ़ैक्ट, NPM पैकेज, एक Go मॉड्यूल या एक कार्गो क्रेट.
मॉड्यूल की रिपो रूट में एक फ़ाइल MODULE.bazel
होनी चाहिए, जो WORKSPACE
फ़ाइल के बगल में होनी चाहिए. इस फ़ाइल के मॉड्यूल का मेनिफ़ेस्ट, उसके नाम, वर्शन, डायरेक्ट डिपेंडेंसी की सूची, और दूसरी जानकारी बताता है. बुनियादी उदाहरण के लिए:
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 इस्तेमाल करने के लिए हर मॉड्यूल के एक वर्शन को चुनें. बैज़ल, रेपो के साथ हर मॉड्यूल को दिखाता है और रजिस्ट्री में फिर से राय देता है. इससे यह पता चलता है कि हर रेपो को कैसे परिभाषित किया जाए.
वर्शन फ़ॉर्मैट
बेज़ल में अलग-अलग तरह का इकोसिस्टम है. यहां अलग-अलग वर्शन वाली स्कीम का इस्तेमाल किया जाता है. SemVer अब तक का सबसे लोकप्रिय प्रोजेक्ट है. हालांकि, Abseil जैसी अलग-अलग स्कीम का भी इस्तेमाल किया जाता है, जिनके वर्शन तारीख पर आधारित होते हैं. उदाहरण के लिए, 20210324.2
).
इस वजह से, Bzlmod ने SemVer स्पेसिफ़िकेशन का ज़्यादा आरामदेह वर्शन अपनाया, जिसमें अंतर है:
- SemVer बताता है कि वर्शन के "रिलीज़" हिस्से में तीन सेगमेंट होने चाहिए:
MAJOR.MINOR.PATCH
. बेज़ल में, यह ज़रूरत ढीली हो गई है, ताकि जितने चाहें उतने सेगमेंट की अनुमति हो. - SemVer में, "रिलीज़" वाले हर सेगमेंट में सिर्फ़ अंक होने चाहिए. बेज़ल में, अक्षरों को भी अनुमति देने के लिए इसे ढीला किया जाता है और तुलना का मतलब: मतलब होता है कि "प्रीरिलीज़" में "आइडेंटिफ़ायर" होते हैं.
- इसके अलावा, मेजर, मामूली, और पैच वर्शन के सिमेंटिक को लागू नहीं किया जाता. पुराने सिस्टम के साथ काम करने की सुविधा के बारे में जानकारी के लिए, कम्पैटबिलटी लेवल देखें.
SemVer का कोई भी मान्य वर्शन एक मान्य Bazel मॉड्यूल वर्शन है. इसके अलावा, दो
SemVer वर्शन a
और b
a < b
की तुलना करें. ऐसा सिर्फ़ तब करें, जब बेज़ल मॉड्यूल वर्शन के साथ तुलना करने पर भी वही हों.
वर्शन चुनना
हीरे की निर्भरता की समस्या पर विचार करें, जो वर्शन और डिपेंडेंसी मैनेजमेंट स्पेस का मुख्य हिस्सा है. मान लें कि आपके पास डिपेंडेंसी ग्राफ़ है:
A 1.0
/ \
B 1.0 C 1.1
| |
D 1.0 D 1.1
D
का कौनसा वर्शन इस्तेमाल करना चाहिए? इस सवाल का जवाब देने के लिए, Bzlmod
मिनिमल वर्शन सिलेक्शन
(MVS) एल्गोरिदम का इस्तेमाल करता है. यह एल्गोरिदम, Go मॉड्यूल सिस्टम में उपलब्ध कराया गया है. MVS को यह माना जाता है कि किसी मॉड्यूल के सभी नए वर्शन, पुराने सिस्टम के साथ काम करते हैं. इसलिए, वह हमारे उदाहरण में मौजूद डिपेंडेंसी के लिए तय किए गए सबसे अच्छे वर्शन (D 1.1
को चुनता है. इसे "मिनिमल" कहा जाता है, क्योंकि D 1.1
सबसे जल्दी का वर्शन होता है जो हमारी ज़रूरी शर्तों को पूरा कर सकता है. भले ही, D 1.2
या उसके बाद का वर्शन मौजूद हो, हम उन्हें नहीं चुनते. एमवीएस का इस्तेमाल करने पर, वर्शन चुनने की प्रोसेस शुरू होती है. यह प्रोसेस हाई फ़िडेलिटी और रीप्रॉड्यूसिबल होती है.
डॉक किए गए वर्शन
अगर रजिस्ट्री से बचना चाहिए, तो रजिस्ट्री कुछ वर्शन के बारे में अहम जानकारी दे सकती है
(जैसे, सुरक्षा से जुड़े जोखिमों के मामले में). अगर बेज़ल किसी मॉड्यूल का येंकेड वर्शन चुनता है, तो गड़बड़ी होती है. इस गड़बड़ी को ठीक करने के लिए, या तो किसी नए याक किए गए वर्शन में अपग्रेड करें या इस जानकारी वाले दस्तावेज़ को साफ़ तौर पर अनुमति देने के लिए, --allow_yanked_versions
फ़्लैग का इस्तेमाल करें.
कंपैटिबिलिटी लेवल
Go {0}SemVer के संदर्भ में, इसका मतलब है कि A 1.x
और A 2.x
को अलग-अलग मॉड्यूल माना जाता है और समाधान किए गए डिपेंडेंसी ग्राफ़ में, ये मौजूद हो सकते हैं. ऐसे में, Go में पैकेज पाथ के मेजर वर्शन को कोड में बदलकर ऐसा किया जा सकता है. इसलिए, कंपाइल करने या लिंक करने के समय से जुड़ी कोई गड़बड़ी नहीं होती.
हालांकि, Bazel ऐसी कोई गारंटी नहीं दे सकता. इसलिए, पुराने सिस्टम के साथ काम न करने वाले वर्शन का पता लगाने के लिए, इसे "खास वर्शन" वाले नंबर की ज़रूरत होती है. इस संख्या को कम्पैटबिलटी लेवल कहा जाता है और यह हर मॉड्यूल वर्शन के module()
डायरेक्टिव में बताया जाता है. इस जानकारी के साथ, Bazel एक गड़बड़ी का पता लगा सकता है जब उसे पता चलता है कि अलग-अलग कम्पैटबिलटी लेवल वाले एक ही मॉड्यूल के वर्शन, ठीक किए गए डिपेंडेंसी ग्राफ़ में मौजूद हैं.
बदली गई कीमत
Bazel मॉड्यूल रिज़ॉल्यूशन के काम करने के तरीके को बदलने के लिए, MODULE.bazel
फ़ाइल में बदलाव करें. सिर्फ़ रूट मॉड्यूल के ओवरराइड लागू होते हैं — अगर किसी मॉड्यूल का इस्तेमाल डिपेंडेंसी के तौर पर किया जाता है, तो उसके ओवरराइड को अनदेखा कर दिया जाता है.
हर बदलाव को किसी खास मॉड्यूल नाम के लिए बताया जाता है, जिससे डिपेंडेंसी ग्राफ़ में उसके सभी वर्शन पर असर पड़ता है. हालांकि, सिर्फ़ रूट मॉड्यूल के ओवरराइड ही असर डालते हैं, लेकिन ये ऐसी ट्रांज़िटिव डिपेंडेंसी के लिए हो सकते हैं जो रूट मॉड्यूल पर सीधे तौर पर निर्भर नहीं हैं.
सिंगल-वर्शन ओवरराइड
single_version_override
कई मकसद से काम करता है:
version
एट्रिब्यूट के साथ, आप किसी खास वर्शन पर डिपेंडेंसी पिन कर सकते हैं. भले ही, डिपेंडेंसी ग्राफ़ में डिपेंडेंसी के कौनसे वर्शन मांगे गए हों.registry
एट्रिब्यूट का इस्तेमाल करके, आप इस डिपेंडेंसी को किसी सामान्य रजिस्ट्री से आने के लिए मजबूर कर सकते हैं. यह सामान्य रजिस्ट्री चुनने की प्रक्रिया के बजाय होगी.patch*
एट्रिब्यूट की मदद से, डाउनलोड किए गए मॉड्यूल पर लागू करने के लिए पैच का सेट तय किया जा सकता है.
ये सभी एट्रिब्यूट ज़रूरी नहीं हैं और इन्हें एक-दूसरे के साथ मिलाकर भी इस्तेमाल किया जा सकता है.
कई वर्शन को ओवरराइड करना
multiple_version_override
को इस तरह तय किया जा सकता है कि एक ही मॉड्यूल के एक से ज़्यादा वर्शन, समाधान किए गए डिपेंडेंसी ग्राफ़ में मौजूद रहें.
आप मॉड्यूल के लिए ऐसे वर्शन की साफ़ तौर पर सूची दे सकते हैं जिन्हें अनुमति मिली हुई है. ये सभी रिज़ॉल्यूशन से पहले, डिपेंडेंसी ग्राफ़ में मौजूद होने चाहिए. अनुमति पा चुके हर वर्शन के आधार पर ट्रांज़िट समय वाली कुछ कुछ चीज़ें होनी चाहिए. रिज़ॉल्यूशन के बाद, मॉड्यूल के सिर्फ़ अनुमति वाले वर्शन बने रहते हैं, जबकि Bazel, मॉड्यूल के दूसरे वर्शन को भी साथ में काम करने वाले वर्शन के हिसाब से अपग्रेड करता है. अगर उसी वर्शन में कोई और वर्शन काम नहीं करता है, तो Bzel एक गड़बड़ी दिखाता है.
उदाहरण के लिए, अगर 1.1
, 1.3
, 1.5
, 1.7
, और 2.0
वर्शन, डिपेंडेंसी ग्राफ़ में डिपेंडेंसी से पहले मौजूद हैं, लेकिन मेजर वर्शन कम्पैटबिलटी लेवल वाला है:
- कई वर्शन वाले बदलाव की वजह से
1.3
,1.7
, और2.0
नतीजों को1.1
में अपग्रेड किया जा रहा है. साथ ही,1.5
को1.7
में अपग्रेड किया जा रहा है और दूसरे वर्शन में कोई बदलाव नहीं किया गया है.1.3
- कई वर्शन वाले वर्शन में बदलाव करने की वजह से
1.5
और2.0
गड़बड़ी वाले पेज में बदल जाते हैं. इसकी वजह यह है कि1.7
में अपग्रेड करने के लिए एक ही वर्शन पर काम करने वाला कोई नया वर्शन नहीं है. - कई वर्शन वाले बदलाव की वजह से
1.9
और2.0
गड़बड़ी वाले पेज में बदल जाते हैं, क्योंकि रिज़ॉल्यूशन के पहले, डिपेंडेंसी ग्राफ़ में1.9
मौजूद नहीं होती.
इसके अलावा, उपयोगकर्ता सिंगल-वर्शन ओवरराइड की तरह ही registry
एट्रिब्यूट का इस्तेमाल करके रजिस्ट्री को ओवरराइड कर सकते हैं.
गैर-रजिस्ट्री ओवरराइड
गैर-रजिस्ट्री ओवरराइड, वर्शन रिज़ॉल्यूशन से मॉड्यूल को पूरी तरह से हटा देते हैं. Bazel,
रजिस्ट्री से MODULE.bazel
फ़ाइलों का अनुरोध नहीं करता, बल्कि रेपो से
अनुरोध करता है.
Baकर, इन गैर-रजिस्ट्री ओवरराइड पर काम करता है:
रिपॉज़िटरी के नाम और पूरी जानकारी
किसी मॉड्यूल के लिए बैक अप लेने के तरीके का कैननिकल नाम module_name~version
है (उदाहरण के लिए, bazel_skylib~1.0.3
). ऐसे मॉड्यूल के लिए जो स्ट्रिंग में बदलाव नहीं किए गए हैं, उन्हें version
स्ट्रिंग से बदल दें override
. ध्यान दें कि कैननिकल नाम का फ़ॉर्मैट एक एपीआई नहीं है. आपको इस पर निर्भर रहना चाहिए और इसमें कभी भी बदलाव किया जा सकता है.
किसी मॉड्यूल को सीधे तौर पर निर्भर करने वाले किसी रेपो का साफ़ नाम डिफ़ॉल्ट रूप से उसके मॉड्यूल नाम पर सेट होता है. ऐसा तब तक होता है, जब तक bazel_dep
डायरेक्टिव का repo_name
एट्रिब्यूट कुछ और नहीं बताता. ध्यान दें कि मॉड्यूल सिर्फ़ अपनी डिपेंडेंसी ही ढूंढ सकता है. इससे ट्रांज़िशन करने पर निर्भरता घट सकती है.
मॉड्यूल एक्सटेंशन से मॉड्यूल के दिखने वाले दायरे में और डेटा भी मिल सकता है.