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

समस्या की शिकायत करें सोर्स देखें ठीक

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

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

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

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

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

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

सामान्य सलाह

स्टाइल

Python स्टाइल

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

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

डॉकस्ट्रिंग

docstrings का इस्तेमाल करके, फ़ाइलों और फ़ंक्शन के बारे में जानकारी देना. हर .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 के लिए हार्डकोड किया गया हो. इस बात का ध्यान रखें कि क्या ये स्टेटमेंट पढ़ने लायक हैं या नहीं, यह जानकारी देने के लिए सही है या नहीं.

मैक्रो

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

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

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

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

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

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

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

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

नियम

  • नियमों, पहलुओं, और उनकी विशेषताओं के लिए, Low_case नाम ("स्नेक केस") का इस्तेमाल किया जाना चाहिए.
  • नियम के नाम ऐसी संज्ञा होते हैं जो नियम के बनाए हुए मुख्य आर्टफ़ैक्ट के बारे में बताते हैं. नियम की डिपेंडेंसी के हिसाब से (या लीफ़ रूल इस्तेमाल करने के लिए, नियम का इस्तेमाल किया जाता है). यह ज़रूरी नहीं है कि यह फ़ाइल सफ़िक्स हो. उदाहरण के लिए, किसी ऐसे नियम को py_extension कहा जा सकता है जो Python एक्सटेंशन के तौर पर इस्तेमाल करने के लिए C++ आर्टफ़ैक्ट बनाता है. ज़्यादातर भाषाओं के लिए, सामान्य नियमों में ये शामिल हैं:
    • *_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 इंटरफ़ेस का इस्तेमाल करके अपने नियमों के बीच जानकारी पास करें. दस्तावेज़ देने वाले फ़ील्ड का एलान करें.
  • ज़्यादा इस्तेमाल करने की शर्तों को ध्यान में रखकर अपना नियम बनाएं. यह सोचें कि दूसरे नियम शायद आपके नियम के साथ इंटरैक्ट करना, आपकी सेवा देने वाली कंपनियों को ऐक्सेस करना, और आपकी बनाई गई कार्रवाइयों का फिर से इस्तेमाल करना चाहें.
  • अपने नियमों में दिए गए परफ़ॉर्मेंस के दिशा-निर्देशों का पालन करें.