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 का मौजूदा कमांड चलाया जा रहा है.
वर्कस्पेस
यह वह एनवायरमेंट है जिसे एक ही मुख्य रिपॉज़िटरी में चलाए गए Bazel के सभी कमांड शेयर करते हैं.
ध्यान दें कि पहले "रिपॉज़िटरी" और "वर्कस्पेस" के कॉन्सेप्ट को एक ही माना जाता था. "वर्कस्पेस" शब्द का इस्तेमाल अक्सर मुख्य रिपॉज़िटरी के लिए किया जाता था. कभी-कभी इसे "रिपॉज़िटरी" के सिननिम के तौर पर भी इस्तेमाल किया जाता था.
कैननिकल रिपॉज़िटरी का नाम
वह कैननिकल नाम जिससे किसी रिपॉज़िटरी को ऐक्सेस किया जा सकता है. किसी वर्कस्पेस के कॉन्टेक्स्ट में, हर रिपॉज़िटरी का एक ही कैननिकल नाम होता है. किसी रिपो में मौजूद टारगेट को
जिसका कैननिकल नाम canonical_name है, लेबल
@@canonical_name//pac/kage:target से ऐक्सेस किया जा सकता है. ध्यान दें कि इसमें दो बार @ का इस्तेमाल किया गया है.
मुख्य रिपॉज़िटरी का कैननिकल नाम हमेशा खाली स्ट्रिंग होता है.
रिपॉज़िटरी का नाम
वह नाम जिससे किसी दूसरी रिपो के कॉन्टेक्स्ट में, किसी रिपॉज़िटरी को ऐक्सेस किया जा सकता है.
इसे किसी रिपो का "निकनेम" माना जा सकता है: michael कैननिकल नाम वाली रिपो का नाम, alice रिपो के कॉन्टेक्स्ट में mike हो सकता है. वहीं, bob रिपो के कॉन्टेक्स्ट में इसका नाम mickey हो सकता है. इस मामले में, michael में मौजूद टारगेट को, लेबल
@mike//pac/kage:target से alice के कॉन्टेक्स्ट में ऐक्सेस किया जा सकता है. ध्यान दें कि इसमें एक बार @ का इस्तेमाल किया गया है.
इसके उलट, इसे रिपॉज़िटरी मैपिंग के तौर पर समझा जा सकता है: हर रिपो "रिपो के नाम" से "कैननिकल रिपो के नाम" तक की मैपिंग बनाए रखती है.
रिपॉज़िटरी का नियम
यह रिपॉज़िटरी की डेफ़िनिशन के लिए स्कीमा है. इससे 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()
रिपो में मौजूद सभी बिल्ड टारगेट के लिए ऐसा ही करता है.BUILD
उदाहरण के लिए, अपनी रिपो में मौजूद सभी टारगेट के लिए सामान्य लाइसेंस तय करने के लिए, 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 माइग्रेशन गाइड पढ़ें.