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

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

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

इस दस्तावेज़ में, Bazel में बाहरी डिपेंडेंसी मैनेज करने से जुड़े कॉन्सेप्ट के बारे में बताया गया है. इसके बाद, दोनों सिस्टम के बारे में ज़्यादा जानकारी दी गई है.

कॉन्सेप्ट

रिपॉज़िटरी

यह एक डायरेक्ट्री होती है, जिसमें WORKSPACE या WORKSPACE.bazel फ़ाइल होती है. इसमें Bazel बिल्ड में इस्तेमाल की जाने वाली सोर्स फ़ाइलें होती हैं. इसे अक्सर छोटा करके सिर्फ़ repo कहा जाता है.

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

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

Workspace

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

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

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

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

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

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

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

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

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

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

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

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

किसी रिपॉज़िटरी को फ़ेच करना

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

आम तौर पर, Bazel किसी repo को सिर्फ़ तब फ़ेच करता है, जब उसे repo से किसी चीज़ की ज़रूरत होती है और repo को पहले से फ़ेच नहीं किया गया होता है. अगर रेपो को पहले ही फ़ेच किया जा चुका है, तो Bazel इसे सिर्फ़ तब फिर से फ़ेच करता है, जब इसकी डेफ़िनिशन में बदलाव हुआ हो.

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

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

कैननिकल नाम canonical_name के साथ रिपॉज़िटरी का कॉन्टेंट देखने के लिए, यह कमांड चलाएं:

ls $(bazel info output_base)/external/ canonical_name 

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

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

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

किसी मॉड्यूल को सिर्फ़ अपनी डायरेक्ट डिपेंडेंसी की सूची बनानी चाहिए. Bzlmod, Bazel रजिस्ट्री में इनकी खोज करता है. डिफ़ॉल्ट रूप से, यह Bazel Central Registry होती है. रजिस्ट्री, डिपेंडेंसी की MODULE.bazel फ़ाइलें उपलब्ध कराती है. इससे Bazel को वर्शन रिज़ॉल्यूशन करने से पहले, पूरे ट्रांज़िटिव डिपेंडेंसी ग्राफ़ का पता लगाने में मदद मिलती है.

वर्शन तय होने के बाद, Bazel हर मॉड्यूल के लिए एक वर्शन चुनता है. इसके बाद, Bazel हर मॉड्यूल के लिए रेपो को तय करने का तरीका जानने के लिए, रजिस्ट्री से फिर से सलाह लेता है. ज़्यादातर मामलों में, http_archive का इस्तेमाल किया जाता है.

मॉड्यूल, डेटा के कस्टम कॉम्पोनेंट भी तय कर सकते हैं. इन्हें टैग कहा जाता है. मॉड्यूल रिज़ॉल्यूशन के बाद, मॉड्यूल एक्सटेंशन इनका इस्तेमाल करते हैं, ताकि अतिरिक्त रिपॉज़िटरी तय की जा सकें. इन एक्सटेंशन में repo rules जैसी सुविधाएं होती हैं. इनकी मदद से, फ़ाइल I/O और नेटवर्क अनुरोध भेजने जैसी कार्रवाइयां की जा सकती हैं. इनकी मदद से, Bazel को अन्य पैकेज मैनेजमेंट सिस्टम के साथ इंटरैक्ट करने की अनुमति मिलती है. साथ ही, Bazel मॉड्यूल से बनाए गए डिपेंडेंसी ग्राफ़ का पालन किया जाता है.

WORKSPACE की मदद से, रेपो को परिभाषित करें

पहले, WORKSPACE (या WORKSPACE.bazel) फ़ाइल में रेपो तय करके, बाहरी डिपेंडेंसी मैनेज की जा सकती थीं. इस फ़ाइल का सिंटैक्स, BUILD फ़ाइलों के सिंटैक्स जैसा ही होता है. इसमें बिल्ड के नियमों के बजाय, रेपो के नियमों का इस्तेमाल किया जाता है.

नीचे दिया गया स्निपेट, WORKSPACE फ़ाइल में http_archive repo rule का इस्तेमाल करने का उदाहरण है:

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 सिस्टम को लॉन्च हुए कई साल हो चुके हैं. इस दौरान, उपयोगकर्ताओं ने कई समस्याएं बताई हैं. इनमें ये शामिल हैं:

  • Bazel, किसी भी डिपेंडेंसी की WORKSPACE फ़ाइलों का आकलन नहीं करता. इसलिए, सभी ट्रांज़िटिव डिपेंडेंसी को मुख्य रेपो की WORKSPACE फ़ाइल में तय किया जाना चाहिए. इसके अलावा, डायरेक्ट डिपेंडेंसी को भी तय किया जाना चाहिए.
  • इससे बचने के लिए, प्रोजेक्ट में "deps.bzl" पैटर्न का इस्तेमाल किया जाता है. इसमें वे एक मैक्रो तय करते हैं, जो कई रिपॉज़िटरी तय करता है. साथ ही, उपयोगकर्ताओं से इस मैक्रो को अपनी WORKSPACE फ़ाइलों में कॉल करने के लिए कहते हैं.
    • इसकी अपनी समस्याएं हैं: मैक्रो, load अन्य .bzl फ़ाइलें नहीं कर सकते. इसलिए, इन प्रोजेक्ट को इस "deps" मैक्रो में अपनी ट्रांज़िटिव डिपेंडेंसी तय करनी होती है. इसके अलावा, इस समस्या को हल करने के लिए, उपयोगकर्ता को कई लेयर वाले "deps" मैक्रो को कॉल करना होता है.
    • Bazel, WORKSPACE फ़ाइल का आकलन क्रम से करता है. इसके अलावा, यूआरएल के साथ http_archive का इस्तेमाल करके डिपेंडेंसी तय की जाती हैं. इसमें वर्शन की कोई जानकारी नहीं होती. इसका मतलब है कि डायमंड डिपेंडेंसी (A, B और C पर निर्भर करता है; B और C, दोनों D के अलग-अलग वर्शन पर निर्भर करते हैं) के मामले में, वर्शन रिज़ॉल्यूशन करने का कोई भरोसेमंद तरीका नहीं है.

WORKSPACE की कमियों की वजह से, Bzlmod आने वाले समय में Bazel की रिलीज़ में, लेगसी WORKSPACE सिस्टम की जगह लेगा. Bzlmod पर माइग्रेट करने का तरीका जानने के लिए, कृपया Bzlmod माइग्रेशन गाइड पढ़ें.