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

किसी समस्या की शिकायत करना सोर्स देखना Nightly · 8.0 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

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

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

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

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

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

सामान्य सलाह

स्टाइल

Python स्टाइल

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

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

डॉकस्ट्रिंग

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

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

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

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

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

लाइन की लंबाई

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() डिफ़ॉल्ट रूप से बंद हो और उसे सिर्फ़ सोर्स में बदलाव करके चालू किया जा सकता हो. उदाहरण के लिए, अगर print() के सभी इस्तेमाल को if DEBUG: से सुरक्षित किया गया हो, जहां DEBUG को False में हार्डकोड किया गया हो. ध्यान रखें कि ये स्टेटमेंट, पढ़ने में आसानी पर पड़ने वाले असर को सही ठहराने के लिए ज़रूरत के मुताबिक काम के हों.

मैक्रो

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

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

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

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

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

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

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

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

नियम

  • नियमों, पहलुओं, और उनके एट्रिब्यूट के लिए, lower_case नाम ("snake 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 नाम दिया जाता है.
  • अच्छी तरह से तय किए गए प्रोवाइडर इंटरफ़ेस का इस्तेमाल करके, अपने नियमों के बीच जानकारी पास करें. प्रोवाइडर फ़ील्ड की जानकारी दें और उन्हें दस्तावेज़ में शामिल करें.
  • अपने नियम को इस तरह से डिज़ाइन करें कि उसे आगे बढ़ाया जा सके. ध्यान रखें कि हो सकता है कि अन्य नियम आपके नियम के साथ इंटरैक्ट करना चाहें, आपके सेवा देने वालों को ऐक्सेस करना चाहें, और आपकी बनाई गई कार्रवाइयों का फिर से इस्तेमाल करना चाहें.
  • अपने नियमों में परफ़ॉर्मेंस से जुड़े दिशा-निर्देशों का पालन करें.