BUILD
फ़ाइल फ़ॉर्मैटिंग, Go के तरीके का ही पालन करती है. इसमें, फ़ॉर्मैट से जुड़ी ज़्यादातर समस्याओं को स्टैंडर्ड टूल हल करता है.
Buildifier एक ऐसा टूल है जो सोर्स कोड को स्टैंडर्ड स्टाइल में पार्स और उत्सर्जित करता है. इसलिए, हर BUILD
फ़ाइल को एक ही तरीके से अपने-आप फ़ॉर्मैट किया जाता है. इससे कोड की समीक्षा के दौरान, फ़ॉर्मैटिंग से जुड़ी कोई समस्या नहीं होती. इससे टूल के लिए, BUILD
फ़ाइलों को समझना, उनमें बदलाव करना, और जनरेट करना आसान हो जाता है.
BUILD
फ़ाइल का फ़ॉर्मैट, buildifier
के आउटपुट से मेल खाना चाहिए.
फ़ॉर्मैट करने का उदाहरण
# Test code implementing the Foo controller.
package(default_testonly = True)
py_test(
name = "foo_test",
srcs = glob(["*.py"]),
data = [
"//data/production/foo:startfoo",
"//foo",
"//third_party/java/jdk:jdk-k8",
],
flaky = True,
deps = [
":check_bar_lib",
":foo_data_check",
":pick_foo_port",
"//pyglib",
"//testing/pybase",
],
)
फ़ाइल का स्ट्रक्चर
सुझाव: नीचे दिए गए क्रम का इस्तेमाल करें (हर एलिमेंट ज़रूरी नहीं है):
पैकेज का ब्यौरा (एक टिप्पणी)
load()
के सभी स्टेटमेंटpackage()
फ़ंक्शन.नियमों और मैक्रो को कॉल करने की सुविधा
बिल्डिफ़ायर, स्टैंडअलोन टिप्पणी और किसी एलिमेंट से जुड़ी टिप्पणी के बीच फ़र्क़ करता है. अगर कोई टिप्पणी किसी खास एलिमेंट से नहीं जुड़ी है, तो उसके बाद खाली लाइन का इस्तेमाल करें. अपने-आप होने वाले बदलावों के लिए, इस अंतर को समझना ज़रूरी है. उदाहरण के लिए, किसी नियम को मिटाते समय टिप्पणी को बनाए रखना या हटाना.
# Standalone comment (such as to make a section in a file)
# Comment for the cc_library below
cc_library(name = "cc")
मौजूदा पैकेज में टारगेट के रेफ़रंस
फ़ाइलों को पैकेज डायरेक्ट्री के हिसाब से उनके पाथ से रेफ़र किया जाना चाहिए. इसके लिए, ..
जैसे अप-रेफ़रंस का इस्तेमाल कभी नहीं किया जाना चाहिए. जनरेट की गई फ़ाइलों के नाम के आगे ":
" लगाना चाहिए, ताकि यह पता चल सके कि वे सोर्स नहीं हैं. सोर्स फ़ाइलों के नाम के आगे :
नहीं होना चाहिए. नियमों की शुरुआत में :
होना चाहिए. उदाहरण के लिए, मान लें कि x.cc
एक सोर्स फ़ाइल है:
cc_library(
name = "lib",
srcs = ["x.cc"],
hdrs = [":gen_header"],
)
genrule(
name = "gen_header",
srcs = [],
outs = ["x.h"],
cmd = "echo 'int x();' > $@",
)
टारगेट का नाम
टारगेट के नाम, जानकारी देने वाले होने चाहिए. अगर किसी टारगेट में एक सोर्स फ़ाइल है, तो आम तौर पर टारगेट का नाम उस सोर्स से लिया जाना चाहिए. उदाहरण के लिए, chat.cc
के लिए cc_library
का नाम chat
हो सकता है या DirectMessage.java
के लिए java_library
का नाम direct_message
हो सकता है.
किसी पैकेज के लिए, उसी नाम वाला टारगेट (टारगेट का नाम, पैकेज में मौजूद डायरेक्ट्री के नाम से मेल खाना चाहिए) वही फ़ंक्शन उपलब्ध कराना चाहिए जो डायरेक्ट्री के नाम से पता चलता है. अगर ऐसा कोई टारगेट नहीं है, तो उसी नाम का टारगेट न बनाएं.
एक ही नाम वाले टारगेट का रेफ़रंस देते समय, छोटे नाम (//x:x
के बजाय //x
) का इस्तेमाल करें. अगर आप एक ही पैकेज में हैं, तो स्थानीय रेफ़रंस (//x
के बजाय :x
) का इस्तेमाल करें.
"रिज़र्व" किए गए ऐसे टारगेट नेम का इस्तेमाल करने से बचें जिनका कोई खास मतलब हो. इनमें all
, __pkg__
, और __subpackages__
शामिल हैं. इन नामों का खास मतलब होता है और इनका इस्तेमाल करने पर, भ्रम और अनचाहे व्यवहार हो सकते हैं.
अगर टीम के लिए कोई कन्वेंशन नहीं है, तो यहां कुछ ऐसे सुझाव दिए गए हैं जिनका पालन करना ज़रूरी नहीं है. हालांकि, Google में इनका ज़्यादातर इस्तेमाल किया जाता है:
- आम तौर पर, "snake_case" का इस्तेमाल करें
- एक
src
वालेjava_library
के लिए, इसका मतलब है कि ऐसे नाम का इस्तेमाल करना जो एक्सटेंशन के बिना फ़ाइल के नाम से अलग हो - Java
*_binary
और*_test
नियमों के लिए, "Upper CamelCase" का इस्तेमाल करें. इससे टारगेट का नाम,src
में से किसी एक से मैच हो जाता है.java_test
के लिए, इससे टारगेट के नाम सेtest_class
एट्रिब्यूट का अनुमान लगाया जा सकता है.
- एक
- अगर किसी खास टारगेट के कई वैरिएंट हैं, तो उन्हें अलग-अलग करने के लिए सफ़िक्स जोड़ें. जैसे,
:foo_dev
,:foo_prod
या:bar_x86
,:bar_x64
) _test
,_unittest
,Test
याTests
वाले_test
टारगेट को सफ़िक्स पर ले जाएं_lib
या_library
जैसे काम के न आने वाले सफ़िक्स इस्तेमाल करने से बचें. हालांकि,_library
टारगेट और उससे जुड़े_binary
के बीच टकराव से बचने के लिए, ऐसा करना ज़रूरी हो सकता है- प्रोटो से जुड़े टारगेट के लिए:
proto_library
टारगेट के नाम_proto
पर खत्म होने चाहिए- अलग-अलग भाषाओं के लिए
*_proto_library
के नियम, दिए गए प्रोटो से मेल खाने चाहिए. हालांकि,_proto
को भाषा के हिसाब से सफ़िक्स से बदल देना चाहिए, जैसे कि:cc_proto_library
:_cc_proto
java_proto_library
:_java_proto
java_lite_proto_library
:_java_proto_lite
किसको दिखे
विज़िबिलिटी का दायरा जितना हो सके उतना सटीक होना चाहिए. साथ ही, टेस्ट और रिवर्स डिपेंडेंसी से ऐक्सेस दिया जाना चाहिए. ज़रूरत के हिसाब से __pkg__
और __subpackages__
का इस्तेमाल करें.
पैकेज default_visibility
को //visibility:public
पर सेट करने से बचें.
//visibility:public
को प्रोजेक्ट के सार्वजनिक एपीआई में मौजूद टारगेट के लिए ही अलग से सेट किया जाना चाहिए. ये ऐसी लाइब्रेरी हो सकती हैं जिन्हें किसी बाहरी प्रोजेक्ट या बाइनरी पर निर्भर रहने के लिए डिज़ाइन किया गया है. इनका इस्तेमाल बाहरी प्रोजेक्ट की बिल्ड प्रोसेस में किया जा सकता है.
डिपेंडेंसी
डिपेंडेंसी को डायरेक्ट डिपेंडेंसी तक सीमित होना चाहिए (नियम में बताए गए सोर्स के लिए ज़रूरी डिपेंडेंसी). ट्रांज़िटिव डिपेंडेंसी शामिल न करें.
पैकेज-लोकल डिपेंडेंसी को सबसे पहले सूची में शामिल किया जाना चाहिए. साथ ही, इनका रेफ़रंस ऊपर दिए गए मौजूदा पैकेज में टारगेट के रेफ़रंस सेक्शन के मुताबिक होना चाहिए, न कि उनके पैकेज के पूरे नाम से.
डिपेंडेंसी को सीधे तौर पर, एक सूची के तौर पर शामिल करें. एक वैरिएबल में कई टारगेट की "सामान्य" डिपेंडेंसी डालने से रखरखाव में कमी आ जाती है और टूल के लिए टारगेट की डिपेंडेंसी को बदलना नामुमकिन हो जाता है. साथ ही, इसकी वजह से इस्तेमाल न होने वाली डिपेंडेंसी हो सकती है.
ग्लॉब
[]
का इस्तेमाल करके, "कोई टारगेट नहीं" दिखाएं. ऐसे ग्लोब का इस्तेमाल न करें जो किसी भी चीज़ से मेल न खाता हो: इससे गड़बड़ियों की संभावना ज़्यादा होती है और खाली सूची के मुकाबले यह कम काम का होता है.
बार-बार होने वाला
सोर्स फ़ाइलों से मिलान करने के लिए, बार-बार होने वाले ग्लोब का इस्तेमाल न करें (उदाहरण के लिए,
glob(["**/*.java"])
).
बार-बार इस्तेमाल होने वाले ग्लोब की वजह से, BUILD
फ़ाइलों को समझना मुश्किल हो जाता है, क्योंकि वे BUILD
फ़ाइलों वाली सबडायरेक्ट्री को स्किप कर देते हैं.
आम तौर पर, बार-बार इस्तेमाल होने वाले ग्लोब, हर डायरेक्ट्री में एक BUILD
फ़ाइल के मुकाबले कम असरदार होते हैं. ऐसा इसलिए, क्योंकि इनमें एक-दूसरे पर निर्भरता वाले ग्राफ़ को बेहतर तरीके से रिमोट कैश मेमोरी में सेव किया जा सकता है और एक साथ कई प्रोसेस की जा सकती हैं.
हर डायरेक्ट्री में एक BUILD
फ़ाइल बनाना और उनके बीच डिपेंडेंसी ग्राफ़ तय करना अच्छा होता है.
बार-बार नहीं होने वाला
आम तौर पर, नॉन-रेक्यूर्सिव ग्लोब स्वीकार किए जाते हैं.
अन्य कन्वेंशन
कॉन्सटेंट (जैसे,
GLOBAL_CONSTANT
) का एलान करने के लिए, अंग्रेज़ी के बड़े अक्षरों और अंडरस्कोर का इस्तेमाल करें. वैरिएबल (जैसे,my_variable
) का एलान करने के लिए, अंग्रेज़ी के छोटे अक्षरों और अंडरस्कोर का इस्तेमाल करें.लेबल को कभी भी अलग-अलग नहीं किया जाना चाहिए. भले ही, वे 79 से ज़्यादा वर्णों के हों. जहां तक हो सके, लेबल स्ट्रिंग लिटरल होने चाहिए. वजह: इससे, टेक्स्ट में किसी शब्द को ढूंढना और बदलना आसान हो जाता है. इससे कॉन्टेंट को पढ़ना भी आसान हो जाता है.
नाम एट्रिब्यूट की वैल्यू, मैक्रो को छोड़कर, लिटरल कॉन्स्टेंट स्ट्रिंग होनी चाहिए. वजह: बाहरी टूल, किसी नियम का रेफ़रंस देने के लिए नाम एट्रिब्यूट का इस्तेमाल करते हैं. उन्हें कोड को समझे बिना नियम ढूंढने होंगे.
बूलियन-टाइप एट्रिब्यूट सेट करते समय, बूलियन वैल्यू का इस्तेमाल करें, न कि पूर्णांक वैल्यू का. लेगसी वजहों से, नियम अब भी ज़रूरत के हिसाब से पूर्णांकों को बूलियन में बदलते हैं. हालांकि, ऐसा करने का सुझाव नहीं दिया जाता. वजह:
flaky = 1
को गलत तरीके से पढ़ा जा सकता है, जैसे कि "इस टारगेट को फिर से चलाकर, इसे डिफ़्लेक करें".flaky = True
साफ़ तौर पर कहता है कि "यह टेस्ट ठीक से काम नहीं करता".
Python स्टाइल गाइड के साथ अंतर
हालांकि, एक लक्ष्य Python स्टाइल गाइड के साथ काम करना है, लेकिन इनमें कुछ अंतर हैं:
लाइन की लंबाई पर कोई पाबंदी नहीं है. लंबी टिप्पणियों और लंबी स्ट्रिंग को अक्सर 79 कॉलम में बांटा जाता है. हालांकि, ऐसा करना ज़रूरी नहीं है. इसे कोड की समीक्षाओं या सबमिट करने से पहले की जाने वाली स्क्रिप्ट में लागू नहीं किया जाना चाहिए. ज़रूरी वजह: लेबल लंबे हो सकते हैं और तय सीमा से ज़्यादा हो सकते हैं. आम तौर पर,
BUILD
फ़ाइलों को टूल की मदद से जनरेट किया जाता है या उनमें बदलाव किया जाता है. ऐसा करने पर, लाइन की लंबाई की सीमा का पालन नहीं किया जा सकता.इंप्लिसिट स्ट्रिंग कनेक्शन की सुविधा काम नहीं करती.
+
ऑपरेटर का इस्तेमाल करें. खास जानकारी:BUILD
फ़ाइलों में कई स्ट्रिंग की सूचियां होती हैं. कॉमा को आसानी से भूल जाया जा सकता है. इससे नतीजा पूरी तरह से अलग हो जाता है. इस गड़बड़ी की वजह से, पहले कई गड़बड़ियां हुई हैं. यह चर्चा भी देखें.नियमों में कीवर्ड आर्ग्युमेंट के लिए,
=
साइन के आस-पास स्पेस का इस्तेमाल करें. वजह: नाम वाले आर्ग्युमेंट, Python के मुकाबले ज़्यादा इस्तेमाल किए जाते हैं और ये हमेशा अलग लाइन में होते हैं. स्पेसेज़ का इस्तेमाल करके, कॉन्टेंट को आसानी से पढ़ा जा सकता है. यह कॉन्वेंशन काफ़ी समय से है और सभी मौजूदाBUILD
फ़ाइलों में बदलाव करना सही नहीं है.डिफ़ॉल्ट रूप से, स्ट्रिंग के लिए डबल कोटेशन मार्क का इस्तेमाल करें. वजह: Python स्टाइल गाइड में इस बारे में जानकारी नहीं दी गई है. हालांकि, इसमें एक जैसा इस्तेमाल करने का सुझाव दिया गया है. इसलिए, हमने सिर्फ़ डबल कोट वाली स्ट्रिंग का इस्तेमाल करने का फ़ैसला लिया है. कई भाषाओं में, स्ट्रिंग लिटरल के लिए डबल कोट का इस्तेमाल किया जाता है.
दो टॉप-लेवल डेफ़िनिशन के बीच एक खाली लाइन का इस्तेमाल करें. खास जानकारी: किसी
BUILD
फ़ाइल का स्ट्रक्चर, किसी आम Python फ़ाइल की तरह नहीं होता. इसमें सिर्फ़ टॉप-लेवल के स्टेटमेंट होते हैं. एक खाली लाइन का इस्तेमाल करने से,BUILD
फ़ाइलें छोटी हो जाती हैं.