लेबल, टारगेट के लिए एक आइडेंटिफ़ायर होता है. कैननिकल फ़ॉर्म में पूरा लेबल ऐसा दिखता है:
@@myrepo//my/app/main:app_binary
लेबल का पहला हिस्सा, रिपॉज़िटरी का नाम होता है. इसे @@myrepo
के तौर पर दिखाया गया है. डबल-@
सिंटैक्स से पता चलता है कि यह कैननिकल repo name है, जो वर्कस्पेस में यूनीक है. कैननिकल रेपो के नामों वाले लेबल, टारगेट की साफ़ तौर पर पहचान करते हैं. इससे कोई फ़र्क़ नहीं पड़ता कि वे किस कॉन्टेक्स्ट में दिखते हैं.
कैननिकल रेपो का नाम अक्सर एक ऐसी स्ट्रिंग होती है जिसे समझना मुश्किल होता है. यह @@rules_java++toolchains+local_jdk
की तरह दिखती है. हालांकि, आम तौर पर साफ़ तौर पर रिपो का नाम दिखाने वाले लेबल दिखते हैं. ये इस तरह दिखते हैं:
@myrepo//my/app/main:app_binary
इनमें सिर्फ़ यह अंतर है कि पहले वाले में, रेपो के नाम से पहले दो @
हैं, जबकि दूसरे वाले में एक @
है.
इसका मतलब myrepo
नाम की किसी रिपॉज़िटरी से है. यह नाम, इस लेबल के कॉन्टेक्स्ट के आधार पर अलग हो सकता है.
अगर लेबल उसी रिपॉज़िटरी को दिखाता है जिससे इसका इस्तेमाल किया गया है, तो रिपॉज़िटरी के नाम वाले हिस्से को हटाया जा सकता है. इसलिए, @@myrepo
के अंदर पहले लेबल को आम तौर पर इस तरह लिखा जाता है
//my/app/main:app_binary
लेबल का दूसरा हिस्सा, पैकेज का पूरा नाम नहीं है
my/app/main
. यह पैकेज का पाथ है
जो रिपॉज़िटरी रूट के हिसाब से तय होता है. रिपॉज़िटरी का नाम और बिना क्वालिफ़ाइड पैकेज का नाम, मिलकर पूरी तरह क्वालिफ़ाइड पैकेज का नाम @@myrepo//my/app/main
बनाते हैं. जब लेबल उसी पैकेज को रेफ़र करता है जिसमें इसका इस्तेमाल किया जाता है, तो पैकेज का नाम (और ज़रूरत पड़ने पर, कोलन) हटाया जा सकता है. इसलिए, @@myrepo//my/app/main
एट्रिब्यूट की वैल्यू के तौर पर, इस लेबल को इनमें से किसी भी तरीके से लिखा जा सकता है:
app_binary
:app_binary
यह एक सामान्य नियम है कि फ़ाइलों के लिए कोलन को हटा दिया जाता है, लेकिन नियमों के लिए इसे बनाए रखा जाता है. हालांकि, इससे कोई खास फ़र्क़ नहीं पड़ता.
कोलन के बाद लेबल का हिस्सा, app_binary
बिना क्वालिफ़ाइड किया गया टारगेट नेम है. अगर यह पैकेज पाथ के आखिरी कॉम्पोनेंट से मेल खाता है, तो इसे और कोलन को हटाया जा सकता है. इसलिए, ये दोनों लेबल एक जैसे हैं:
//my/app/lib
//my/app/lib:lib
पैकेज की किसी सबडायरेक्ट्री में मौजूद फ़ाइल टारगेट का नाम, पैकेज रूट (BUILD
फ़ाइल वाली डायरेक्ट्री) के हिसाब से फ़ाइल का पाथ होता है. इसलिए, यह फ़ाइल रिपॉज़िटरी की my/app/main/testdata
सबडायरेक्ट्री में है:
//my/app/main:testdata/input.txt
//my/app
और @@some_repo//my/app
जैसी स्ट्रिंग के दो मतलब होते हैं. ये इस बात पर निर्भर करता है कि इनका इस्तेमाल किस कॉन्टेक्स्ट में किया गया है: जब Bazel को किसी लेबल की ज़रूरत होती है, तब इनका मतलब क्रमशः //my/app:app
और @@some_repo//my/app:app
होता है. हालांकि, जब Bazel को किसी पैकेज की ज़रूरत होती है (जैसे कि package_group
स्पेसिफ़िकेशन में), तो वह उस पैकेज का रेफ़रंस देता है जिसमें वह लेबल होता है.
BUILD
फ़ाइलों में आम तौर पर यह गलती होती है कि किसी पैकेज का रेफ़रंस देने के लिए //my/app
का इस्तेमाल किया जाता है. इसके अलावा, किसी पैकेज में मौजूद सभी टारगेट का रेफ़रंस देने के लिए भी इसका इस्तेमाल किया जाता है. हालांकि, ऐसा नहीं होता. ध्यान रखें कि यह //my/app:app
के बराबर है. इसलिए, यह मौजूदा रिपॉज़िटरी के my/app
पैकेज में app
टारगेट का नाम देता है.
हालांकि, package_group
के स्पेसिफ़िकेशन या .bzl
फ़ाइलों में, पैकेज का रेफ़रंस देने के लिए //my/app
का इस्तेमाल करने का सुझाव दिया जाता है. ऐसा इसलिए, क्योंकि इससे यह साफ़ तौर पर पता चलता है कि पैकेज का नाम, वर्कस्पेस की टॉप-लेवल डायरेक्ट्री में मौजूद है.
रिलेटिव लेबल का इस्तेमाल, अन्य पैकेज में मौजूद टारगेट को रेफ़र करने के लिए नहीं किया जा सकता. इस मामले में, रिपॉज़िटरी आइडेंटिफ़ायर और पैकेज का नाम हमेशा बताया जाना चाहिए.
उदाहरण के लिए, अगर सोर्स ट्री में पैकेज my/app
और पैकेज my/app/testdata
, दोनों शामिल हैं (इन दोनों डायरेक्ट्री में अपनी BUILD
फ़ाइल है), तो बाद वाले पैकेज में testdepot.zip
नाम की फ़ाइल शामिल है. //my/app:BUILD
में इस फ़ाइल को रेफ़र करने के दो तरीके यहां दिए गए हैं. इनमें से एक तरीका गलत है और एक सही:
गलत — testdata
एक अलग पैकेज है. इसलिए, रिलेटिव पाथ का इस्तेमाल नहीं किया जा सकता
testdata/testdepot.zip
सही — testdata
का पूरा पाथ दिया गया है
//my/app/testdata:testdepot.zip
@@//
से शुरू होने वाले लेबल, मुख्य रिपॉज़िटरी के रेफ़रंस होते हैं. ये बाहरी रिपॉज़िटरी से भी काम करेंगे.
इसलिए, जब किसी बाहरी रिपॉज़िटरी से रेफ़रंस दिया जाता है, तो @@//a/b/c
, //a/b/c
से अलग होता है.
पहले वाला, मुख्य रिपॉज़िटरी पर वापस जाता है. वहीं, दूसरा वाला //a/b/c
को बाहरी रिपॉज़िटरी में ही ढूंढता है.
यह खास तौर पर तब काम आता है, जब मुख्य रिपॉज़िटरी में ऐसे नियम लिखे जा रहे हों जो मुख्य रिपॉज़िटरी में मौजूद टारगेट को रेफ़रंस देते हैं. साथ ही, इनका इस्तेमाल बाहरी रिपॉज़िटरी से किया जाएगा.
टारगेट को रेफ़र करने के अलग-अलग तरीकों के बारे में जानने के लिए, टारगेट पैटर्न देखें.
किसी लेबल की लेक्सिकल जानकारी
लेबल सिंटैक्स, ऐसे मेटाकैरेक्टर के इस्तेमाल को हतोत्साहित करता है जिनका शेल के लिए खास मतलब होता है. इससे अनजाने में कोट करने से जुड़ी समस्याओं से बचा जा सकता है. साथ ही, लेबल में बदलाव करने वाले टूल और स्क्रिप्ट बनाना आसान हो जाता है. जैसे, Bazel Query Language.
अनुमति वाले टारगेट के नामों के बारे में सटीक जानकारी यहां दी गई है.
टारगेट के नाम — package-name:target-name
target-name
पैकेज में मौजूद टारगेट का नाम है. किसी नियम का नाम, BUILD
फ़ाइल में नियम के एलान में मौजूद name
एट्रिब्यूट की वैल्यू होती है. किसी फ़ाइल का नाम, BUILD
फ़ाइल वाली डायरेक्ट्री के हिसाब से उसका पाथनेम होता है.
टारगेट के नाम में सिर्फ़ a
–z
, A
–Z
, 0
–9
सेट के वर्ण और विराम चिह्न !%-@^_"#$&'()*-+,;<=>?[]{|}~/.
होने चाहिए.
फ़ाइल के नाम, सामान्य फ़ॉर्म में रिलेटिव पाथनेम होने चाहिए. इसका मतलब है कि वे न तो स्लैश से शुरू होने चाहिए और न ही स्लैश पर खत्म होने चाहिए. उदाहरण के लिए, /foo
और foo/
का इस्तेमाल नहीं किया जा सकता. साथ ही, उनमें पाथ सेपरेटर के तौर पर एक साथ कई स्लैश नहीं होने चाहिए. उदाहरण के लिए, foo//bar
. इसी तरह, अप-लेवल रेफ़रंस (..
) और मौजूदा डायरेक्ट्री के रेफ़रंस (./
) का इस्तेमाल नहीं किया जा सकता.
गलत — अन्य पैकेज में मौजूद फ़ाइलों के लिए ..
का इस्तेमाल न करें
सही — //package-name:filename
का इस्तेमाल करें
फ़ाइल टारगेट के नाम में /
का इस्तेमाल करना आम बात है. हालांकि, नियमों के नाम में /
का इस्तेमाल न करें. खास तौर पर, जब लेबल के छोटे नाम का इस्तेमाल किया जाता है, तो इससे पढ़ने वाले को भ्रम हो सकता है. //foo/bar/wiz
लेबल हमेशा //foo/bar/wiz:wiz
का छोटा नाम होता है. भले ही, ऐसा कोई पैकेज foo/bar/wiz
मौजूद न हो. यह कभी भी //foo:bar/wiz
को रेफ़र नहीं करता है, भले ही वह टारगेट मौजूद हो.
हालांकि, कुछ स्थितियों में स्लैश का इस्तेमाल करना आसान होता है. साथ ही, कभी-कभी यह ज़रूरी भी होता है. उदाहरण के लिए, कुछ नियमों के नाम, उनकी मुख्य सोर्स फ़ाइल से मेल खाने चाहिए. यह फ़ाइल, पैकेज की किसी सबडायरेक्ट्री में मौजूद हो सकती है.
पैकेज के नाम — //package-name:target-name
किसी पैकेज का नाम, उस डायरेक्ट्री का नाम होता है जिसमें उसकी BUILD
फ़ाइल होती है. यह नाम, उस डायरेक्ट्री के हिसाब से होता है जिसमें रिपॉज़िटरी की टॉप-लेवल डायरेक्ट्री होती है.
उदाहरण के लिए: my/app
.
तकनीकी तौर पर, Bazel इन बातों का पालन करता है:
- पैकेज के नाम में अंग्रेज़ी के छोटे अक्षर
a
से लेकरz
तक, अंग्रेज़ी के बड़े अक्षरA
से लेकरZ
तक, अंक0
से लेकर9
तक, वर्ण! \"#$%&'()*+,-.;<=>?@[]^_`{|}
(हां, इसमें स्पेस वाला वर्ण भी शामिल है!), और फ़ॉरवर्ड स्लैश/
(क्योंकि यह डायरेक्ट्री सेपरेटर है) का इस्तेमाल किया जा सकता है. - पैकेज के नाम, फ़ॉरवर्ड स्लैश
/
से शुरू या खत्म नहीं हो सकते. - पैकेज के नाम में सबस्ट्रिंग
//
नहीं हो सकता. यह सही नहीं है---इसका डायरेक्ट्री पाथ क्या होगा? - पैकेज के नाम में
/./
या/../
या/.../
वगैरह सबस्ट्रिंग नहीं होनी चाहिए. इस नियम को इसलिए लागू किया गया है, ताकि लॉजिकल पैकेज के नाम और फ़िज़िकल डायरेक्ट्री के नाम के बीच अनुवाद करते समय कोई भ्रम न हो. ऐसा इसलिए, क्योंकि पाथ स्ट्रिंग में डॉट वर्ण का सिमैंटिक मतलब होता है.
प्रैक्टिकल लेवल पर:
- ऐसी भाषा के लिए जिसका डायरेक्ट्री स्ट्रक्चर, उसके मॉड्यूल सिस्टम के लिए अहम है (उदाहरण के लिए, Java), डायरेक्ट्री के ऐसे नाम चुनना ज़रूरी है जो भाषा में मान्य आइडेंटिफ़ायर हों. उदाहरण के लिए, इसे किसी अंक से शुरू न करें. साथ ही, इसमें खास वर्णों का इस्तेमाल न करें. खास तौर पर, अंडरस्कोर और हाइफ़न का इस्तेमाल न करें.
- Bazel, वर्कस्पेस के रूट पैकेज में टारगेट के साथ काम करता है. उदाहरण के लिए,
//:foo
. हालांकि, उस पैकेज को खाली छोड़ना सबसे अच्छा होता है, ताकि सभी काम के पैकेज के नाम जानकारी देने वाले हों.
नियम
नियम से, इनपुट और आउटपुट के बीच संबंध के बारे में पता चलता है. साथ ही, आउटपुट बनाने के चरणों के बारे में भी जानकारी मिलती है. नियम कई तरह के हो सकते हैं. इन्हें कभी-कभी नियम क्लास भी कहा जाता है. ये नियम, कंपाइल किए गए एक्ज़ीक्यूटेबल और लाइब्रेरी, टेस्ट एक्ज़ीक्यूटेबल, और अन्य आउटपुट जनरेट करते हैं. इनके बारे में Build Encyclopedia में बताया गया है.
BUILD
फ़ाइलें, नियमों को लागू करके टारगेट तय करती हैं.
यहां दिए गए उदाहरण में, cc_binary
नियम का इस्तेमाल करके, टारगेट my_app
की जानकारी दी गई है.
cc_binary(
name = "my_app",
srcs = ["my_app.cc"],
deps = [
"//absl/base",
"//absl/strings",
],
)
हर नियम इनवोकेशन में एक name
एट्रिब्यूट होता है. यह एक मान्य टारगेट का नाम होना चाहिए. यह BUILD
फ़ाइल के पैकेज में मौजूद किसी टारगेट का एलान करता है.
हर नियम में एट्रिब्यूट का एक सेट होता है. किसी नियम पर लागू होने वाले एट्रिब्यूट, हर एट्रिब्यूट का महत्व, और सिमैंटिक, नियम के टाइप पर निर्भर करते हैं. नियमों और उनसे जुड़े एट्रिब्यूट की सूची देखने के लिए, बिल्ड एनसाइक्लोपीडिया देखें. हर एट्रिब्यूट का एक नाम और एक टाइप होता है. किसी एट्रिब्यूट के लिए, यहां कुछ सामान्य टाइप दिए गए हैं: पूर्णांक, लेबल, लेबल की सूची, स्ट्रिंग, स्ट्रिंग की सूची, आउटपुट लेबल, आउटपुट लेबल की सूची. यह ज़रूरी नहीं है कि हर नियम में सभी एट्रिब्यूट की जानकारी दी जाए. इस तरह, एट्रिब्यूट, कुंजियों (नामों) से लेकर टाइप की गई वैल्यू तक की डिक्शनरी बनाते हैं.
कई नियमों में मौजूद srcs
एट्रिब्यूट का टाइप "लेबल की सूची" होता है. अगर इसकी वैल्यू मौजूद है, तो यह लेबल की सूची होती है. इसमें हर लेबल, ऐसे टारगेट का नाम होता है जो इस नियम के लिए इनपुट होता है.
कुछ मामलों में, नियम के टाइप का नाम कुछ हद तक मनमाना होता है. साथ ही, नियम से जनरेट की गई फ़ाइलों के नाम ज़्यादा दिलचस्प होते हैं. यह बात, जनरेट किए गए नियमों पर भी लागू होती है. ज़्यादा जानकारी के लिए, सामान्य नियम: genrule देखें.
अन्य मामलों में, नाम अहम होता है: उदाहरण के लिए, *_binary
और *_test
नियमों के लिए, नियम का नाम यह तय करता है कि बिल्ड से तैयार किए गए एक्ज़ीक्यूटेबल का नाम क्या होगा.
टारगेट के इस डायरेक्टेड ऐसाइक्लिक ग्राफ़ को टारगेट ग्राफ़ या बिल्ड डिपेंडेंसी ग्राफ़ कहा जाता है. Bazel Query टूल इसी डोमेन पर काम करता है.
Targets | BUILD फ़ाइलें |