Bazel, एक्सटर्नल डिपेंडेंसी, सोर्स फ़ाइलों (टेक्स्ट और बाइनरी, दोनों) के साथ काम करता है. इनका इस्तेमाल आपके बिल्ड में किया जाता है. ये फ़ाइलें, आपके वर्कस्पेस से नहीं होती हैं. उदाहरण के लिए, ये GitHub रिपॉज़िटरी में होस्ट किया गया नियमों का सेट, Maven आर्टफ़ैक्ट या आपके मौजूदा वर्कस्पेस के बाहर, आपकी लोकल मशीन पर मौजूद कोई डायरेक्ट्री हो सकती हैं.
Bazel 6.0 से, Bazel के साथ एक्सटर्नल डिपेंडेंसी मैनेज करने के दो तरीके हैं:
पहला, रिपॉज़िटरी पर फ़ोकस करने वाला पुराना WORKSPACE सिस्टम और
दूसरा, मॉड्यूल पर फ़ोकस करने वाला नया MODULE.bazel सिस्टम. इसे Bzlmod कोडनेम दिया गया है.
इसे --enable_bzlmod फ़्लैग की मदद से चालू किया जा सकता है. इन दोनों सिस्टम का इस्तेमाल एक साथ किया जा सकता है.
हालांकि, Bazel के आने वाले वर्शन में, WORKSPACE सिस्टम की जगह Bzlmod का इस्तेमाल किया जाएगा. माइग्रेट करने का तरीका जानने के लिए, Bzlmod माइग्रेशन गाइड देखें.
इस दस्तावेज़ में, Bazel में एक्सटर्नल डिपेंडेंसी मैनेजमेंट से जुड़े कॉन्सेप्ट के बारे में बताया गया है. इसके बाद, दोनों सिस्टम के बारे में ज़्यादा जानकारी दी गई है.
कॉन्सेप्ट
रिपॉज़िटरी
यह डायरेक्ट्री ट्री होती है. इसकी रूट डायरेक्ट्री में, बाउंड्री मार्कर फ़ाइल होती है. इसमें सोर्स फ़ाइलें होती हैं, जिनका इस्तेमाल Bazel बिल्ड में किया जा सकता है. इसे अक्सर सिर्फ़ रिपो कहा जाता है.
रिपो बाउंड्री मार्कर फ़ाइल, MODULE.bazel (इससे पता चलता है कि यह रिपो
Bazel मॉड्यूल को दिखाता है), REPO.bazel (नीचे देखें) या पुराने
कॉन्टेक्स्ट में, WORKSPACE या WORKSPACE.bazel हो सकती है. कोई भी रिपो बाउंड्री मार्कर फ़ाइल, रिपो की बाउंड्री को दिखाएगी. एक डायरेक्ट्री में, ऐसी कई फ़ाइलें मौजूद हो सकती हैं.
मुख्य रिपॉज़िटरी
वह रिपॉज़िटरी जिसमें Bazel का मौजूदा कमांड चलाया जा रहा है.
Workspace
यह वह एनवायरमेंट है जिसे एक ही मुख्य रिपॉज़िटरी में चलाए गए Bazel के सभी कमांड शेयर करते हैं.
ध्यान दें कि पहले "रिपॉज़िटरी" और "वर्कस्पेस" के कॉन्सेप्ट को एक ही माना जाता था. "वर्कस्पेस" शब्द का इस्तेमाल अक्सर मुख्य रिपॉज़िटरी के लिए किया जाता था. कभी-कभी इसे "रिपॉज़िटरी" के सिननिम के तौर पर भी इस्तेमाल किया जाता था.
कैननिकल रिपॉज़िटरी का नाम
वह कैननिकल नाम जिससे किसी रिपॉज़िटरी को ऐक्सेस किया जा सकता है. किसी वर्कस्पेस के कॉन्टेक्स्ट में, हर रिपॉज़िटरी का एक कैननिकल नाम होता है. किसी रिपो में मौजूद टारगेट
जिसका कैननिकल नाम canonical_name है, उसे
@@canonical_name//pac/kage:target लेबल से ऐक्सेस किया जा सकता है. ध्यान दें कि इसमें दो बार @ का इस्तेमाल किया गया है.
मुख्य रिपॉज़िटरी का कैननिकल नाम हमेशा खाली स्ट्रिंग होता है.
रिपॉज़िटरी का नाम
वह नाम जिससे किसी दूसरी रिपो के कॉन्टेक्स्ट में, किसी रिपॉज़िटरी को ऐक्सेस किया जा सकता है.
इसे किसी रिपो का "निकनेम" माना जा सकता है: alice रिपो के कॉन्टेक्स्ट में, michael कैननिकल नाम वाली रिपो का नाम mike हो सकता है. वहीं, bob रिपो के कॉन्टेक्स्ट में, इसका नाम mickey हो सकता है. इस मामले में, alice के कॉन्टेक्स्ट में, michael में मौजूद टारगेट को लेबल
@mike//pac/kage:target से ऐक्सेस किया जा सकता है. ध्यान दें कि इसमें एक बार @ का इस्तेमाल किया गया है.
इसके उलट, इसे रिपॉज़िटरी मैपिंग के तौर पर समझा जा सकता है: हर रिपो "रिपो के नाम" से "कैननिकल रिपो के नाम" तक की मैपिंग बनाए रखती है.
रिपॉज़िटरी का नियम
यह रिपॉज़िटरी की डेफ़िनिशन का स्कीमा है. इससे Bazel को पता चलता है कि रिपॉज़िटरी को कैसे तैयार किया जाए. उदाहरण के लिए, यह "किसी यूआरएल से zip संग्रह डाउनलोड करें और उसे एक्सट्रैक्ट करें" या "किसी Maven आर्टफ़ैक्ट को फ़ेच करें और उसे java_import टारगेट के तौर पर उपलब्ध कराएं" या सिर्फ़ "किसी लोकल डायरेक्ट्री को सिमलंक करें" हो सकता है. हर रिपो को, सही संख्या में आर्ग्युमेंट के साथ रिपो के नियम को कॉल करके तय किया जाता है.
अपनी रिपॉज़िटरी के नियम लिखने के तरीके के बारे में ज़्यादा जानने के लिए, रिपॉज़िटरी के नियम देखें.
सबसे आम रिपो के नियम,
http_archive और
local_repository हैं.
http_archive नियम, किसी यूआरएल से संग्रह डाउनलोड करता है और उसे एक्सट्रैक्ट करता है. वहीं,
local_repository नियम, किसी लोकल डायरेक्ट्री को सिमलंक करता है. यह डायरेक्ट्री, पहले से ही Bazel रिपॉज़िटरी होती है.
रिपॉज़िटरी को फ़ेच करना
रिपो के नियम को चलाकर, किसी रिपो को लोकल डिस्क पर उपलब्ध कराना. किसी वर्कस्पेस में तय की गई रिपो, फ़ेच किए जाने से पहले लोकल डिस्क पर उपलब्ध नहीं होती हैं.
आम तौर पर, Bazel किसी रिपो को सिर्फ़ तब फ़ेच करता है, जब उसे रिपो से किसी चीज़ की ज़रूरत होती है और रिपो को पहले से फ़ेच नहीं किया गया होता है. अगर रिपो को पहले से फ़ेच किया गया है, तो Bazel उसे सिर्फ़ तब फिर से फ़ेच करता है, जब उसकी डेफ़िनिशन में बदलाव किया गया हो.
fetch कमांड का इस्तेमाल करके, किसी रिपॉज़िटरी, टारगेट या किसी भी बिल्ड को पूरा करने के लिए ज़रूरी सभी रिपॉज़िटरी को पहले से फ़ेच किया जा सकता है. इस सुविधा की मदद से, --nofetch विकल्प का इस्तेमाल करके ऑफ़लाइन बिल्ड किए जा सकते हैं.
--fetch विकल्प का इस्तेमाल, नेटवर्क ऐक्सेस को मैनेज करने के लिए किया जाता है. इसकी डिफ़ॉल्ट वैल्यू, 'सही' होती है.
हालांकि, इसे 'गलत' (--nofetch) पर सेट करने पर, कमांड डिपेंडेंसी के कैश किए गए किसी भी वर्शन का इस्तेमाल करेगा. अगर कोई वर्शन मौजूद नहीं है, तो कमांड फ़ेल हो जाएगा.
फ़ेच करने की सुविधा को कंट्रोल करने के बारे में ज़्यादा जानने के लिए, फ़ेच करने के विकल्प देखें.
डायरेक्ट्री का लेआउट
canonical_name कैननिकल नाम वाली रिपो का कॉन्टेंट देखने के लिए, यह कमांड चलाएं:
ls $(bazel info output_base)/external/ canonical_name REPO.bazel फ़ाइल
REPO.bazel फ़ाइल का इस्तेमाल, डायरेक्ट्री ट्री की सबसे ऊपरी बाउंड्री को मार्क करने के लिए किया जाता है. यह डायरेक्ट्री ट्री, रिपो बनाती है. रिपो बाउंड्री फ़ाइल के तौर पर काम करने के लिए, इसमें कुछ भी शामिल करने की ज़रूरत नहीं होती. हालांकि, इसका इस्तेमाल रिपो में मौजूद सभी बिल्ड टारगेट के लिए, कुछ सामान्य एट्रिब्यूट तय करने के लिए भी किया जा सकता है.
REPO.bazel फ़ाइल का सिंटैक्स, BUILD फ़ाइलों जैसा होता है. हालांकि, इसमें load स्टेटमेंट काम नहीं करते. साथ ही, इसमें सिर्फ़ एक फ़ंक्शन, repo() उपलब्ध होता है. repo() फ़ंक्शन, BUILD फ़ाइलों में package()
फ़ंक्शन के जैसे ही आर्ग्युमेंट लेता है. package()
फ़ंक्शन, पैकेज में मौजूद सभी बिल्ड टारगेट के लिए सामान्य एट्रिब्यूट तय करता है. इसी तरह, repo()
फ़ंक्शन, रिपो में मौजूद सभी बिल्ड टारगेट के लिए सामान्य एट्रिब्यूट तय करता है.
उदाहरण के लिए, अपनी रिपो में मौजूद सभी टारगेट के लिए, एक सामान्य लाइसेंस तय किया जा सकता है. इसके लिए, REPO.bazel फ़ाइल में यह जानकारी शामिल करें:
repo(
default_package_metadata = ["//:my_license"],
)
Bzlmod की मदद से, एक्सटर्नल डिपेंडेंसी मैनेज करना
एक्सटर्नल डिपेंडेंसी का नया सबसिस्टम, Bzlmod, रिपो की डेफ़िनिशन के साथ सीधे काम नहीं करता. इसके बजाय, यह मॉड्यूल से डिपेंडेंसी ग्राफ़ बनाता है. इसके बाद, ग्राफ़ पर एक्सटेंशन चलाता है और इसके मुताबिक, रिपो तय करता है.
एक Bazel मॉड्यूल, Bazel का एक ऐसा प्रोजेक्ट है जिसके कई
वर्शन हो सकते हैं. इनमें से हर वर्शन, उन अन्य मॉड्यूल के बारे में मेटाडेटा पब्लिश करता है जिन पर वह निर्भर
करता है. किसी मॉड्यूल की रिपो रूट में, WORKSPACE फ़ाइल के बगल में, 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")
किसी मॉड्यूल को सिर्फ़ अपनी डायरेक्ट डिपेंडेंसी की सूची बनानी चाहिए. Bzlmod, Bazel रजिस्ट्री में इनकी जानकारी ढूंढता है. डिफ़ॉल्ट रूप से, यह Bazel Central
Registry होती है. रजिस्ट्री, डिपेंडेंसी की MODULE.bazel फ़ाइलें उपलब्ध कराती है. इससे Bazel को वर्शन रिज़ॉल्यूशन करने से पहले, ट्रांज़िटिव डिपेंडेंसी का पूरा ग्राफ़ ढूंढने में मदद मिलती है.
वर्शन रिज़ॉल्यूशन के बाद, जिसमें हर मॉड्यूल के लिए एक वर्शन चुना जाता है, Bazel रजिस्ट्री से फिर से संपर्क करता है, ताकि उसे हर मॉड्यूल के लिए रिपो तय करने का तरीका पता चल सके. ज़्यादातर मामलों में, यह http_archive का इस्तेमाल करके किया जाता है.
मॉड्यूल, टैग नाम का डेटा भी तय कर सकते हैं. इनका इस्तेमाल, मॉड्यूल रिज़ॉल्यूशन के बाद मॉड्यूल एक्सटेंशन करते हैं, ताकि अतिरिक्त रिपो तय की जा सकें. इन एक्सटेंशन में, रिपो के नियमों जैसी ही क्षमताएं होती हैं. इससे वे फ़ाइल I/O और नेटवर्क अनुरोध भेजने जैसी कार्रवाइयां कर सकते हैं. इनकी मदद से, Bazel, पैकेज मैनेजमेंट के अन्य सिस्टम के साथ इंटरैक्ट कर सकता है. साथ ही, यह Bazel मॉड्यूल से बने डिपेंडेंसी ग्राफ़ का भी पालन करता है.
Bzlmod पर बाहरी लिंक
- bazelbuild/examples में, Bzlmod के इस्तेमाल के उदाहरण
- Bazel की एक्सटर्नल डिपेंडेंसी में बदलाव (Bzlmod के डिज़ाइन का ओरिजनल दस्तावेज़)
- Bzlmod पर BazelCon 2021 की बातचीत
- Bzlmod पर Bazel कम्यूनिटी डे की बातचीत
WORKSPACE की मदद से रिपो तय करना
पहले,
WORKSPACE (या WORKSPACE.bazel) फ़ाइल में रिपो तय करके, एक्सटर्नल डिपेंडेंसी मैनेज की जा सकती थीं. इस फ़ाइल का सिंटैक्स, BUILD फ़ाइलों जैसा होता है. इसमें बिल्ड के नियमों के बजाय, रिपो के नियमों का इस्तेमाल किया जाता है.
WORKSPACE फ़ाइल में, http_archive रिपो के नियम का इस्तेमाल करने का उदाहरण यहां दिया गया है:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "foo",
urls = ["https://example.com/foo.zip"],
sha256 = "c9526390a7cd420fdcec2988b4f3626fe9c5b51e2959f685e8f4d170d1a9bd96",
)
इस स्निपेट में, foo कैननिकल नाम वाली रिपो तय की गई है. WORKSPACE सिस्टम में, डिफ़ॉल्ट रूप से, किसी रिपो का कैननिकल नाम, अन्य सभी रिपो के लिए उसका नाम भी होता है.
फ़ंक्शन की पूरी सूची देखें जो
WORKSPACE फ़ाइलों में उपलब्ध हैं.
WORKSPACE सिस्टम की कमियां
WORKSPACE सिस्टम को लॉन्च किए जाने के बाद से, उपयोगकर्ताओं ने कई समस्याएं बताई हैं. इनमें ये शामिल हैं:
- Bazel, किसी भी डिपेंडेंसी की
WORKSPACEफ़ाइलों का आकलन नहीं करता. इसलिए, डायरेक्ट डिपेंडेंसी के अलावा, सभी ट्रांज़िटिव डिपेंडेंसी को मुख्य रिपो कीWORKSPACEफ़ाइल में तय करना होगा. - इससे बचने के लिए, प्रोजेक्ट ने "deps.bzl" पैटर्न अपनाया है. इसमें वे एक मैक्रो तय करते हैं. यह मैक्रो, कई रिपो तय करता है. साथ ही, उपयोगकर्ताओं से अपनी
WORKSPACEफ़ाइलों में इस मैक्रो को कॉल करने के लिए कहा जाता है.- इसकी अपनी समस्याएं हैं: मैक्रो, अन्य
.bzlफ़ाइलों कोloadनहीं कर सकते. इसलिए, इन प्रोजेक्ट को अपनी ट्रांज़िटिव डिपेंडेंसी को इस "deps" मैक्रो में तय करना होगा. इसके अलावा, इस समस्या से बचने के लिए, उपयोगकर्ता को कई लेयर वाले "deps" मैक्रो को कॉल करना होगा. - Bazel,
WORKSPACEफ़ाइल का आकलन क्रम से करता है. इसके अलावा, डिपेंडेंसी को यूआरएल के साथhttp_archiveका इस्तेमाल करके तय किया जाता है. इसमें वर्शन की कोई जानकारी नहीं होती. इसका मतलब है कि डायमंड डिपेंडेंसी (A,BऔरCपर निर्भर करता है.BऔरC, दोनोंDके अलग-अलग वर्शन पर निर्भर करते हैं) के मामले में, वर्शन रिज़ॉल्यूशन करने का कोई भरोसेमंद तरीका नहीं है.
- इसकी अपनी समस्याएं हैं: मैक्रो, अन्य
WORKSPACE की कमियों की वजह से, Bazel के आने वाले वर्शन में, पुराने WORKSPACE सिस्टम की जगह Bzlmod का इस्तेमाल किया जाएगा. Bzlmod पर माइग्रेट करने का तरीका जानने के लिए, कृपया Bzlmod माइग्रेशन गाइड पढ़ें.