मैक्रो

किसी समस्या की शिकायत करें सोर्स देखें रात · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

इस पृष्ठ में मैक्रो के उपयोग की बुनियादी बातें दी गई हैं और इसमें सामान्य उपयोग के उदाहरण दिए गए हैं, डीबग करने की प्रोसेस, और कंवेंशन.

मैक्रो BUILD फ़ाइल से कॉल किया जाने वाला फ़ंक्शन होता है, जो नियमों को इंस्टैंशिएट कर सकता है. मैक्रो का इस्तेमाल मुख्य रूप से एनकैप्सुलेशन के लिए और मौजूदा नियमों को कोड को दोबारा इस्तेमाल करने के लिए किया जाता है और अन्य मैक्रो शामिल हैं. आखिर में लोड होने का चरण, मैक्रो अब मौजूद नहीं होते, और Basel को इंस्टैंशिएट किए गए नियमों का सिर्फ़ ठोस सेट ही दिखता है.

इस्तेमाल

आम तौर पर, मैक्रो के इस्तेमाल का उदाहरण तब होता है, जब आपको किसी नियम का फिर से इस्तेमाल करना हो.

उदाहरण के लिए, BUILD फ़ाइल में जेन रूल इस्तेमाल करने पर, निर्देश में हार्डकोड किया गया some_arg तर्क वाला //:generator:

genrule(
    name = "file",
    outs = ["file.txt"],
    cmd = "$(location //:generator) some_arg > $@",
    tools = ["//:generator"],
)

अगर आपको अलग-अलग आर्ग्युमेंट के साथ ज़्यादा फ़ाइलें जनरेट करनी हैं, तो इस कोड को मैक्रो फ़ंक्शन में एक्सट्रैक्ट करें. चलिए, मैक्रो file_generator को कॉल करते हैं, जो इसमें name और arg पैरामीटर हैं. जेनरूल को इससे बदलें:

load("//path:generator.bzl", "file_generator")

file_generator(
    name = "file",
    arg = "some_arg",
)

file_generator(
    name = "file-two",
    arg = "some_arg_two",
)

file_generator(
    name = "file-three",
    arg = "some_arg_three",
)

यहां, आप .bzl मौजूद फ़ाइल से file_generator सिंबल लोड करते हैं //path पैकेज में. मैक्रो फ़ंक्शन की परिभाषाएं अलग .bzl फ़ाइल, आप अपनी BUILD फ़ाइलों को साफ़ और घोषणा के तौर पर रखते हैं, .bzl फ़ाइल को फ़ाइल फ़ोल्डर में किसी भी पैकेज से लोड किया जा सकता है.

आखिर में, path/generator.bzl में मैक्रो की परिभाषा ओरिजनल जेनरल डेफ़िनिशन को इनकैप्सुलेट और पैरामीटर के तौर पर पेश करता है:

def file_generator(name, arg, visibility=None):
  native.genrule(
    name = name,
    outs = [name + ".txt"],
    cmd = "$(location //:generator) %s > $@" % arg,
    tools = ["//:generator"],
    visibility = visibility,
  )

नियमों को एक साथ चेन करने के लिए, मैक्रो का भी इस्तेमाल किया जा सकता है. इस उदाहरण में एक के बाद एक कई जेनरूल में, पिछले जेनरूल के आउटपुट को इनपुट के तौर पर इस्तेमाल किया जाता है:

def chained_genrules(name, visibility=None):
  native.genrule(
    name = name + "-one",
    outs = [name + ".one"],
    cmd = "$(location :tool-one) $@",
    tools = [":tool-one"],
    visibility = ["//visibility:private"],
  )

  native.genrule(
    name = name + "-two",
    srcs = [name + ".one"],
    outs = [name + ".two"],
    cmd = "$(location :tool-two) $< $@",
    tools = [":tool-two"],
    visibility = visibility,
  )

उदाहरण में, दूसरे जनरेशन के नियम के लिए सिर्फ़ 'किसको दिखे' वैल्यू असाइन की गई है. इससे आपको इंटरमीडिएट नियमों के आउटपुट को छिपाने के लिए मैक्रो लेखक टारगेट के हिसाब से.

मैक्रो को बड़ा करना

यह पता लगाने के लिए कि मैक्रो क्या करता है, query कमांड का इस्तेमाल बड़ा किया गया फ़ॉर्म देखने के लिए --output=build:

$ bazel query --output=build :file
# /absolute/path/test/ext.bzl:42:3
genrule(
  name = "file",
  tools = ["//:generator"],
  outs = ["//test:file.txt"],
  cmd = "$(location //:generator) some_arg > $@",
)

नेटिव नियमों को लागू किया जा रहा है

नेटिव नियम (ऐसे नियम जिनके लिए load() स्टेटमेंट की ज़रूरत नहीं होती) नेटिव मॉड्यूल से इंस्टैंशिएट किया गया:

def my_macro(name, visibility=None):
  native.cc_library(
    name = name,
    srcs = ["main.cc"],
    visibility = visibility,
  )

अगर आपको पैकेज का नाम जानने की ज़रूरत है (उदाहरण के लिए, कौनसी BUILD फ़ाइल मैक्रो) को इंस्टॉल करने के लिए, native.package_name() फ़ंक्शन का इस्तेमाल करना होगा. ध्यान दें कि native का इस्तेमाल सिर्फ़ .bzl फ़ाइलों में किया जा सकता है, BUILD फ़ाइलों में नहीं.

मैक्रो में लेबल रिज़ॉल्यूशन

