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()फ़ंक्शन.नियमों और मैक्रो के लिए कॉल
Buildifier, स्टैंडअलोन टिप्पणी और किसी एलिमेंट से जुड़ी टिप्पणी के बीच अंतर करता है. अगर कोई टिप्पणी किसी खास एलिमेंट से जुड़ी नहीं है, तो उसके बाद एक खाली लाइन का इस्तेमाल करें. ऑटोमैटिक तरीके से बदलाव करते समय, यह अंतर ज़रूरी होता है. उदाहरण के लिए, किसी नियम को मिटाते समय टिप्पणी को बनाए रखना या हटाना.
# 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();' > $@",
)
टारगेट का नामकरण
टारगेट के नाम जानकारी देने वाले होने चाहिए. अगर किसी टारगेट में एक सोर्स फ़ाइल है,
तो आम तौर पर टारगेट का नाम उस सोर्स से लिया जाना चाहिए. उदाहरण के लिए,
cc_library के लिए chat.cc का नाम chat हो सकता है या java_library के लिए
DirectMessage.java का नाम 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` सफ़िक्स वाले टारगेट में `_test`, `_unittest`, `Test`, या `Tests` सफ़िक्स जोड़ें - ऐसे सफ़िक्स का इस्तेमाल न करें जिनका कोई मतलब न हो. जैसे,
_libया_library. हालांकि, अगर_libraryटारगेट और उससे जुड़े_binaryके बीच टकराव से बचने के लिए ऐसा करना ज़रूरी हो, तो किया जा सकता है - proto से जुड़े टारगेट के लिए:
proto_libraryटारगेट के नाम,_protoपर खत्म होने चाहिए- भाषा के हिसाब से
*_proto_libraryनियम, underlying proto से मेल खाने चाहिए. हालांकि,_protoको भाषा के हिसाब से सफ़िक्स से बदलें. जैसे:cc_proto_library:_cc_protojava_proto_library:_java_protojava_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 स्टाइल गाइड में यह तय नहीं किया गया है. हालांकि, इसमें एक जैसा फ़ॉर्मैट इस्तेमाल करने का सुझाव दिया गया है. इसलिए, हमने सिर्फ़ डबल कोट वाली स्ट्रिंग का इस्तेमाल करने का फ़ैसला किया है. कई भाषाओं में, स्ट्रिंग लिटरल के लिए डबल कोट का इस्तेमाल किया जाता है.
टॉप-लेवल की दो परिभाषाओं के बीच, एक खाली लाइन का इस्तेमाल करें. वजह: फ़ाइल का स्ट्रक्चर, आम तौर पर Python फ़ाइल जैसा नहीं होता.
BUILDइसमें सिर्फ़ टॉप-लेवल स्टेटमेंट होते हैं. एक खाली लाइन का इस्तेमाल करने से,BUILDफ़ाइलें छोटी हो जाती हैं.