.bzl स्टाइल गाइड

किसी समस्या की शिकायत करें सोर्स देखें Nightly · 7.4 .

इस पेज पर, Starlark के लिए स्टाइल से जुड़े बुनियादी दिशा-निर्देश दिए गए हैं. साथ ही, इसमें मैक्रो और नियमों के बारे में जानकारी भी दी गई है.

Starlark, एक ऐसी भाषा है जो सॉफ़्टवेयर बनाने का तरीका तय करती है. यह प्रोग्रामिंग और कॉन्फ़िगरेशन भाषा, दोनों है.

BUILD फ़ाइलों, मैक्रो, और बिल्ड के नियम लिखने के लिए, Starlark का इस्तेमाल किया जा सकता है. मैक्रो और नियम, मुख्य रूप से मेटा-भाषाएं होती हैं - ये तय करते हैं कि BUILD फ़ाइलें कैसे लिखी जाती हैं. BUILD फ़ाइलें आसान और बार-बार इस्तेमाल की जानी चाहिए.

किसी भी सॉफ़्टवेयर को लिखने के मुकाबले, उसे पढ़ा जाने की संख्या ज़्यादा होती है. ऐसा खास तौर पर Starlark के लिए सही है, क्योंकि इंजीनियर BUILD फ़ाइलों को पढ़ते हैं. इससे उन्हें अपने टारगेट और बिल्ड की जानकारी पर निर्भर करता है. यह रीडिंग अक्सर पास होने, जल्दी में या किसी दूसरे काम को पूरा करने के साथ-साथ हो जाती है. इसलिए, BUILD फ़ाइलों को आसानी से पढ़ा और समझा जा सके, इसके लिए यह ज़रूरी है कि वे आसान हों.

जब कोई उपयोगकर्ता BUILD फ़ाइल खोलता है, तो वह फ़ाइल में मौजूद टारगेट की सूची तुरंत जानना चाहता है. इसके अलावा, वह उस C++ लाइब्रेरी के सोर्स की सूची की समीक्षा करना चाहता है या उस Java बाइनरी से डिपेंडेंसी हटाना चाहता है. जब भी कोई एब्स्ट्रैक्शन लेयर जोड़ी जाती है, तो उपयोगकर्ता के लिए ये टास्क करना मुश्किल हो जाता है.

BUILD फ़ाइलों का विश्लेषण करने के साथ-साथ, उन्हें कई अलग-अलग टूल की मदद से अपडेट भी किया जाता है. अगर आपकी BUILD फ़ाइल में एब्स्ट्रैक्शन का इस्तेमाल किया गया है, तो हो सकता है कि टूल उसमें बदलाव न कर पाएं. BUILD फ़ाइलों को आसान रखने से, आपको बेहतर टूल मिल सकेगा. जैसे-जैसे कोड बेस बढ़ता जाता है, लाइब्रेरी को अपडेट करने या क्लीनअप करने के लिए, BUILD की कई फ़ाइलों में बार-बार बदलाव करना पड़ता है.

सामान्य सलाह

स्टाइल

Python स्टाइल

जब भी आपको पता न हो कि पीईपी 8 स्टाइल गाइड में दी गई जानकारी पढ़ें. खास तौर पर, Python के नियमों का पालन करने के लिए, इंडेंटेशन के लिए दो के बजाय चार स्पेस का इस्तेमाल करें.

Starlark, Python नहीं है. इसलिए, Python स्टाइल के कुछ पहलू लागू नहीं होते. उदाहरण के लिए, पीईपी 8 सलाह देता है कि सिंगलटन से तुलना is से की जाए, जो Starlark में ऑपरेटर नहीं है.

डॉकस्ट्रिंग

डॉस्ट्रिंग का इस्तेमाल करके, फ़ाइलों और फ़ंक्शन के बारे में जानकारी दें. हर .bzl फ़ाइल में सबसे ऊपर docstring और हर सार्वजनिक फ़ंक्शन के लिए एक docstring का इस्तेमाल करें.

