मॉड्यूल एक्सटेंशन की मदद से, उपयोगकर्ता मॉड्यूल सिस्टम को बड़ा कर सकते हैं. इसके लिए, वे डिपेंडेंसी ग्राफ़ में मौजूद मॉड्यूल से इनपुट डेटा पढ़ते हैं. साथ ही, डिपेंडेंसी को हल करने के लिए ज़रूरी लॉजिक लागू करते हैं और आखिर में, रेपो के नियमों को कॉल करके रेपो बनाते हैं. ये एक्सटेंशन इसमें रेपो नियमों से मिलती-जुलती सुविधाएं हैं. इससे उन्हें फ़ाइल I/O चलाने का विकल्प मिलता है, नेटवर्क अनुरोध भेजने की अनुमति देता है. इसके अलावा, इनकी मदद से बेज़ल ये काम भी कर पाते हैं अन्य पैकेज मैनेजमेंट सिस्टम के साथ इंटरैक्ट करते हैं. साथ ही, Basel मॉड्यूल से बनाया गया डिपेंडेंसी ग्राफ़.
रेपो नियमों की तरह ही, .bzl
फ़ाइलों में मॉड्यूल एक्सटेंशन तय किए जा सकते हैं. इन्हें सीधे तौर पर शुरू नहीं किया जाता. इसके बजाय, हर मॉड्यूल में एक्सटेंशन के लिए पढ़ने के लिए, टैग नाम के डेटा के हिस्से होते हैं. Bazel, किसी भी एक्सटेंशन का आकलन करने से पहले मॉड्यूल रिज़ॉल्यूशन चलाता है. एक्सटेंशन, पूरे डिपेंडेंसी ग्राफ़ में उससे जुड़े सभी टैग पढ़ता है.
एक्सटेंशन का इस्तेमाल
एक्सटेंशन, Bazel मॉड्यूल में ही होस्ट किए जाते हैं. किसी एक्सटेंशन का इस्तेमाल
मॉड्यूल से, पहले एक्सटेंशन को होस्ट करने वाले मॉड्यूल में bazel_dep
जोड़ें और फिर
use_extension
पहले से मौजूद फ़ंक्शन को कॉल करें
उसे दायरे में लाने के लिए किया जा सकता है. इस उदाहरण पर ध्यान दें — rules_jvm_external
मॉड्यूल में बताए गए "maven" एक्सटेंशन का इस्तेमाल करने के लिए, MODULE.bazel
फ़ाइल का स्निपेट:
bazel_dep(name = "rules_jvm_external", version = "4.5")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
यह use_extension
की रिटर्न वैल्यू को वैरिएबल से बाइंड कर देता है. इससे,
उपयोगकर्ता को डॉट-सिंटैक्स का उपयोग करके एक्सटेंशन के टैग दर्ज करना होगा. टैग, एक्सटेंशन की परिभाषा में बताई गई टैग क्लास के मुताबिक तय किए गए स्कीमा के मुताबिक होने चाहिए. उदाहरण के लिए, कुछ
maven.install
और maven.artifact
टैग:
maven.install(artifacts = ["org.junit:junit:4.13.2"])
maven.artifact(group = "com.google.guava",
artifact = "guava",
version = "27.0-jre",
exclusions = ["com.google.j2objc:j2objc-annotations"])
एक्सटेंशन से जनरेट किए गए रिपॉज़िटरी को मौजूदा मॉड्यूल के दायरे में लाने के लिए, use_repo
डायरेक्टिव का इस्तेमाल करें.
use_repo(maven, "maven")
किसी एक्सटेंशन के ज़रिए जनरेट किए गए डेटा स्टोर करने की जगह, इसके एपीआई का हिस्सा होती है. इस उदाहरण में,
"मावेन" मॉड्यूल एक्सटेंशन, maven
नाम का रेपो जनरेट करने का वादा करता है.
ऊपर दी गई घोषणा के अनुसार, एक्सटेंशन लेबलों, जैसे कि
"maven" के जनरेट किए गए रेपो पर ले जाने के लिए @maven//:org_junit_junit
एक्सटेंशन चुनें.
एक्सटेंशन की परिभाषा
module_extension
फ़ंक्शन का इस्तेमाल करके, मॉड्यूल एक्सटेंशन को ठीक उसी तरह से तय किया जा सकता है जिस तरह रिपॉज़िटरी के नियम तय किए जाते हैं. हालांकि, रिपॉज़िटरी के नियमों में कई एट्रिब्यूट होते हैं, जबकि मॉड्यूल एक्सटेंशन में tag_class
होते हैं. इनमें से हर एक में कई एट्रिब्यूट होते हैं. टैग क्लास, इस एक्सटेंशन में इस्तेमाल किए गए टैग के लिए स्कीमा तय करती हैं. उदाहरण के लिए, ऊपर दिए गए "maven" एक्सटेंशन को इस तरह परिभाषित किया जा सकता है:
# @rules_jvm_external//:extensions.bzl
_install = tag_class(attrs = {"artifacts": attr.string_list(), ...})
_artifact = tag_class(attrs = {"group": attr.string(), "artifact": attr.string(), ...})
maven = module_extension(
implementation = _maven_impl,
tag_classes = {"install": _install, "artifact": _artifact},
)
इन एलान से पता चलता है कि एट्रिब्यूट के लिए तय किए गए स्कीमा का इस्तेमाल करके, maven.install
और maven.artifact
टैग की जानकारी दी जा सकती है.
मॉड्यूल एक्सटेंशन को लागू करने का फ़ंक्शन, रेपो एक्सटेंशन से मिलता-जुलता है
इसके अलावा, उन्हें एक module_ctx
ऑब्जेक्ट मिलता है,
जो एक्सटेंशन और सभी काम के टैग का इस्तेमाल करने वाले सभी मॉड्यूल को ऐक्सेस करने की अनुमति देता है.
इसके बाद, लागू करने वाला फ़ंक्शन, रिपॉज़िटरी जनरेट करने के लिए रिपॉज़िटरी के नियमों को कॉल करता है.
# @rules_jvm_external//:extensions.bzl
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file") # a repo rule
def _maven_impl(ctx):
# This is a fake implementation for demonstration purposes only
# collect artifacts from across the dependency graph
artifacts = []
for mod in ctx.modules:
for install in mod.tags.install:
artifacts += install.artifacts
artifacts += [_to_artifact(artifact) for artifact in mod.tags.artifact]
# call out to the coursier CLI tool to resolve dependencies
output = ctx.execute(["coursier", "resolve", artifacts])
repo_attrs = _process_coursier_output(output)
# call repo rules to generate repos
for attrs in repo_attrs:
http_file(**attrs)
_generate_hub_repo(name = "maven", repo_attrs)
एक्सटेंशन आइडेंटिटी
मॉड्यूल एक्सटेंशन की पहचान, ऐप्लिकेशन के नाम और दिखने वाली .bzl
फ़ाइल से की जाती है
use_extension
को किए गए कॉल में. नीचे दिए गए उदाहरण में, एक्सटेंशन maven
की पहचान .bzl
फ़ाइल @rules_jvm_external//:extension.bzl
और
नाम maven
:
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
किसी एक्सटेंशन को किसी दूसरी .bzl
फ़ाइल से फिर से एक्सपोर्ट करने पर, उसे एक नई पहचान मिलती है. अगर ट्रांज़िशन वाले मॉड्यूल ग्राफ़ में एक्सटेंशन के दोनों वर्शन का इस्तेमाल किया जाता है, तो उनका अलग-अलग आकलन किया जाएगा. साथ ही, उनमें सिर्फ़ उस खास पहचान से जुड़े टैग दिखेंगे.
एक्सटेंशन लेखक के रूप में आपको यह पक्का करना चाहिए कि उपयोगकर्ता सिर्फ़ आपके
एक .bzl
फ़ाइल से मॉड्यूल एक्सटेंशन.
रिपॉज़िटरी के नाम और उन्हें दिखने की सेटिंग
एक्सटेंशन के ज़रिए जनरेट किए गए डेटा संग्रह में module_repo_canonical_name~extension_name~repo_name
के तौर पर कैननिकल नाम होते हैं. इसमें होस्ट किए गए एक्सटेंशन के लिए
रूट मॉड्यूल में module_repo_canonical_name
हिस्सा है
स्ट्रिंग को _main
से बदला गया. ध्यान दें कि कैननिकल नेम फ़ॉर्मैट ऐसा एपीआई नहीं है जिस पर आपको भरोसा करना चाहिए — यह कभी भी बदल सकता है.
नाम रखने की इस नीति का मतलब है कि हर एक्सटेंशन का अपना "रिपो नेमस्पेस" होता है. दो अलग-अलग एक्सटेंशन, एक ही नाम वाले रिपो को तय कर सकते हैं. इसका मतलब यह भी है कि repository_ctx.name
, कैननिकल नाम की जानकारी देता है
होता है, जो रेपो नियम में बताए गए नाम से मिलता-जुलता नहीं है
कॉल.
मॉड्यूल एक्सटेंशन से जनरेट किए गए रिपॉज़िटरी को ध्यान में रखते हुए, रिपॉज़िटरी को दिखने से जुड़े कई नियम हैं:
- Bazel मॉड्यूल का कोई भी रिपॉज़िटरी,
bazel_dep
औरuse_repo
की मदद से, अपनीMODULE.bazel
फ़ाइल में शामिल सभी रिपॉज़िटरी देख सकता है. - मॉड्यूल एक्सटेंशन के ज़रिए जनरेट किए गए रेपो,
मॉड्यूल जो एक्सटेंशन होस्ट करता है, और इसके ज़रिए जनरेट किए गए अन्य सभी डेटा संग्रह स्थान
एक ही मॉड्यूल एक्सटेंशन (रेपो नियम कॉल में बताए गए नामों का इस्तेमाल करके
असली उपयोगकर्ताओं के नाम.
- इसकी वजह से विवाद हो सकता है. अगर मॉड्यूल रेपो को
दिखाई देता है
foo
, और एक्सटेंशन नामfoo
, फिर उस एक्सटेंशन के ज़रिए जनरेट किए गए सभी डेटा स्टोर करने की जगह के लिएfoo
पिछले वाले के बारे में बताता है.
- इसकी वजह से विवाद हो सकता है. अगर मॉड्यूल रेपो को
दिखाई देता है
सबसे सही तरीके
इस सेक्शन में एक्सटेंशन लिखने के सबसे सही तरीकों के बारे में बताया गया है, ताकि वे ये इस्तेमाल में आसान और आसान होते हैं. साथ ही, समय के साथ होने वाले बदलावों के हिसाब से ढल जाते हैं.
हर एक्सटेंशन को एक अलग फ़ाइल में डालें
जब एक्सटेंशन किसी अलग फ़ाइल में होते हैं, तो यह एक एक्सटेंशन को लोड करने की अनुमति देता है डेटा स्टोर करने की जगहों की जानकारी, किसी दूसरे एक्सटेंशन के ज़रिए जनरेट की गई. भले ही आप इसका उपयोग काम है, तो ज़रूरत पड़ने पर उन्हें अलग-अलग फ़ाइलों में रखना सबसे अच्छा होगा बाद में. ऐसा इसलिए है क्योंकि एक्सटेंशन की पहचान उसकी फ़ाइल पर आधारित होती है, इसलिए किसी अन्य फ़ाइल का एक्सटेंशन बाद में आपके सार्वजनिक API को बदल देता है और वह पीछे की ओर आपके उपयोगकर्ताओं के लिए असंगत परिवर्तन.
ऑपरेटिंग सिस्टम और आर्किटेक्चर की जानकारी दें
अगर आपका एक्सटेंशन, ऑपरेटिंग सिस्टम या उसके आर्किटेक्चर टाइप पर निर्भर करता है, तो os_dependent
और arch_dependent
बूलियन एट्रिब्यूट का इस्तेमाल करके, एक्सटेंशन की परिभाषा में इसकी जानकारी ज़रूर दें. इससे यह पक्का होता है कि Baज़र,
अगर इनमें से किसी में भी बदलाव होता है, तो फिर से आकलन करने की ज़रूरत होगी.
डेटा स्टोर करने की जगह के नामों पर, सिर्फ़ रूट मॉड्यूल का सीधे तौर पर असर होना चाहिए
ध्यान रखें कि जब कोई एक्सटेंशन रिपॉज़िटरी बनाता है, तो वे एक्सटेंशन के नेमस्पेस में बनते हैं. इसका मतलब है कि अगर अलग-अलग मॉड्यूल एक ही एक्सटेंशन का इस्तेमाल करते हैं और एक ही नाम वाली कोई रिपॉज़िटरी बनाते हैं, तो कोलिज़न हो सकते हैं. यह समस्या अक्सर मॉड्यूल एक्सटेंशन के tag_class
में name
आर्ग्युमेंट के तौर पर दिखती है. इसे रिपॉज़िटरी नियम की name
वैल्यू के तौर पर पास किया जाता है.
उदाहरण के लिए, मान लें कि रूट मॉड्यूल A
, मॉड्यूल B
पर निर्भर करता है. दोनों मॉड्यूल
मॉड्यूल mylang
पर निर्भर करता है. अगर A
और B
, दोनों कॉल करते हैं
mylang.toolchain(name="foo")
, वे दोनों नाम का डेटा स्टोर करने की जगह बनाने की कोशिश करेंगे
foo
मॉड्यूल में mylang
होने पर एक गड़बड़ी मिलेगी.
इससे बचने के लिए, सीधे तौर पर रिपॉज़िटरी का नाम सेट करने की सुविधा हटाएं या सिर्फ़ रूट मॉड्यूल को ऐसा करने की अनुमति दें. रूट मॉड्यूल को यह अनुमति देना ठीक है, क्योंकि इस पर कुछ भी निर्भर नहीं होगा. इसलिए, उसे इस बात की चिंता नहीं करनी होगी कि कोई दूसरा मॉड्यूल, रिपॉज़िटरी का नाम दोहराता है या नहीं.