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

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

एक बाहरी डेटाबेस एक ऐसा नियम है जिसका इस्तेमाल सिर्फ़ 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_rule के environ एट्रिब्यूट के साथ तय किए गए किसी भी एनवायरमेंट वैरिएबल की वैल्यू. कमांड लाइन पर फ़्लैग के साथ, इन एनवायरमेंट वैरिएबल की वैल्यू को हार्ड-वायर किया जा सकता है. --action_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 आर्टफ़ैक्ट के लिए, बिल्ड टारगेट जनरेट करता है.