दस्तावेज़ के नियम और पहलू

नियमों और पहलुओं, एट्रिब्यूट, सेवा देने वाली कंपनियों, और उनके फ़ील्ड के बारे में doc आर्ग्युमेंट में बताया जाना चाहिए.

नेमिंग कन्वेंशन

  • वैरिएबल और फ़ंक्शन के नामों में, अंडरस्कोर ([a-z][a-z0-9_]*) से अलग किए गए शब्दों के साथ छोटे अक्षरों का इस्तेमाल किया जाता है, जैसे कि cc_library.
  • टॉप-लेवल की निजी वैल्यू, एक अंडरस्कोर से शुरू होती हैं. Basel ने लागू किया कि अन्य फ़ाइलों से निजी वैल्यू का इस्तेमाल नहीं किया जा सकता. लोकल वैरिएबल को अंडरस्कोर प्रीफ़िक्स का इस्तेमाल नहीं करना चाहिए.

लाइन की लंबाई

BUILD फ़ाइलों की तरह, लाइन की लंबाई की कोई तय सीमा नहीं है, क्योंकि लेबल लंबे हो सकते हैं. जब मुमकिन हो, तब हर लाइन में ज़्यादा से ज़्यादा 79 वर्ण इस्तेमाल करने की कोशिश करें (Python की स्टाइल गाइड, PEP 8 के हिसाब से). इस दिशा-निर्देश को पूरी तरह से लागू नहीं करना चाहिए: एडिटर को 80 से ज़्यादा कॉलम दिखाने चाहिए, अपने-आप होने वाले बदलावों से बार-बार लंबी लाइनें दिखेंगी. साथ ही, लोगों को ऐसी लाइनों को बांटने में समय नहीं देना चाहिए जिन्हें पहले से पढ़ा जा सकता है.

कीवर्ड के तर्क

कीवर्ड आर्ग्युमेंट में, बराबर के निशान के आस-पास स्पेस का इस्तेमाल करें:

def fct(name, srcs):
    filtered_srcs = my_filter(source = srcs)
    native.cc_library(
        name = name,
        srcs = filtered_srcs,
        testonly = True,
    )

बूलियन मान

बूलियन वैल्यू के लिए (1 और 0 के बजाय) True और False वैल्यू को प्राथमिकता दें (जैसे, किसी नियम में बूलियन एट्रिब्यूट का इस्तेमाल करते समय).

प्रोडक्शन कोड में print() फ़ंक्शन का इस्तेमाल न करें. इसका मकसद सिर्फ़ डीबग करना है. साथ ही, यह आपकी .bzl फ़ाइल के सभी डायरेक्ट और इनडायरेक्ट उपयोगकर्ताओं को स्पैम भेज सकता है. इसका अपवाद सिर्फ़ यह है कि आप print() का इस्तेमाल करने वाला ऐसा कोड सबमिट कर सकते हैं जो डिफ़ॉल्ट रूप से बंद हो और इसे सिर्फ़ सोर्स में बदलाव करके ही चालू किया जा सकता हो. उदाहरण के लिए, अगर print() के सभी इस्तेमाल if DEBUG: से सुरक्षित होते हैं, जहां DEBUG को False के लिए हार्डकोड किया गया हो. इस बात का ध्यान रखें कि क्या ये स्टेटमेंट पढ़ने लायक हैं या नहीं, यह जानकारी देने के लिए सही हैं या नहीं.

मैक्रो

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

इस वजह से, जब कुछ गड़बड़ी होती है, तो उपयोगकर्ता को बिल्ड से जुड़ी समस्याओं को हल करने के लिए, आपके मैक्रो के लागू होने के तरीके को समझना होगा. इसके अलावा, bazel query के नतीजों को समझना मुश्किल हो सकता है, क्योंकि नतीजों में दिखाए गए टारगेट, मैक्रो एक्सपैंशन से मिलते हैं. आखिर में, ऐस्पेक्ट को मैक्रो के बारे में पता नहीं होता. इसलिए, ऐस्पेक्ट (IDE और अन्य) पर आधारित टूल काम नहीं कर सकते.

