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

इस पेज पर, रिपॉज़िटरी के नियम बनाने का तरीका बताया गया है. साथ ही, ज़्यादा जानकारी के लिए उदाहरण दिए गए हैं.

बाहरी रिपॉज़िटरी एक ऐसा नियम है जिसका इस्तेमाल सिर्फ़ WORKSPACE फ़ाइल में किया जा सकता है. साथ ही, यह Bazel के लोडिंग फ़ेज़ में नॉन-हर्मेटिक ऑपरेशन को चालू करता है. बाहरी रिपॉज़िटरी के हर नियम के लिए, अपना वर्कस्पेस बनाया जाता है. इसमें अपनी BUILD फ़ाइलें और आर्टफ़ैक्ट होते हैं. इनका इस्तेमाल, तीसरे पक्ष की लाइब्रेरी (जैसे, Maven पैकेज की गई लाइब्रेरी) पर निर्भर रहने के लिए किया जा सकता है. साथ ही, इनका इस्तेमाल BUILD फ़ाइलें जनरेट करने के लिए भी किया जा सकता है. ये फ़ाइलें, उस होस्ट के हिसाब से होती हैं जिस पर Bazel चल रहा है.

डेटाबेस के नियम बनाना

.bzl फ़ाइल में, repository_rule फ़ंक्शन का इस्तेमाल करके, नया रिपॉज़िटरी नियम बनाएं और उसे ग्लोबल वैरिएबल में सेव करें.

कस्टम रिपॉज़िटरी के नियम का इस्तेमाल, नेटिव रिपॉज़िटरी के नियम की तरह ही किया जा सकता है. इसमें name एट्रिब्यूट होना ज़रूरी है. साथ ही, इसकी बिल्ड फ़ाइलों में मौजूद हर टारगेट को @<name>//package:target के तौर पर रेफ़र किया जा सकता है. यहां <name>, name एट्रिब्यूट की वैल्यू है.

नियम को तब लोड किया जाता है, जब उसे साफ़ तौर पर बनाया जाता है या जब वह बिल्ड की डिपेंडेंसी होती है. इस मामले में, Bazel अपने implementation फ़ंक्शन को लागू करेगा. इस फ़ंक्शन में, रिपॉज़िटरी, उसके कॉन्टेंट, और BUILD फ़ाइलें बनाने का तरीका बताया गया है.

विशेषताएं

एट्रिब्यूट, नियम के ऐसे आर्ग्युमेंट होते हैं जिन्हें attrs नियम के आर्ग्युमेंट में डिक्शनरी के तौर पर पास किया जाता है. रिपॉज़िटरी का नियम तय करते समय, एट्रिब्यूट और उनके टाइप की सूची दिखती है. url और sha256 एट्रिब्यूट को स्ट्रिंग के तौर पर तय करने का उदाहरण:

local_repository = repository_rule(
    implementation=_impl,
    local=True,
    attrs={
        "url": attr.string(mandatory=True)
        "sha256": attr.string(mandatory=True)
    }
)

लागू करने वाले फ़ंक्शन में मौजूद किसी एट्रिब्यूट को ऐक्सेस करने के लिए, repository_ctx.attr.<attribute_name> का इस्तेमाल करें:

def _impl(repository_ctx):
    url = repository_ctx.attr.url
    checksum = repository_ctx.attr.sha256

सभी repository_rule में, एट्रिब्यूट पहले से तय होते हैं. ये एट्रिब्यूट, बिल्ड नियमों की तरह ही होते हैं. दो इंप्लिसिट एट्रिब्यूट ये हैं: name (ठीक उसी तरह जैसे बिल्ड के नियमों के लिए) और repo_mapping. किसी रिपॉज़िटरी के नियम का नाम repository_ctx.name की मदद से ऐक्सेस किया जा सकता है. repo_mapping का मतलब वही है जो नेटिव रिपॉज़िटरी के नियमों local_repository और new_local_repository के लिए है.

अगर किसी एट्रिब्यूट का नाम _ से शुरू होता है, तो वह निजी होता है. साथ ही, उपयोगकर्ता उसे सेट नहीं कर सकते.

लागू करने से जुड़ा फ़ंक्शन

