मॉड्यूल एक्सटेंशन, उपयोगकर्ताओं को डिपेंडेंसी ग्राफ़ में मॉड्यूल से इनपुट डेटा पढ़कर, डिपेंडेंसी के लिए ज़रूरी लॉजिक इस्तेमाल करके, और आखिर में रिपो नियमों को कॉल करके रिपॉज़िट बनाने की सुविधा देते हैं. इन एक्सटेंशन में रेपो नियमों जैसी क्षमताएं होती हैं, जो उन्हें फ़ाइल I/O करने, नेटवर्क के अनुरोध भेजने वगैरह में सक्षम बनाती हैं. इसके अलावा, वे Bazel को दूसरे पैकेज मैनेजमेंट सिस्टम से इंटरैक्ट करने की अनुमति देते हैं. साथ ही, वह Bazel मॉड्यूल से बने डिपेंडेंसी ग्राफ़ का भी ध्यान रखते हैं.
रेपो नियमों की तरह ही, .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" एक्सटेंशन से जनरेट किए गए रेपो को पॉइंट करने के लिए,
@maven//:org_junit_junit
जैसे लेबल को सही तरीके से रिज़ॉल्व करता है.
एक्सटेंशन की परिभाषा
module_extension
फ़ंक्शन का इस्तेमाल करके, रिपो नियमों की तरह मॉड्यूल एक्सटेंशन तय किए जा सकते हैं. हालांकि,
रीपो के नियमों में कई एट्रिब्यूट होते हैं, लेकिन मॉड्यूल एक्सटेंशन में
tag_class
es होते हैं. इनमें से हर एक में कई
एट्रिब्यूट होते हैं. टैग क्लास, इस एक्सटेंशन में इस्तेमाल किए गए टैग के लिए स्कीमा तय करती हैं. उदाहरण के लिए, ऊपर दिए गए "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)
एक्सटेंशन की पहचान
मॉड्यूल एक्सटेंशन की पहचान, use_extension
को कॉल करने में दिखने वाली .bzl
फ़ाइल और नाम से की जाती है. यहां दिए गए उदाहरण में, एक्सटेंशन 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 मॉड्यूल रेपो, अपनी
MODULE.bazel
फ़ाइल में पेश किए गए सभी रिपो देख सकता हैbazel_dep
औरuse_repo
की मदद से. - किसी मॉड्यूल एक्सटेंशन से जनरेट किया गया रेपो, एक्सटेंशन को होस्ट करने वाले मॉड्यूल पर दिखने वाले
सभी रिपो देख सकता है, साथ ही उसी मॉड्यूल एक्सटेंशन से जनरेट किए गए दूसरे सभी रिपो देख सकता है (रीपो नियम कॉल में बताए गए नामों का इस्तेमाल करके
उनके साफ़ तौर पर दिखने वाले नामों का इस्तेमाल करके).
- इसकी वजह से, समय पर विवाद हो सकता है. अगर मॉड्यूल रेपो, साफ़ तौर पर दिखने वाले नाम
foo
के साथ डेटा स्टोर करने की जगह देख सकता है और एक्सटेंशन तय किए गए नामfoo
से डेटा रेपो जनरेट करता है, तो उस एक्सटेंशन से जनरेट किए गए सभी रिपो के लिएfoo
का मतलब पुराने नाम से है.
- इसकी वजह से, समय पर विवाद हो सकता है. अगर मॉड्यूल रेपो, साफ़ तौर पर दिखने वाले नाम
सबसे सही तरीके
इस सेक्शन में एक्सटेंशन लिखने के सबसे सही तरीके बताए गए हैं. इससे इन्हें इस्तेमाल करने, मैनेज करने, और समय के साथ होने वाले बदलावों के हिसाब से ढलने में आसानी होगी.
हर एक्सटेंशन को अलग फ़ाइल में रखें
जब एक्सटेंशन किसी अलग फ़ाइल में होते हैं, तो यह एक एक्सटेंशन को दूसरे एक्सटेंशन से जनरेट किए गए रिपॉज़िटरी लोड करने की अनुमति देता है. भले ही आप इस फ़ंक्शन का इस्तेमाल न करें, लेकिन बेहतर होगा कि बाद में ज़रूरत पड़ने पर आप उन्हें अलग-अलग फ़ाइलों में रख दें. ऐसा इसलिए है, क्योंकि एक्सटेंशन की पहचान उसकी फ़ाइल पर आधारित होती है. इसलिए, एक्सटेंशन को बाद में किसी दूसरी फ़ाइल में ले जाने से आपका सार्वजनिक एपीआई बदल जाता है और यह आपके उपयोगकर्ताओं के लिए पुराने सिस्टम के साथ काम नहीं करता.
ऑपरेटिंग सिस्टम और आर्किटेक्चर की जानकारी दें
अगर आपका एक्सटेंशन, ऑपरेटिंग सिस्टम या उसके आर्किटेक्चर पर निर्भर करता है, तो "os_dependent" और "arch_exact" बूलियन एट्रिब्यूट का इस्तेमाल करके, एक्सटेंशन की परिभाषा में इसकी जानकारी ज़रूर दें. इससे यह पक्का होता है कि अगर उनमें से किसी में भी बदलाव होता है, तो Bazel को फिर से आकलन करने की ज़रूरत होगी.