मैक्रो का आकलन लोड करने के चरण में किया जाता है. इसलिए, मैक्रो में मौजूद "//foo:bar" जैसी लेबल स्ट्रिंग की व्याख्या की जाती है उस BUILD फ़ाइल के सापेक्ष जिसमें मैक्रो का उपयोग किया जाता है, न कि वह .bzl फ़ाइल जिसमें उसे परिभाषित किया गया है. ऐसा व्यवहार आमतौर पर अवांछनीय होता है ऐसे मैक्रो के लिए जिन्हें अन्य डेटा स्टोर करने की जगहों में इस्तेमाल किया जाना है. उदाहरण के लिए, Starlark के पब्लिश किए गए नियमों का हिस्सा हैं.

स्टारलार्क के नियमों जैसा ही व्यवहार पाने के लिए, लेबल स्ट्रिंग को Label कंस्ट्रक्टर:

# @my_ruleset//rules:defs.bzl
def my_cc_wrapper(name, deps = [], **kwargs):
  native.cc_library(
    name = name,
    deps = deps + select({
      # Due to the use of Label, this label is resolved within @my_ruleset,
      # regardless of its site of use.
      Label("//config:needs_foo"): [
        # Due to the use of Label, this label will resolve to the correct target
        # even if the canonical name of @dep_of_my_ruleset should be different
        # in the main repo, such as due to repo mappings.
        Label("@dep_of_my_ruleset//tools:foo"),
      ],
      "//conditions:default": [],
    }),
    **kwargs,
  )

डीबग करना

  • bazel query --output=build //my/path:all आपको दिखाएगा कि BUILD फ़ाइल आकलन करती है. सभी मैक्रो, ग्लब, लूप विस्तृत किए जाते हैं. जाने-पहचाने संपर्क सीमा: select एक्सप्रेशन, फ़िलहाल आउटपुट में नहीं दिखाए गए हैं.

  • आउटपुट को generator_function (यह फ़ंक्शन किस काम करता है) के हिसाब से फ़िल्टर किया जा सकता है नियम जनरेट किए हैं) या generator_name (मैक्रो का नाम एट्रिब्यूट): bash $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)'

  • BUILD फ़ाइल में foo नियम कहां जनरेट हुआ है, यह जानने के लिए आपको नीचे दी गई ट्रिक आज़मा सकते हैं. BUILD के ऊपरी हिस्से के पास यह लाइन डालें फ़ाइल: cc_library(name = "foo"). रन बेज़ल. आपको अपवाद तब मिलेगा, जब नियम foo बनाया गया है (नाम मेल नहीं खाने की वजह से), जिससे आपको पता चलेगा कि फ़ुल स्टैक ट्रेस चुनें.

  • डीबग करने के लिए, प्रिंट का इस्तेमाल भी किया जा सकता है. यह लोड होने के दौरान, DEBUG लॉग लाइन के तौर पर मैसेज. अपवाद के तौर पर केस, या तो print कॉल निकालें या उन्हें debugging पैरामीटर, जो कोड को सबमिट करने से पहले डिफ़ॉल्ट रूप से False पर सेट होता है डिपो.

गड़बड़ियां

अगर आपको कोई गड़बड़ी करनी है, तो fail फ़ंक्शन का इस्तेमाल करें. उपयोगकर्ता को साफ़ तौर पर बताएं कि क्या गड़बड़ी हुई और उनकी BUILD फ़ाइल को कैसे ठीक करें. गड़बड़ी का पता लगाना संभव नहीं है.

def my_macro(name, deps, visibility=None):
  if len(deps) < 2:
    fail("Expected at least two values in deps")
  # ...

सम्मेलन

  • वे सभी पब्लिक फ़ंक्शन (वे फ़ंक्शन जो अंडरस्कोर से शुरू नहीं होते) जो इंस्टैंशिएट के नियमों में name आर्ग्युमेंट होना चाहिए. यह तर्क वैकल्पिक (डिफ़ॉल्ट वैल्यू न दें).

  • सार्वजनिक फ़ंक्शन को Python के बाद मौजूद docstring का इस्तेमाल करना चाहिए कन्वेंशन में बदल सकते हैं.

  • BUILD फ़ाइलों में, मैक्रो का name आर्ग्युमेंट एक कीवर्ड होना चाहिए आर्ग्युमेंट (न कि पोज़िशनल आर्ग्युमेंट).

  • मैक्रो के ज़रिए जनरेट किए गए नियमों की name एट्रिब्यूट में नाम शामिल होना चाहिए तर्क का इस्तेमाल करें. उदाहरण के लिए, macro(name = "foo") cc_library foo और जेनरुल foo_gen.

  • ज़्यादातर मामलों में, वैकल्पिक पैरामीटर की डिफ़ॉल्ट वैल्यू None होनी चाहिए. None को सीधे नेटिव नियमों के पास भेजा जा सकता है. जो इसे उसी तरह से देखते हैं आपने किसी भी तर्क में पास नहीं किया. इसलिए, इसे बदलने की ज़रूरत नहीं है इस उद्देश्य के लिए 0, False या [] के साथ. इसके बजाय, मैक्रो को स्थगित कर देना चाहिए रखता है, क्योंकि डिफ़ॉल्ट सेटिंग जटिल हो सकती है या पूरी तरह बदल सकती है समय. इसके अलावा, एक ऐसा पैरामीटर जो साफ़ तौर पर अपनी डिफ़ॉल्ट वैल्यू पर सेट होता है उस आईडी से अलग दिखता है जिसे ऐक्सेस किए जाने पर, कभी भी सेट नहीं किया जाता या None पर सेट नहीं किया जाता क्वेरी लैंग्वेज या बिल्ड-सिस्टम इंटर्नल के ज़रिए

  • मैक्रो में एक वैकल्पिक visibility तर्क होना चाहिए.