हर रिपॉज़िटरी के नियम के लिए, implementation फ़ंक्शन की ज़रूरत होती है. इसमें नियम का असली लॉजिक होता है. इसे सिर्फ़ लोडिंग फ़ेज़ में लागू किया जाता है.

फ़ंक्शन में सिर्फ़ एक इनपुट पैरामीटर, repository_ctx होता है. यह फ़ंक्शन, None वैल्यू दिखाता है. इसका मतलब है कि दिए गए पैरामीटर के हिसाब से, नियम को दोहराया जा सकता है. इसके अलावा, यह फ़ंक्शन उस नियम के लिए पैरामीटर का एक डिक्शनरी दिखाता है. इससे नियम को दोहराया जा सकता है और एक ही रिपॉज़िटरी जनरेट की जा सकती है. उदाहरण के लिए, किसी git रिपॉज़िटरी को ट्रैक करने वाले नियम के लिए, इसका मतलब है कि मूल रूप से तय की गई फ़्लोटिंग ब्रांच के बजाय, किसी खास कमिट आइडेंटिफ़ायर को वापस लाना.

इनपुट पैरामीटर repository_ctx का इस्तेमाल, एट्रिब्यूट की वैल्यू ऐक्सेस करने के लिए किया जा सकता है. साथ ही, इसका इस्तेमाल नॉन-हर्मेटिक फ़ंक्शन के लिए भी किया जा सकता है. जैसे, बाइनरी ढूंढना, बाइनरी को एक्ज़ीक्यूट करना, रिपॉज़िटरी में फ़ाइल बनाना या इंटरनेट से फ़ाइल डाउनलोड करना. ज़्यादा जानकारी के लिए, लाइब्रेरी देखें. उदाहरण:

def _impl(repository_ctx):
  repository_ctx.symlink(repository_ctx.attr.path, "")

local_repository = repository_rule(
    implementation=_impl,
    ...)

लागू करने वाला फ़ंक्शन कब लागू होता है?

किसी रिपॉज़िटरी के implementation फ़ंक्शन को तब लागू किया जाता है, जब Bazel को उस रिपॉज़िटरी से किसी टारगेट की ज़रूरत होती है. उदाहरण के लिए, जब किसी दूसरी रिपॉज़िटरी में मौजूद कोई टारगेट उस पर निर्भर होता है या जब उसे कमांड लाइन पर मेंशन किया जाता है. इसके बाद, लागू करने वाले फ़ंक्शन से फ़ाइल सिस्टम में रिपॉज़िटरी बनाने की उम्मीद की जाती है. इसे रिपॉज़िटरी को "फ़ेच करना" कहा जाता है.

सामान्य टारगेट के उलट, जब कोई ऐसी चीज़ बदलती है जिसकी वजह से डेटाबेस अलग हो जाता है, तो ज़रूरी नहीं कि डेटाबेस को फिर से फ़ेच किया जाए. ऐसा इसलिए है, क्योंकि Bazel कुछ चीज़ों में बदलावों का पता नहीं लगा सकता. इसके अलावा, हर बिल्ड पर बहुत ज़्यादा ओवरहेड हो सकता है. उदाहरण के लिए, नेटवर्क से फ़ेच की गई चीज़ें. इसलिए, रिपॉज़िटरी को सिर्फ़ तब फिर से फ़ेच किया जाता है, जब इनमें से कोई एक बदलाव होता है:

  • WORKSPACE फ़ाइल में, रिपॉज़िटरी के एलान के लिए पास किए गए पैरामीटर.
  • Starlark कोड, जिसमें रिपॉज़िटरी को लागू करने की जानकारी शामिल होती है.
  • repository_ctx के getenv() तरीके को पास किए गए किसी भी एनवायरमेंट वैरिएबल की वैल्यू या repository_rule के environ एट्रिब्यूट के साथ एलान किया गया. --repo_env फ़्लैग का इस्तेमाल करके, कमांड लाइन पर इन एनवायरमेंट वैरिएबल की वैल्यू को हार्ड-वायर किया जा सकता है.
  • repository_ctx के read(), execute(), और इसी तरह के अन्य तरीकों से पास की गई किसी भी फ़ाइल का कॉन्टेंट, जिसे किसी लेबल से रेफ़र किया जाता है. उदाहरण के लिए, //mypkg:label.txt, लेकिन mypkg/label.txt नहीं
  • जब bazel sync को एक्ज़ीक्यूट किया जाता है.

