एक्सटर्नल डिपेंडेंसी के बारे में खास जानकारी

Bazel, बाहरी डिपेंडेंसी के साथ काम करता है. ये ऐसी सोर्स फ़ाइलें होती हैं (टेक्स्ट और बाइनरी, दोनों) जिनका इस्तेमाल आपके बिल्ड में किया जाता है और जो आपके फ़ाइल फ़ोल्डर में मौजूद नहीं होतीं. उदाहरण के लिए, यह GitHub repo में होस्ट किया गया कोई रूलसेट, Maven आर्टफ़ैक्ट या आपके मौजूदा वर्कस्पेस से बाहर की लोकल मशीन पर मौजूद कोई डायरेक्ट्री हो सकती है.

Bazel 6.0 के बाद, Bazel की मदद से बाहरी डिपेंडेंसी मैनेज करने के दो तरीके हैं: पहला, रिपॉज़िटरी पर फ़ोकस करने वाला पारंपरिक WORKSPACE सिस्टम और दूसरा, मॉड्यूल पर फ़ोकस करने वाला नया MODULE.bazel सिस्टम (इसका कोडनेम Bzlmod है और इसे फ़्लैग --enable_bzlmod की मदद से चालू किया जाता है). इन दोनों सिस्टम का एक साथ इस्तेमाल किया जा सकता है. हालांकि, Bazel के आने वाले रिलीज़ में Bzlmod, WORKSPACE सिस्टम की जगह ले लेगा. माइग्रेट करने का तरीका जानने के लिए, Bzlmod माइग्रेशन गाइड देखें.

यह दस्तावेज़, Baज़ल में एक्सटर्नल डिपेंडेंसी मैनेजमेंट से जुड़े सिद्धांतों के बारे में बताता है, ताकि दोनों सिस्टम के बारे में ज़्यादा जानकारी हासिल की जा सके.

कॉन्सेप्ट

रिपॉज़िटरी

WORKSPACE या WORKSPACE.bazel फ़ाइल वाली डायरेक्ट्री. इसमें ऐसी सोर्स फ़ाइलें शामिल होती हैं जिनका इस्तेमाल Basel बिल्ड में किया जाना है. इसे अक्सर repo के तौर पर छोटा किया जाता है.

मुख्य रिपॉज़िटरी

वह रिपॉज़िटरी, जिसमें मौजूदा बेज़ल कमांड चलाया जा रहा है.

Workspace

Bazel के सभी निर्देशों के साथ शेयर किया गया एनवायरमेंट, एक ही मुख्य रिपॉज़िटरी में चलता है.

ध्यान दें कि "रिपॉज़िटरी" और "वर्कस्पेस" के कॉन्सेप्ट को ऐतिहासिक तौर पर एक ही माना जाता रहा है. "वर्कस्पेस" शब्द का इस्तेमाल अक्सर मुख्य रिपॉज़िटरी के लिए किया जाता है. कभी-कभी, इसका इस्तेमाल "रिपॉज़िटरी" के लिए भी किया जाता है.

कैननिकल रिपॉज़िटरी का नाम

वह कैननिकल नाम जिससे रिपॉज़िटरी (डेटा स्टोर करने की जगह) दी जाती है. वर्कस्पेस के संदर्भ में, हर रिपॉज़िटरी का एक ही कैननिकल नाम होता है. किसी ऐसे रिपॉज़िटरी में मौजूद टारगेट का नाम जिसका कैननिकल नाम canonical_name है, उसे लेबल @@canonical_name//pac/kage:target से ऐक्सेस किया जा सकता है. ध्यान दें कि इसमें दो @ हैं.

डेटा स्टोर करने की मुख्य जगह में, कैननिकल नाम के तौर पर हमेशा खाली स्ट्रिंग होती है.

डेटा स्टोर करने की आसान जगह का नाम

वह नाम जिसे किसी अन्य डेटा स्टोर करने की जगह के संदर्भ में इस्तेमाल किया जा सकता है. इसे रेपो के "निकनेम" के तौर पर माना जा सकता है: कैननिकल नाम वाले रेपो alice के लिए, रिपो का नाम mike हो सकता है. हालांकि, रेपो के लिए इसका नाम mickey हो सकता हैbob.michael इस मामले में, michael में मौजूद टारगेट को @mike//pac/kage:target लेबल, alice (ध्यान दें कि एक @) के हिसाब से बता सकता है.

इसके उलट, इसे रिपॉज़िटरी मैपिंग के तौर पर समझा जा सकता है: हर रिपॉज़िटरी, "रिपॉज़िटरी का दिखने वाला नाम" से "रिपॉज़िटरी का कैननिकल नाम" तक मैपिंग बनाए रखती है.

रिपॉज़िटरी का नियम

रिपॉज़िटरी की परिभाषाओं के लिए स्कीमा, जो बेज़ल को डेटा स्टोर करने की जगह बनाने के तरीके के बारे में बताता है. उदाहरण के लिए, "किसी यूआरएल से zip संग्रह डाउनलोड करना और उसे निकालना", "किसी Maven आर्टफ़ैक्ट को फ़ेच करना और उसे java_import टारगेट के तौर पर उपलब्ध कराना" या "किसी स्थानीय डायरेक्ट्री को सिंबल लिंक करना". हर repo को, सही संख्या में आर्ग्युमेंट के साथ repo नियम को कॉल करके तय किया जाता है.

