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

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

एक बाहरी डेटाबेस एक ऐसा नियम है जिसका इस्तेमाल सिर्फ़ 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,
    ...)

इम्प्लीमेंटेशन फ़ंक्शन कब लागू होता है?

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

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

  • WORKSPACE फ़ाइल में डेटाबेस की घोषणा के लिए पास किए गए पैरामीटर.
  • डेटाबेस के इम्प्लीमेंटेशन में शामिल Starlark कोड.
  • repository_ctx के तरीके को पास किए गए किसी भी एनवायरमेंट वैरिएबल की वैल्यू या environ एट्रिब्यूट के साथ तय की गई वैल्यूrepository_rule.getenv() कमांड लाइन पर --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 आर्टफ़ैक्ट के लिए, बिल्ड टारगेट जनरेट करता है.