repository_rule के दो पैरामीटर होते हैं. इनसे यह कंट्रोल किया जाता है कि रिपॉज़िटरी को फिर से कब फ़ेच किया जाए:

  • अगर configure फ़्लैग सेट है, तो रिपॉज़िटरी को सिर्फ़ bazel sync पर फिर से फ़ेच किया जाता है. ऐसा तब होता है, जब --configure पैरामीटर को पास किया जाता है. अगर एट्रिब्यूट सेट नहीं है, तो इस कमांड से रिपॉज़िटरी को फिर से फ़ेच नहीं किया जाएगा
  • अगर local फ़्लैग सेट है, तो ऊपर दिए गए मामलों के अलावा, Bazel सर्वर के रीस्टार्ट होने पर भी रिपॉज़िटरी को फिर से फ़ेच किया जाता है. साथ ही, रिपॉज़िटरी के एलान पर असर डालने वाली किसी भी फ़ाइल में बदलाव होने पर भी ऐसा होता है. उदाहरण के लिए, WORKSPACE फ़ाइल या वह फ़ाइल जिसे यह लोड करती है. भले ही, बदलावों की वजह से रिपॉज़िटरी के एलान या उसके कोड में बदलाव हुआ हो या नहीं.

    इन मामलों में, गैर-स्थानीय डेटाबेस को फिर से फ़ेच नहीं किया जाता. ऐसा इसलिए है, क्योंकि इन रिपॉज़िटरी को नेटवर्क से कम्यूनिकेट करने या अन्य मामलों में महंगा माना जाता है.

लागू करने वाले फ़ंक्शन को फिर से शुरू करना

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

बाहरी रिपॉज़िटरी को फिर से फ़ेच करने के लिए मजबूर करना

कभी-कभी, बाहरी रिपॉज़िटरी पुरानी हो सकती है. ऐसा तब होता है, जब उसकी परिभाषा या डिपेंडेंसी में कोई बदलाव नहीं किया जाता. उदाहरण के लिए, सोर्स फ़ेच करने वाली कोई रिपॉज़िटरी, तीसरे पक्ष की रिपॉज़िटरी की किसी खास ब्रांच को फ़ॉलो कर सकती है. साथ ही, उस ब्रांच पर नई कमिट उपलब्ध होती हैं. इस मामले में, bazel sync को कॉल करके, Bazel से सभी बाहरी रिपॉज़िटरी को बिना किसी शर्त के फिर से फ़ेच करने के लिए कहा जा सकता है.

इसके अलावा, कुछ नियम स्थानीय मशीन की जांच करते हैं. अगर स्थानीय मशीन को अपग्रेड किया गया है, तो हो सकता है कि ये नियम पुराने हो जाएं. यहां Bazel से सिर्फ़ उन बाहरी रिपॉज़िटरी को फिर से फ़ेच करने के लिए कहा जा सकता है जिनमें repository_rule डेफ़िनिशन में configure एट्रिब्यूट सेट है. इसके लिए, bazel sync --configure का इस्तेमाल करें.

उदाहरण

  • C++ के लिए अपने-आप कॉन्फ़िगर होने वाली टूलचेन: यह रिपॉज़िटरी के नियम का इस्तेमाल करके, Bazel के लिए C++ कॉन्फ़िगरेशन फ़ाइलें अपने-आप बनाती है. इसके लिए, यह लोकल C++ कंपाइलर, एनवायरमेंट, और C++ कंपाइलर के साथ काम करने वाले फ़्लैग खोजती है.

  • Go रिपॉज़िटरी, Go के नियमों का इस्तेमाल करने के लिए ज़रूरी डिपेंडेंसी की सूची तय करने के लिए, कई repository_rule का इस्तेमाल करती है.

  • rules_jvm_external डिफ़ॉल्ट रूप से @maven नाम की एक बाहरी रिपॉज़िटरी बनाता है. यह रिपॉज़िटरी, ट्रांज़िटिव डिपेंडेंसी ट्री में मौजूद हर Maven आर्टफ़ैक्ट के लिए, बिल्ड टारगेट जनरेट करती है.