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

समस्या की शिकायत करें स्रोत देखें

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

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

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

कॉन्सेप्ट

रिपॉज़िटरी

यह एक डायरेक्ट्री ट्री है, जिसके रूट में बाउंड्री मार्कर फ़ाइल होती है. इसमें ऐसी सोर्स फ़ाइलें होती हैं जिनका इस्तेमाल Bazel बिल्ड में किया जा सकता है. इसे अक्सर सिर्फ़ रेपो में छोटा किया जाता है.

रेपो बाउंड्री मार्कर फ़ाइल MODULE.bazel (यह सिग्नल देती है कि यह रेपो Bzel मॉड्यूल को दिखाता है), REPO.bazel (नीचे देखें) या लेगसी कॉन्टेक्स्ट में, WORKSPACE या WORKSPACE.bazel हो सकता है. कोई भी रेपो बाउंड्री मार्कर फ़ाइल, रेपो की सीमा के बारे में बताती है. इस तरह की कई फ़ाइलें एक डायरेक्ट्री में एक साथ मौजूद हो सकती हैं.

डेटा स्टोर करने की मुख्य जगह

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

मुख्य डेटा स्टोर करने की जगह के रूट को वर्कस्पेस रूट के नाम से भी जाना जाता है.

फ़ाइल फ़ोल्डर

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

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

कैननिकल डेटा स्टोर करने की जगह का नाम

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

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

डेटा स्टोर करने की जगह का साफ़ तौर पर दिखने वाला नाम

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

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

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

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

डेटा स्टोर करने की जगह के अपने नियम लिखने के तरीके के बारे में ज़्यादा जानकारी के लिए, डेटा स्टोर करने की जगह के नियम देखें.

अब तक, रेपो के सबसे सामान्य नियम हैं: 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 सीधे रेपो डेफ़िनिशन के साथ काम नहीं करता. इसके बजाय, यह मॉड्यूल से एक डिपेंडेंसी ग्राफ़ बनाता है, ग्राफ़ के ऊपर एक्सटेंशन चलाता है, और उसी के हिसाब से रिपोज़ को तय करता है.

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 को वर्शन रिज़ॉल्यूशन से पहले, सभी ट्रांज़िशनिव डिपेंडेंसी ग्राफ़ खोजने की सुविधा मिलती है.

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

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