खुद के रिपॉज़िटरी नियम लिखने के तरीके के बारे में ज़्यादा जानने के लिए, रिपॉज़िटरी के नियम देखें.

अब तक, सबसे सामान्य रिपॉज़िटरी नियम ये हैं: http_archive, जो किसी यूआरएल से संग्रह डाउनलोड करता है और उसे निकालता है. दूसरा, local_repository, जो पहले से ही Bazel रिपॉज़िटरी वाली किसी स्थानीय डायरेक्ट्री को लिंक करता है.

डेटा स्टोर करने की जगह फ़ेच करना

लोकल डिस्क से जुड़े रेपो के नियम को चलाकर, उस पर मौजूद रेपो को उपलब्ध कराने की कार्रवाई. किसी वर्कस्पेस में तय किए गए रिपॉज़िटरी, फ़ेच किए जाने से पहले लोकल डिस्क पर उपलब्ध नहीं होते.

आम तौर पर, Bazel किसी रिपॉज़िटरी को सिर्फ़ तब फ़ेच करता है, जब उसे रिपॉज़िटरी से कुछ चाहिए हो और रिपॉज़िटरी को पहले से फ़ेच न किया गया हो. अगर किसी रिपॉज़िटरी को पहले ही फ़ेच किया जा चुका है, तो Bazel उसे फिर से सिर्फ़ तब फ़ेच करता है, जब उसकी डेफ़िनिशन बदल जाती है.

डायरेक्ट्री का लेआउट

डेटा फ़ेच करने के बाद, रेपो को उसके कैननिकल नाम के तहत, आउटपुट बेस की सबडायरेक्ट्री external में देखा जा सकता है.

कैननिकल नाम canonical_name के साथ, रेपो का कॉन्टेंट देखने के लिए यह निर्देश दिया जा सकता है:

ls $(bazel info output_base)/external/ canonical_name 

Bzlmod की मदद से बाहरी डिपेंडेंसी मैनेज करना

Bzlmod नया एक्सटर्नल डिपेंडेंसी सबसिस्टम है. यह सीधे तौर पर रेपो डेफ़िनिशन के साथ काम नहीं करता. इसके बजाय, यह मॉड्यूल से एक डिपेंडेंसी ग्राफ़ बनाता है और ग्राफ़ पर सबसे ऊपर एक्सटेंशन चलाता है. साथ ही, उसी हिसाब से डेटा संग्रह की संख्या के बारे में बताता है.

Basel मॉड्यूल एक Basel प्रोजेक्ट है, जिसके कई वर्शन हो सकते हैं. इनमें से हर वर्शन, उस मॉड्यूल के बारे में मेटाडेटा पब्लिश करता है जिस पर वह निर्भर करता है. मॉड्यूल के रेपो रूट में, 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 फिर से रजिस्ट्री से सलाह लेता है, ताकि हर मॉड्यूल के लिए एक रिपॉज़िटरी तय करने का तरीका जाने. ज़्यादातर मामलों में, http_archive का इस्तेमाल किया जाता है.

मॉड्यूल में, टैग नाम के डेटा के कस्टमाइज़ किए गए हिस्सों की जानकारी भी दी जा सकती है. मॉड्यूल रिज़ॉल्यूशन के बाद, मॉड्यूल एक्सटेंशन इनका इस्तेमाल करते हैं, ताकि अन्य रिपॉज़िटरी तय की जा सकें. इन एक्सटेंशन में रेपो नियमों जैसी क्षमताएं होती हैं, जिनकी मदद से ये I/O फ़ाइल करने और नेटवर्क अनुरोध भेजने जैसी कार्रवाइयां कर सकते हैं. इनकी मदद से, Bazel को अन्य पैकेज मैनेजमेंट सिस्टम के साथ इंटरैक्ट करने की अनुमति मिलती है. साथ ही, 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 फ़ाइलों में इस मैक्रो को कॉल करने के लिए कहा जाता है.
    • इसकी कुछ समस्याएं हैं: मैक्रो, load दूसरी .bzl फ़ाइलों को load नहीं कर सकते. इसलिए, इन प्रोजेक्ट को इस "deps" मैक्रो में अपनी ट्रांज़िशन डिपेंडेंसी तय करनी होगी या उपयोगकर्ता को कई लेयर वाले "deps" मैक्रो को कॉल करके इस समस्या को हल करना होगा.
    • Baज़र, WORKSPACE फ़ाइल का क्रम से आकलन करता है. इसके अलावा, यूआरएल के साथ http_archive का इस्तेमाल करके, डिपेंडेंसी तय की जाती हैं. इसमें वर्शन की कोई जानकारी नहीं होती. इसका मतलब है कि डायमंड डिपेंडेंसी के मामले में, वर्शन रिज़ॉल्यूशन करने का कोई भरोसेमंद तरीका नहीं है. जैसे, A, B और C पर निर्भर करता है. B और C, दोनों D के अलग-अलग वर्शन पर निर्भर करते हैं.

WorkSPACE की कमियों की वजह से, Bzlmod फ़ॉर्मैट में लेगसी Workspace Workspace सिस्टम की जगह ले रहा है. यह सिस्टम, आने वाले समय में Basel के वर्शन रिलीज़ पर काम करेगा. Bzlmod पर माइग्रेट करने का तरीका जानने के लिए, कृपया Bzlmod पर माइग्रेट करने के लिए बनी गाइड पढ़ें.