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