इस पेज पर, मैक्रो इस्तेमाल करने के बारे में बुनियादी जानकारी दी गई है. साथ ही, इसमें इस्तेमाल के सामान्य उदाहरण, डीबग करने का तरीका, और नियम शामिल हैं.
मैक्रो, BUILD
फ़ाइल से कॉल किया गया एक फ़ंक्शन होता है. यह नियमों को इंस्टैंशिएट कर सकता है.
मैक्रो का इस्तेमाल मुख्य रूप से, मौजूदा नियमों और अन्य मैक्रो के इनकैप्सुलेशन और कोड को फिर से इस्तेमाल करने के लिए किया जाता है.
मैक्रो दो तरह के होते हैं: सिंबल वाले मैक्रो, जिनके बारे में इस पेज पर बताया गया है. इसके अलावा, लेगसी मैक्रो भी होते हैं. हमारा सुझाव है कि जहां भी हो सके वहां कोड को समझने में आसानी के लिए, सिंबॉलिक मैक्रो का इस्तेमाल करें.
सिंबॉलिक मैक्रो, टाइप किए गए आर्ग्युमेंट (स्ट्रिंग से लेबल कन्वर्ज़न, जहां मैक्रो को कॉल किया गया था उसके हिसाब से) उपलब्ध कराते हैं. साथ ही, बनाए गए टारगेट की विज़िबिलिटी को सीमित करने और तय करने की सुविधा देते हैं. इन्हें लेज़ी इवैलुएशन के हिसाब से डिज़ाइन किया गया है. यह सुविधा, Bazel के आने वाले वर्शन में जोड़ी जाएगी. सिंबॉलिक मैक्रो, Bazel 8 में डिफ़ॉल्ट रूप से उपलब्ध होते हैं. इस दस्तावेज़ में जहां भी macros
का ज़िक्र किया गया है वहां इसका मतलब सिंबॉलिक मैक्रो से है.
सिंबॉलिक मैक्रो के काम करने का उदाहरण, उदाहरणों वाली रिपॉज़िटरी में देखा जा सकता है.
इस्तेमाल
मैक्रो को .bzl
फ़ाइलों में तय किया जाता है. इसके लिए, macro()
फ़ंक्शन को दो ज़रूरी पैरामीटर attrs
और implementation
के साथ कॉल किया जाता है.
विशेषताएं
attrs
, एट्रिब्यूट के नाम से लेकर attribute
types तक की डिक्शनरी स्वीकार करता है. यह मैक्रो के आर्ग्युमेंट को दिखाता है. दो सामान्य एट्रिब्यूट – 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
पैरामीटर को भी स्वीकार करते हैं. इससे यह तय होता है कि एट्रिब्यूट, configurable
को स्वीकार करता है या नहीं.select
अगर कोई एट्रिब्यूट configurable
है, तो यह select
नहीं है, तो वैल्यू को पार्स करेगा. select
को कॉन्फ़िगर नहीं किया जा सकता – "foo"
, select({"//conditions:default": "foo"})
बन जाएगा. चुने गए में जाकर, इसके बारे में ज़्यादा जानें.
एट्रिब्यूट इनहेरिटेंस
मैक्रो का इस्तेमाल अक्सर किसी नियम (या दूसरे मैक्रो) को रैप करने के लिए किया जाता है. साथ ही, मैक्रो का लेखक अक्सर रैप किए गए सिंबल के ज़्यादातर एट्रिब्यूट को बिना किसी बदलाव के, मैक्रो के मुख्य टारगेट (या मुख्य इनर मैक्रो) को फ़ॉरवर्ड करना चाहता है. इसके लिए, वह **kwargs
का इस्तेमाल करता है.
इस पैटर्न को सपोर्ट करने के लिए, कोई मैक्रो किसी नियम या दूसरे मैक्रो से एट्रिब्यूट इनहेरिट कर सकता है. इसके लिए, macro()
के inherit_attrs
आर्ग्युमेंट में नियम या मैक्रो सिंबल पास करें. (सभी Starlark बिल्ड नियमों के लिए तय किए गए सामान्य एट्रिब्यूट इनहेरिट करने के लिए, नियम या मैक्रो सिंबल के बजाय खास स्ट्रिंग "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
पर सेट होती है. भले ही, एट्रिब्यूट की मूल परिभाषा की डिफ़ॉल्ट वैल्यू कुछ भी हो. अगर आपको इनहेरिट किए गए किसी ऐसे एट्रिब्यूट की जांच करनी है या उसमें बदलाव करना है जो ज़रूरी नहीं है, तो आपको अपने मैक्रो के लागू करने वाले फ़ंक्शन में tags
केस को हैंडल करना होगा. उदाहरण के लिए, अगर आपको इनहेरिट किए गए tags
एट्रिब्यूट में कोई टैग जोड़ना है, तो आपको यह काम करना होगा:None
# 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
फ़ाइल में उनकी परिभाषा को लोड करके और कॉल करके किया जाता है.
# 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
नाम की फ़ाइलें या टारगेट बना सकता है. इसके अलावा, my_macro(name = "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()
का इस्तेमाल करके, अपने एट्रिब्यूट की जांच कर सकता हो.
चुनता है
अगर किसी एट्रिब्यूट को 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()
को कॉल कर सकता है. हालांकि, लेगसी मैक्रो में यह थोड़ा अलग तरीके से काम करता है: यह सिर्फ़ नॉन-फ़ाइनलाइज़र नियम के टारगेट का सेट दिखाता है. फ़ाइनलाइज़र, उस सेट की स्थिति पर दावा कर सकता है या नए टारगेट तय कर सकता है.
फ़ाइनलाइज़र तय करने के लिए, macro()
को macro()
के साथ कॉल करें:finalizer = True
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,
)
आलस
अहम जानकारी: हम लेज़ी मैक्रो एक्सपैंशन और आकलन को लागू करने की प्रोसेस में हैं. यह सुविधा फ़िलहाल उपलब्ध नहीं है.
फ़िलहाल, BUILD फ़ाइल लोड होते ही सभी मैक्रो का आकलन किया जाता है. इससे उन पैकेज के टारगेट की परफ़ॉर्मेंस पर बुरा असर पड़ सकता है जिनमें महंगे और काम के न होने वाले मैक्रो भी शामिल हैं. आने वाले समय में, नॉन-फ़ाइनलाइज़र सिंबॉलिक मैक्रो का आकलन सिर्फ़ तब किया जाएगा, जब वे बिल्ड के लिए ज़रूरी हों. प्रीफ़िक्स नेमिंग स्कीमा की मदद से, Bazel यह तय कर पाता है कि अनुरोध किए गए टारगेट के लिए, किस मैक्रो को बड़ा करना है.
माइग्रेशन से जुड़ी समस्या हल करना
यहां माइग्रेट करने से जुड़ी कुछ सामान्य समस्याएं और उन्हें ठीक करने का तरीका बताया गया है.
- लेगसी मैक्रो कॉल
glob()
glob()
कॉल को अपनी BUILD फ़ाइल में ले जाएं. इसके अलावा, इसे BUILD फ़ाइल से कॉल किए गए लेगसी मैक्रो में भी ले जाया जा सकता है. साथ ही, लेबल-लिस्ट एट्रिब्यूट का इस्तेमाल करके, glob()
वैल्यू को सिंबॉलिक मैक्रो में पास करें:
# BUILD file
my_macro(
...,
deps = glob(...),
)
- लेगसी मैक्रो में ऐसा पैरामीटर है जो मान्य स्टार्लार्क
attr
टाइप नहीं है.
ज़्यादा से ज़्यादा लॉजिक को नेस्ट किए गए सिंबॉलिक मैक्रो में डालें. हालांकि, टॉप लेवल के मैक्रो को लेगसी मैक्रो के तौर पर रखें.
- लेगसी मैक्रो, ऐसे नियम को कॉल करता है जो नाम रखने के तरीके का उल्लंघन करने वाला टारगेट बनाता है
कोई बात नहीं, बस "नीति का उल्लंघन करने वाले" टारगेट पर निर्भर न रहें. नाम की जांच को अनदेखा कर दिया जाएगा.