मैक्रो का सुरक्षित इस्तेमाल, अतिरिक्त टारगेट तय करने के लिए किया जाता है. इन टारगेट का रेफ़रंस, सीधे तौर पर Bazel CLI या BUILD फ़ाइलों में दिया जाता है: इस मामले में, सिर्फ़ उन टारगेट के असल उपयोगकर्ताओं को उनके बारे में पता होना चाहिए. साथ ही, मैक्रो के इस्तेमाल से होने वाली कोई भी बिल्ड समस्या, उनके इस्तेमाल से कभी भी दूर नहीं होती.

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

  • मैक्रो में name आर्ग्युमेंट होना चाहिए और उस नाम से टारगेट तय किया जाना चाहिए. वह टारगेट उस मैक्रो का मुख्य टारगेट बन जाता है.
  • जनरेट किए गए टारगेट, यानी मैक्रो से तय किए गए सभी अन्य टारगेट के लिए:
    • उनके नाम के आगे <name> या _<name> लगा हो. उदाहरण के लिए, name = '%s_bar' % (name) का इस्तेमाल करना.
    • प्रॉडक्ट सीमित लोगों को दिख रहे हों (//visibility:private), और
    • वाइल्डकार्ड टारगेट (:all, ..., :* वगैरह) में एक्सपैंशन से बचने के लिए, manual टैग का इस्तेमाल करें.
  • name का इस्तेमाल सिर्फ़ मैक्रो से तय किए गए टारगेट के नाम पाने के लिए किया जाना चाहिए, किसी और चीज़ के लिए नहीं. उदाहरण के लिए, किसी ऐसी डिपेंडेंसी या इनपुट फ़ाइल को जनरेट करने के लिए नाम का इस्तेमाल न करें जो मैक्रो से जनरेट नहीं होती.
  • मैक्रो में बनाए गए सभी टारगेट किसी न किसी तरह से मुख्य टारगेट के साथ जोड़े जाने चाहिए.
  • मैक्रो में पैरामीटर के नाम एक जैसे रखें. अगर किसी पैरामीटर को मुख्य टारगेट के लिए एट्रिब्यूट वैल्यू के तौर पर पास किया जाता है, तो उसका नाम पहले जैसा ही रखें. अगर कोई मैक्रो पैरामीटर, deps जैसे सामान्य नियम एट्रिब्यूट के मकसद के लिए काम करता है, तो उसे एट्रिब्यूट की तरह ही नाम दें (नीचे देखें).
  • मैक्रो कॉल करते समय, केवल कीवर्ड तर्क का उपयोग करें. यह नियमों के मुताबिक है और इसे पढ़ना आसान हो जाता है.

इंजीनियर अक्सर मैक्रो लिखते हैं, जब काम के नियमों का Starlark API, उनके इस्तेमाल के उदाहरण के लिए काफ़ी नहीं होता. भले ही, नियम को Bazel में नेटिव कोड या Starlark में तय किया गया हो. अगर आपको यह समस्या आ रही है, तो नियम बनाने वाले व्यक्ति से पूछें कि क्या वह आपके लक्ष्यों को पूरा करने के लिए एपीआई को बढ़ा सकता है.

आम तौर पर, जितने ज़्यादा मैक्रो नियमों से मिलते-जुलते होंगे उतना ही बेहतर होगा.

मैक्रो भी देखें.

नियम

  • नियमों, पहलुओं, और उनकी विशेषताओं के लिए, Low_case नाम ("स्नेक केस") का इस्तेमाल किया जाना चाहिए.
  • नियम के नाम ऐसे संज्ञा होते हैं जो नियम से जनरेट होने वाले मुख्य आर्टफ़ैक्ट के बारे में बताते हैं. यह जानकारी, नियम की डिपेंडेंसी (या लीफ़ नियमों के लिए, उपयोगकर्ता) के हिसाब से दी जाती है. यह ज़रूरी नहीं है कि यह फ़ाइल का सफ़िक्स हो. उदाहरण के लिए, C++ आर्टफ़ैक्ट जनरेट करने वाले नियम को py_extension कहा जा सकता है. इन आर्टफ़ैक्ट का इस्तेमाल, Python एक्सटेंशन के तौर पर किया जाता है. ज़्यादातर भाषाओं के लिए, सामान्य नियमों में ये शामिल हैं:
    • *_library - कंपाइलेशन यूनिट या "मॉड्यूल".
    • *_binary - ऐसा टारगेट जो किसी प्रोग्राम को चलाने लायक या डिप्लॉयमेंट यूनिट बनाता है.
    • *_test - टेस्ट टारगेट. इसमें एक से ज़्यादा टेस्ट शामिल हो सकते हैं. किसी *_test टारगेट में सभी जांच एक ही थीम के वैरिएशन होनी चाहिए. उदाहरण के लिए, किसी एक लाइब्रेरी को टेस्ट करना.
    • *_import: पहले से कंपाइल किए गए आर्टफ़ैक्ट को कवर करने वाला टारगेट, जैसे कि .jar या .dll, जिसका इस्तेमाल कंपाइलेशन के दौरान किया जाता है.
  • एट्रिब्यूट के लिए एक जैसे नाम और टाइप का इस्तेमाल करें. आम तौर पर, ये एट्रिब्यूट इस्तेमाल किए जाते हैं:
    • srcs: label_list, फ़ाइलों को अनुमति देना: सोर्स फ़ाइलें, आम तौर पर इन्हें लोग लिखते हैं.
    • deps: label_list, आम तौर पर फ़ाइलों को कंपाइल करने के लिए ज़रूरी डिपेंडेंसी को अनुमति नहीं दी जाती.
    • data: label_list, फ़ाइलों को अनुमति दी जा रही है: डेटा फ़ाइलों, जैसे कि टेस्ट डेटा वगैरह.
    • runtime_deps: label_list: रनटाइम डिपेंडेंसी, जिन्हें कंपाइल करने के लिए ज़रूरत नहीं होती.
  • बिना किसी अंतर वाले व्यवहार वाले किसी भी एट्रिब्यूट (उदाहरण के लिए, खास विकल्पों वाले स्ट्रिंग टेंप्लेट या खास शर्तों के साथ शुरू किए गए टूल) के लिए, एट्रिब्यूट की जानकारी (attr.label_list() या इससे मिलते-जुलते) का इस्तेमाल करके, doc कीवर्ड आर्ग्युमेंट का इस्तेमाल करके दस्तावेज़ दें.
  • नियम लागू करने वाले फ़ंक्शन करीब-करीब हमेशा निजी फ़ंक्शन होने चाहिए (जिनका नाम सबसे पहले अंडरस्कोर से दिया गया है). myrule के लिए लागू करने वाले फ़ंक्शन को _myrule_impl नाम देना, एक सामान्य स्टाइल है.
  • एक अच्छी तरह से तय provider इंटरफ़ेस का इस्तेमाल करके अपने नियमों के बीच जानकारी पास करें. प्रोवाइडर फ़ील्ड की जानकारी दें और उन्हें दस्तावेज़ में शामिल करें.
  • ज़्यादा इस्तेमाल करने की शर्तों को ध्यान में रखकर अपना नियम बनाएं. ध्यान रखें कि हो सकता है कि अन्य नियम आपके नियम के साथ इंटरैक्ट करना चाहें, आपके सेवा देने वालों को ऐक्सेस करना चाहें, और आपकी बनाई गई कार्रवाइयों का फिर से इस्तेमाल करना चाहें.
  • अपने नियमों में परफ़ॉर्मेंस से जुड़े दिशा-निर्देशों का पालन करें.