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

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

बाहरी रिपॉज़िटरी एक डायरेक्ट्री ट्री होती है. इसमें ऐसे सोर्स फ़ाइलें होती हैं जिनका इस्तेमाल Bazel बिल्ड में किया जा सकता है. इसे मांग पर जनरेट किया जाता है. इसके लिए, इससे जुड़े repo rule को चलाया जाता है. रेपो को कई तरीकों से तय किया जा सकता है. हालांकि, आखिर में हर रेपो को रेपो के नियम लागू करके तय किया जाता है. ठीक उसी तरह जैसे बिल्ड के नियमों को लागू करके बिल्ड टारगेट तय किए जाते हैं. इनका इस्तेमाल, तीसरे पक्ष की लाइब्रेरी (जैसे कि Maven पैकेज की गई लाइब्रेरी) पर निर्भर रहने के लिए किया जा सकता है. साथ ही, इनका इस्तेमाल BUILD फ़ाइलें जनरेट करने के लिए भी किया जा सकता है. ये फ़ाइलें, उस होस्ट के हिसाब से होती हैं जिस पर Bazel चल रहा है.

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

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

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

विशेषताएं

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

http_archive = repository_rule(
    implementation=_impl,
    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 नियम के इनपुट के तौर पर तय किया जाता है, तो यह repo का नाम लेता है. हालांकि, जब इसे repository_ctx.attr.name का इस्तेमाल करके, repo नियम के लागू करने वाले फ़ंक्शन से पढ़ा जाता है, तो यह repo का कैननिकल नाम दिखाता है.

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

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

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

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

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

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

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

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

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

  • रिपो नियम को लागू करने के लिए पास किए गए एट्रिब्यूट.
  • Starlark कोड, जिसमें repo नियम को लागू करने की जानकारी शामिल होती है.
  • repository_ctx के getenv() तरीके को पास किए गए किसी भी एनवायरमेंट वैरिएबल की वैल्यू या repository_rule के environ एट्रिब्यूट के साथ एलान किया गया. इन एनवायरमेंट वैरिएबल की वैल्यू को कमांड लाइन पर, --repo_env फ़्लैग के साथ हार्ड-वायर किया जा सकता है.
  • रेपो के नियम को लागू करने वाले फ़ंक्शन में, watch किए जा रहे किसी भी पाथ का मौजूद होना, उसका कॉन्टेंट, और उसका टाइप.
    • watch पैरामीटर के साथ repository_ctx के कुछ अन्य तरीकों, जैसे कि read(), execute(), और extract() से भी पाथ को मॉनिटर किया जा सकता है.
    • इसी तरह, repository_ctx.watch_tree और path.readdir की वजह से, पाथ को अन्य तरीकों से देखा जा सकता है.
  • जब bazel fetch --force को एक्ज़ीक्यूट किया जाता है.

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

  • अगर configure फ़्लैग सेट किया गया है, तो रिपॉज़िटरी को bazel fetch --force --configure पर फिर से फ़ेच किया जाता है. हालांकि, configure नहीं की गई रिपॉज़िटरी को फिर से फ़ेच नहीं किया जाता.
  • अगर local फ़्लैग सेट है, तो ऊपर दिए गए मामलों के अलावा, Bazel सर्वर के रीस्टार्ट होने पर भी रेपो को फिर से फ़ेच किया जाता है.

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

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

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

उदाहरण

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

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

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