इस पेज पर, मैक्रो इस्तेमाल करने की बुनियादी जानकारी दी गई है. इसमें, मैक्रो इस्तेमाल करने के सामान्य उदाहरण, डीबग करने का तरीका, और इस्तेमाल से जुड़ी ज़रूरी शर्तें शामिल हैं.
मैक्रो, BUILD फ़ाइल से कॉल किया जाने वाला एक फ़ंक्शन है. इसकी मदद से, नियमों को इंस्टैंशिएट किया जा सकता है.
मैक्रो का मुख्य तौर पर इस्तेमाल, मौजूदा नियमों और अन्य मैक्रो को एनकैप्सुलेट करने और कोड को फिर से इस्तेमाल करने के लिए किया जाता है.
मैक्रो दो तरह के होते हैं: सिंबॉलिक मैक्रो, जिनके बारे में इस पेज पर बताया गया है, और लेगसी मैक्रो. हमारा सुझाव है कि कोड को साफ़ तौर पर दिखाने के लिए, सिंबॉलिक मैक्रो का इस्तेमाल करें.
सिंबॉलिक मैक्रो में, टाइप किए गए आर्ग्युमेंट (मैक्रो को जहां से कॉल किया गया है उसके हिसाब से, स्ट्रिंग को लेबल में बदलना) इस्तेमाल किए जा सकते हैं. साथ ही, बनाए गए टारगेट की विज़िबिलिटी को सीमित और तय किया जा सकता है. इन्हें लेज़ी इवैल्युएशन के हिसाब से डिज़ाइन किया गया है. यह सुविधा, Bazel के आने वाले वर्शन में जोड़ी जाएगी. Bazel 8 में, सिंबॉलिक मैक्रो डिफ़ॉल्ट रूप से उपलब्ध होते हैं. इस दस्तावेज़ में जहां भी macros का ज़िक्र है, वहां इसका मतलब सिंबॉलिक मैक्रो है.
सिंबॉलिक मैक्रो का कोई ऐसा उदाहरण जिसे चलाया जा सके, उदाहरणों के रिपॉज़िटरी में देखा जा सकता है.
इस्तेमाल
मैक्रो को .bzl फ़ाइलों में
macro() फ़ंक्शन को दो ज़रूरी पैरामीटर के साथ कॉल करके तय किया जाता है: attrs और implementation.
विशेषताएं
attrs एट्रिब्यूट के नाम से एट्रिब्यूट
के टाइप की डिक्शनरी स्वीकार करता है. यह डिक्शनरी, मैक्रो के आर्ग्युमेंट
को दिखाती है. दो सामान्य एट्रिब्यूट – name और visibility – सभी मैक्रो में अपने-आप जुड़ जाते हैं. इन्हें attrs को पास की गई डिक्शनरी में शामिल नहीं किया जाता.
# macro/macro.bzl
my_macro = macro(
attrs = {
"deps": attr.label_list(mandatory = True, doc = "The dependencies passed to the inner cc_binary and cc_test targets"),
"create_test": attr.bool(default = False, configurable = False, doc = "If true, creates a test target"),
},
implementation = _my_macro_impl,
)
एट्रिब्यूट टाइप के एलान में,
पैरामीटर,
mandatory, default, और doc स्वीकार किए जाते हैं. ज़्यादातर एट्रिब्यूट टाइप, configurable पैरामीटर भी स्वीकार करते हैं. इससे यह तय होता है कि एट्रिब्यूट, select स्वीकार करता है या नहीं. अगर कोई एट्रिब्यूट configurable है, तो वह select नहीं होने वाली वैल्यू को, कॉन्फ़िगर नहीं की जा सकने वाली select के तौर पर पार्स करेगा – "foo", select({"//conditions:default": "foo"}) बन जाएगा. selects के बारे में ज़्यादा जानें.
एट्रिब्यूट इनहेरिटेंस
मैक्रो का इस्तेमाल अक्सर किसी नियम (या दूसरे मैक्रो) को रैप करने के लिए किया जाता है. साथ ही, मैक्रो का लेखक अक्सर रैप किए गए सिंबल के ज़्यादातर एट्रिब्यूट को, **kwargs का इस्तेमाल करके, मैक्रो के मुख्य टारगेट (या मुख्य इनर मैक्रो) को बिना किसी बदलाव के फ़ॉरवर्ड करना चाहता है.
इस पैटर्न के लिए, कोई मैक्रो, नियम या दूसरे
मैक्रो से एट्रिब्यूट इनहेरिट कर सकता है. इसके लिए, नियम या
मैक्रो सिंबल को macro()'s
inherit_attrs आर्ग्युमेंट में पास किया जाता है. (Starlark के सभी बिल्ड नियमों के लिए तय किए गए सामान्य एट्रिब्यूट को इनहेरिट करने के लिए, नियम या मैक्रो सिंबल के बजाय, खास स्ट्रिंग "common"
`"common"` का भी इस्तेमाल किया जा सकता है.)
सिर्फ़ सार्वजनिक एट्रिब्यूट इनहेरिट किए जाते हैं. साथ ही, मैक्रो की अपनी attrs डिक्शनरी में मौजूद एट्रिब्यूट, एक ही नाम वाले इनहेरिट किए गए एट्रिब्यूट को ओवरराइड करते हैं. attrs डिक्शनरी में, None को वैल्यू के तौर पर इस्तेमाल करके, इनहेरिट किए गए एट्रिब्यूट को हटाया भी जा सकता है:
# macro/macro.bzl
my_macro = macro(
inherit_attrs = native.cc_library,
attrs = {
# override native.cc_library's `local_defines` attribute
"local_defines": attr.string_list(default = ["FOO"]),
# do not inherit native.cc_library's `defines` attribute
"defines": None,
},
...
)
ज़रूरी नहीं होने वाले इनहेरिट किए गए एट्रिब्यूट की डिफ़ॉल्ट वैल्यू हमेशा None पर ओवरराइड की जाती है. भले ही, ओरिजनल एट्रिब्यूट की डिफ़ॉल्ट वैल्यू कुछ भी हो. अगर आपको ज़रूरी नहीं होने वाले इनहेरिट किए गए एट्रिब्यूट की जांच करनी है या उसमें बदलाव करना है, तो आपको अपने मैक्रो के लागू करने वाले फ़ंक्शन में, None केस को मैनेज करना होगा. उदाहरण के लिए, अगर आपको इनहेरिट किए गए tags एट्रिब्यूट में कोई टैग जोड़ना है, तो आपको यह करना होगा:
# macro/macro.bzl
def _my_macro_impl(name, visibility, tags, **kwargs):
# Append a tag; tags attr is an inherited non-mandatory attribute, and
# therefore is None unless explicitly set by the caller of our macro.
my_tags = (tags or []) + ["another_tag"]
native.cc_library(
...
tags = my_tags,
**kwargs,
)
...
लागू करना
implementation, एक ऐसा फ़ंक्शन स्वीकार करता है जिसमें मैक्रो की लॉजिक शामिल होती है.
लागू करने वाले फ़ंक्शन अक्सर एक या उससे ज़्यादा नियमों को कॉल करके टारगेट बनाते हैं. ये फ़ंक्शन आम तौर पर निजी होते हैं. इनके नाम की शुरुआत में अंडरस्कोर होता है. आम तौर पर,
इनके नाम वही होते हैं जो इनके मैक्रो के होते हैं. हालांकि, इनके नाम की शुरुआत में _ और आखिर में
_impl जोड़ा जाता है.
नियम लागू करने वाले फ़ंक्शन के उलट, मैक्रो लागू करने वाले फ़ंक्शन हर आर्ग्युमेंट के लिए एक पैरामीटर स्वीकार करते हैं. नियम लागू करने वाले फ़ंक्शन, सिर्फ़ एक आर्ग्युमेंट (ctx) स्वीकार करते हैं, जिसमें एट्रिब्यूट का रेफ़रंस होता है.
# macro/macro.bzl
def _my_macro_impl(name, visibility, deps, create_test):
cc_library(
name = name + "_cc_lib",
deps = deps,
)
if create_test:
cc_test(
name = name + "_test",
srcs = ["my_test.cc"],
deps = deps,
)
अगर कोई मैक्रो, एट्रिब्यूट इनहेरिट करता है, तो उसके लागू करने वाले फ़ंक्शन में, **kwargs रेसिडुअल कीवर्ड पैरामीटर ज़रूर होना चाहिए. इसे, इनहेरिट किए गए नियम या सबमैक्रो को लागू करने वाले कॉल को फ़ॉरवर्ड किया जा सकता है. (इससे यह पक्का करने में मदद मिलती है कि अगर वह नियम या मैक्रो जिससे आप इनहेरिट कर रहे हैं, कोई नया एट्रिब्यूट जोड़ता है, तो आपका मैक्रो काम करना बंद नहीं करेगा.)
एलान
मैक्रो का एलान, BUILD फ़ाइल में उसकी परिभाषा लोड करके और कॉल करके किया जाता है.
```starlark
pkg/BUILD
my_macro( name = "macro_instance", deps = ["src.cc"] + select( { "//config_setting:special": ["special_source.cc"], "//conditions:default": [], }, ), create_tests = True, ) ```
इससे, //pkg:macro_instance_cc_lib और//pkg:macro_instance_test टारगेट बनेंगे.
नियम कॉल की तरह, अगर किसी मैक्रो कॉल में किसी एट्रिब्यूट की वैल्यू None पर सेट की जाती है, तो उस एट्रिब्यूट को ऐसा माना जाता है जैसे कि उसे मैक्रो के कॉलर ने छोड़ दिया हो. उदाहरण के लिए, ये दो मैक्रो कॉल एक जैसे हैं:
# pkg/BUILD
my_macro(name = "abc", srcs = ["src.cc"], deps = None)
my_macro(name = "abc", srcs = ["src.cc"])
आम तौर पर, यह BUILD फ़ाइलों में काम का नहीं होता. हालांकि, प्रोग्राम के ज़रिए किसी मैक्रो को दूसरे मैक्रो में रैप करते समय यह काम का होता है.
विवरण
बनाए गए टारगेट के लिए नाम रखने से जुड़ी ज़रूरी शर्तें
सिंबॉलिक मैक्रो से बनाए गए किसी भी टारगेट या सबमैक्रो के नाम, मैक्रो के name पैरामीटर से मेल खाने चाहिए. इसके अलावा, उनके नाम की शुरुआत में name के बाद _ (सुझाया गया), . या - होना चाहिए. उदाहरण के लिए, my_macro(name = "foo") से सिर्फ़ foo नाम की फ़ाइलें या टारगेट बनाए जा सकते हैं. इसके अलावा, इनके नाम की शुरुआत में foo_, foo- या foo. होना चाहिए. जैसे, foo_bar.
मैक्रो के नाम रखने से जुड़ी ज़रूरी शर्तों का उल्लंघन करने वाले टारगेट या फ़ाइलें, एलान की जा सकती हैं. हालांकि, इन्हें बनाया नहीं जा सकता और न ही इन्हें डिपेंडेंसी के तौर पर इस्तेमाल किया जा सकता है.
मैक्रो इंस्टेंस वाले एक ही पैकेज में मौजूद, मैक्रो के अलावा अन्य फ़ाइलों और टारगेट के नाम, मैक्रो के संभावित टारगेट के नामों से मेल नहीं खाने चाहिए. हालांकि, यह ज़रूरी नहीं है. हम सिंबॉलिक मैक्रो की परफ़ॉर्मेंस को बेहतर बनाने के लिए, लेज़ी इवैल्युएशन को लागू करने की प्रोसेस में हैं. नाम रखने के स्कीमा का उल्लंघन करने वाले पैकेज में, यह सुविधा काम नहीं करेगी.
पाबंदियां
लेगसी मैक्रो की तुलना में, सिंबॉलिक मैक्रो पर कुछ अतिरिक्त पाबंदियां हैं.
सिंबॉलिक मैक्रो
- में
nameआर्ग्युमेंट औरvisibilityआर्ग्युमेंट होना ज़रूरी है - में
implementationफ़ंक्शन होना ज़रूरी है - वैल्यू नहीं लौटा सकते
- अपने आर्ग्युमेंट में बदलाव नहीं कर सकते
native.existing_rules()को कॉल नहीं कर सकते, जब तक कि वे खासfinalizerमैक्रो न होंnative.package()को कॉल नहीं कर सकतेglob()को कॉल नहीं कर सकतेnative.environment_group()को कॉल नहीं कर सकते- ऐसे टारगेट बनाने होंगे जिनके नाम, नाम रखने के स्कीमा के मुताबिक हों
- इनपुट फ़ाइलों का रेफ़रंस नहीं ले सकते जिन्हें आर्ग्युमेंट के तौर पर पास नहीं किया गया है या जिनका एलान नहीं किया गया है
- अपने कॉलर के निजी टारगेट का रेफ़रंस नहीं ले सकते. ज़्यादा जानकारी के लिए, विज़िबिलिटी और मैक्रो देखें.
विज़िबिलिटी और मैक्रो
विज़िबिलिटी सिस्टम, (सिंबॉलिक) मैक्रो और उनके कॉलर, दोनों की लागू करने से जुड़ी जानकारी को सुरक्षित रखने में मदद करता है.
डिफ़ॉल्ट रूप से, सिंबॉलिक मैक्रो में बनाए गए टारगेट, मैक्रो में ही दिखते हैं. हालांकि, यह ज़रूरी नहीं है कि वे मैक्रो के कॉलर को भी दिखें. मैक्रो, किसी टारगेट को सार्वजनिक एपीआई के तौर पर "एक्सपोर्ट" कर सकता है. इसके लिए, वह अपने visibilityएट्रिब्यूट की वैल्यू को फ़ॉरवर्ड करता है. जैसे, some_rule(..., visibility = visibility).
मैक्रो की विज़िबिलिटी से जुड़े मुख्य आइडिया यहां दिए गए हैं:
विज़िबिलिटी की जांच, इस आधार पर की जाती है कि टारगेट का एलान किस मैक्रो ने किया है. न कि इस आधार पर कि मैक्रो को किस पैकेज ने कॉल किया है.
- दूसरे शब्दों में, एक ही पैकेज में होने से, एक टारगेट दूसरे को नहीं दिखता. इससे, मैक्रो के इंटरनल टारगेट को, पैकेज में मौजूद अन्य मैक्रो या टॉप-लेवल टारगेट की डिपेंडेंसी बनने से बचाया जा सकता है.
नियमों और मैक्रो, दोनों पर मौजूद सभी
visibilityएट्रिब्यूट में, उस जगह की जानकारी अपने-आप शामिल हो जाती है जहां नियम या मैक्रो को कॉल किया गया था.- इसलिए, कोई टारगेट, उसी मैक्रो में एलान किए गए अन्य टारगेट (या
BUILDफ़ाइल, अगर वह मैक्रो में नहीं है) को बिना किसी शर्त के दिखता है.
- इसलिए, कोई टारगेट, उसी मैक्रो में एलान किए गए अन्य टारगेट (या
असल में, इसका मतलब है कि जब कोई मैक्रो, visibility सेट किए बिना किसी टारगेट का एलान करता है, तो टारगेट डिफ़ॉल्ट रूप से मैक्रो के लिए इंटरनल होता है. (पैकेज की
डिफ़ॉल्ट विज़िबिलिटी मैक्रो में
लागू नहीं होती.) टारगेट को एक्सपोर्ट करने का मतलब है कि टारगेट, मैक्रो के कॉलर की ओर से मैक्रो के visibility एट्रिब्यूट में तय की गई जगह के साथ-साथ, मैक्रो के कॉलर के पैकेज और मैक्रो के अपने कोड को भी दिखता है.
इसे समझने का एक और तरीका यह है कि मैक्रो की विज़िबिलिटी से यह तय होता है कि मैक्रो के एक्सपोर्ट किए गए टारगेट को कौन देख सकता है. इसमें मैक्रो को शामिल नहीं किया जाता.
# tool/BUILD
...
some_rule(
name = "some_tool",
visibility = ["//macro:__pkg__"],
)
# macro/macro.bzl
def _impl(name, visibility):
cc_library(
name = name + "_helper",
...
# No visibility passed in. Same as passing `visibility = None` or
# `visibility = ["//visibility:private"]`. Visible to the //macro
# package only.
)
cc_binary(
name = name + "_exported",
deps = [
# Allowed because we're also in //macro. (Targets in any other
# instance of this macro, or any other macro in //macro, can see it
# too.)
name + "_helper",
# Allowed by some_tool's visibility, regardless of what BUILD file
# we're called from.
"//tool:some_tool",
],
...
visibility = visibility,
)
my_macro = macro(implementation = _impl, ...)
# pkg/BUILD
load("//macro:macro.bzl", "my_macro")
...
my_macro(
name = "foo",
...
)
some_rule(
...
deps = [
# Allowed, its visibility is ["//pkg:__pkg__", "//macro:__pkg__"].
":foo_exported",
# Disallowed, its visibility is ["//macro:__pkg__"] and
# we are not in //macro.
":foo_helper",
]
)
अगर my_macro को visibility = ["//other_pkg:__pkg__"] के साथ कॉल किया गया था या अगर
//pkg पैकेज ने अपनी default_visibility को उस वैल्यू पर सेट किया था, तो
//pkg:foo_exported का इस्तेमाल //other_pkg/BUILD में या
//other_pkg:defs.bzl में तय किए गए मैक्रो में भी किया जा सकता है. हालांकि, //pkg:foo_helper सुरक्षित रहेगा.
कोई मैक्रो, एलान कर सकता है कि कोई टारगेट, फ़्रेंड पैकेज को दिखे. इसके लिए, इंटरनल टारगेट के लिए
visibility = ["//some_friend:__pkg__"] या एक्सपोर्ट किए गए टारगेट के लिए
visibility = visibility + ["//some_friend:__pkg__"] पास करें.
ध्यान दें कि किसी मैक्रो के लिए, सार्वजनिक
विज़िबिलिटी (visibility = ["//visibility:public"]) के साथ किसी टारगेट का एलान करना, एक एंटीपैटर्न है. ऐसा इसलिए, क्योंकि इससे
टारगेट, हर पैकेज को बिना किसी शर्त के दिखता है. भले ही, कॉलर ने
ज़्यादा सीमित विज़िबिलिटी तय की हो.
विज़िबिलिटी की सभी जांच, फ़िलहाल चल रहे सबसे अंदरूनी सिंबॉलिक मैक्रो के हिसाब से की जाती है. हालांकि, विज़िबिलिटी डेलिगेशन का एक तरीका है: अगर कोई मैक्रो, किसी लेबल को इनर मैक्रो में एट्रिब्यूट वैल्यू के तौर पर पास करता है, तो इनर मैक्रो में लेबल के सभी इस्तेमाल की जांच, आउटर मैक्रो के हिसाब से की जाती है. ज़्यादा जानकारी के लिए, विज़िबिलिटी पेज देखें.
ध्यान रखें कि लेगसी मैक्रो, विज़िबिलिटी सिस्टम के लिए पूरी तरह से पारदर्शी होते हैं. साथ ही, वे ऐसे काम करते हैं जैसे कि उनकी जगह, वह BUILD फ़ाइल या सिंबॉलिक मैक्रो हो जहां से उन्हें कॉल किया गया था.
फ़ाइनलाइज़र और विज़िबिलिटी
नियम फ़ाइनलाइज़र में एलान किए गए टारगेट, सिंबॉलिक मैक्रो की विज़िबिलिटी के सामान्य नियमों के मुताबिक टारगेट देख सकते हैं. इसके अलावा, वे उन सभी टारगेट को भी देख सकते हैं जो फ़ाइनलाइज़र टारगेट के पैकेज को दिखते हैं.
इसका मतलब है कि अगर native.existing_rules() पर आधारित किसी लेगसी मैक्रो को फ़ाइनलाइज़र में माइग्रेट किया जाता है, तो फ़ाइनलाइज़र से एलान किए गए टारगेट, अपनी पुरानी डिपेंडेंसी को अब भी देख पाएंगे.
हालांकि, ध्यान दें कि सिंबॉलिक मैक्रो में किसी टारगेट का एलान इस तरह से किया जा सकता है कि फ़ाइनलाइज़र के टारगेट, विज़िबिलिटी सिस्टम के तहत उसे न देख पाएं. भले ही, फ़ाइनलाइज़र, native.existing_rules() का इस्तेमाल करके, उसके एट्रिब्यूट को इंट्रोस्पेक्ट कर सकता है.
Selects
अगर कोई एट्रिब्यूट configurable है (डिफ़ॉल्ट रूप से) और उसकी वैल्यू None नहीं है, तो मैक्रो लागू करने वाला फ़ंक्शन, एट्रिब्यूट की वैल्यू को एक सामान्य select में रैप करके देखेगा. इससे, मैक्रो के लेखक के लिए उन गड़बड़ियों को पकड़ना आसान हो जाता है जहां उन्हें यह उम्मीद नहीं थी कि एट्रिब्यूट की वैल्यू select हो सकती है.
उदाहरण के लिए, इस मैक्रो पर ध्यान दें:
my_macro = macro(
attrs = {"deps": attr.label_list()}, # configurable unless specified otherwise
implementation = _my_macro_impl,
)
अगर my_macro को deps = ["//a"] के साथ लागू किया जाता है, तो _my_macro_impl
को उसके deps पैरामीटर को select({"//conditions:default":
["//a"]}) पर सेट करके लागू किया जाएगा. अगर इससे लागू करने वाला फ़ंक्शन काम नहीं करता है (उदाहरण के लिए, क्योंकि कोड ने वैल्यू को deps[0] के तौर पर इंडेक्स करने की कोशिश की, जिसकी अनुमति select के लिए नहीं है), तो मैक्रो का लेखक इनमें से कोई एक विकल्प चुन सकता है: या तो वह अपने मैक्रो को फिर से लिखकर, सिर्फ़ select के साथ काम करने वाले ऑपरेशन का इस्तेमाल कर सकता है या वह एट्रिब्यूट को नॉन-कॉन्फ़िगरबल (attr.label_list(configurable = False)) के तौर पर मार्क कर सकता है. दूसरे विकल्प से यह पक्का होता है कि उपयोगकर्ताओं को select वैल्यू पास करने की अनुमति नहीं है.
नियम टारगेट, इस बदलाव को उलट देते हैं. साथ ही, सामान्य select को अपनी
बिना शर्त वाली वैल्यू के तौर पर सेव करते हैं. ऊपर दिए गए उदाहरण में, अगर _my_macro_impl नियम
टारगेट my_rule(..., deps = deps) का एलान करता है, तो उस नियम टारगेट के deps को
["//a"] के तौर पर सेव किया जाएगा. इससे यह पक्का होता है कि select-रैपिंग की वजह से, मैक्रो से इंस्टैंशिएट किए गए सभी टारगेट में, सामान्य select वैल्यू सेव नहीं होती हैं.
अगर कॉन्फ़िगरबल एट्रिब्यूट की वैल्यू None है, तो उसे select में रैप नहीं किया जाता. इससे यह पक्का होता है कि my_attr == None जैसे टेस्ट अब भी काम करते हैं. साथ ही, जब एट्रिब्यूट को कंप्यूट की गई डिफ़ॉल्ट वैल्यू वाले किसी नियम को फ़ॉरवर्ड किया जाता है, तो नियम सही तरीके से काम करता है. इसका मतलब है कि एट्रिब्यूट को पास नहीं किया गया है. यह ज़रूरी नहीं है कि किसी एट्रिब्यूट की वैल्यू हमेशा None हो. हालांकि, attr.label() टाइप और ज़रूरी नहीं होने वाले किसी भी इनहेरिट किए गए एट्रिब्यूट के लिए ऐसा हो सकता है.
फ़ाइनलाइज़र
नियम फ़ाइनलाइज़र, एक खास सिंबॉलिक मैक्रो होता है. इसे, पैकेज लोड करने के आखिरी चरण में, सभी नॉन-फ़ाइनलाइज़र टारगेट तय किए जाने के बाद लागू किया जाता है. भले ही, यह BUILD फ़ाइल में कहीं भी हो. सामान्य सिंबॉलिक मैक्रो के उलट, फ़ाइनलाइज़र, native.existing_rules() को कॉल कर सकता है. इसमें, यह लेगसी मैक्रो की तुलना में थोड़ा अलग तरीके से काम करता है: यह सिर्फ़ नॉन-फ़ाइनलाइज़र नियम टारगेट का सेट लौटाता है. फ़ाइनलाइज़र, उस सेट की स्थिति पर दावा कर सकता है या नए टारगेट तय कर सकता है.
फ़ाइनलाइज़र का एलान करने के लिए, finalizer = True के साथ macro() को कॉल करें:
def _my_finalizer_impl(name, visibility, tags_filter):
for r in native.existing_rules().values():
for tag in r.get("tags", []):
if tag in tags_filter:
my_test(
name = name + "_" + r["name"] + "_finalizer_test",
deps = [r["name"]],
data = r["srcs"],
...
)
continue
my_finalizer = macro(
attrs = {"tags_filter": attr.string_list(configurable = False)},
implementation = _impl,
finalizer = True,
)
Laziness
अहम जानकारी: हम लेज़ी मैक्रो एक्सपैंशन और इवैल्युएशन को लागू करने की प्रोसेस में हैं. फ़िलहाल, आपके लिए यह सुविधा उपलब्ध नहीं है.
फ़िलहाल, BUILD फ़ाइल लोड होते ही सभी मैक्रो का आकलन किया जाता है. इससे उन पैकेज में मौजूद टारगेट की परफ़ॉर्मेंस पर बुरा असर पड़ सकता है जिनमें महंगे और गैर-ज़रूरी मैक्रो भी मौजूद हैं. आने वाले समय में, नॉन-फ़ाइनलाइज़र सिंबॉलिक मैक्रो का आकलन सिर्फ़ तब किया जाएगा, जब वे बिल्ड के लिए ज़रूरी होंगे. प्रीफ़िक्स नेमिंग स्कीमा की मदद से, Bazel यह तय कर पाता है कि अनुरोध किए गए टारगेट के लिए, किस मैक्रो को एक्सपैंड करना है.
माइग्रेशन से जुड़ी समस्या हल करना
यहां माइग्रेशन से जुड़ी कुछ सामान्य समस्याएं और उन्हें ठीक करने का तरीका बताया गया है.
- लेगसी मैक्रो कॉल
glob()
glob() कॉल को अपनी BUILD फ़ाइल में ले जाएं. इसके अलावा, इसे BUILD फ़ाइल से कॉल किए गए किसी लेगसी मैक्रो में भी ले जाया जा सकता है. साथ ही, लेबल-लिस्ट एट्रिब्यूट का इस्तेमाल करके, glob() वैल्यू को सिंबॉलिक मैक्रो में पास करें:
# BUILD file
my_macro(
...,
deps = glob(...),
)
- लेगसी मैक्रो में ऐसा पैरामीटर है जो मान्य Starlark
attrटाइप नहीं है.
नेस्ट किए गए सिंबॉलिक मैक्रो में ज़्यादा से ज़्यादा लॉजिक डालें. हालांकि, टॉप लेवल मैक्रो को लेगसी मैक्रो ही रखें.
- लेगसी मैक्रो, ऐसे नियम को कॉल करता है जिससे ऐसा टारगेट बनता है जो नाम रखने के स्कीमा का उल्लंघन करता है
कोई बात नहीं, बस "उल्लंघन करने वाले" टारगेट पर निर्भर न रहें. नाम की जांच को चुपचाप अनदेखा कर दिया जाएगा.