इस पेज पर, Bazel की मदद से प्रोग्राम बनाने, बिल्ड कमांड सिंटैक्स, और टारगेट पैटर्न सिंटैक्स के बारे में बताया गया है.
क्विकस्टार्ट
Bazel को चलाने के लिए, अपनी बेस workspace डायरेक्ट्री या उसकी किसी भी सब-डायरेक्ट्री पर जाएं और bazel
टाइप करें. अगर आपको नया फ़ाइल फ़ोल्डर बनाना है, तो बिल्ड देखें.
bazel help
[Bazel release bazel version]
Usage: bazel command options ...
उपलब्ध निर्देश
analyze-profile
: बिल्ड प्रोफ़ाइल के डेटा का विश्लेषण करता है.aquery
: विश्लेषण के बाद ऐक्शन ग्राफ़ पर क्वेरी लागू करता है.build
: तय किए गए टारगेट बनाता है.canonicalize-flags
: 'बेज़ल' फ़्लैग को कैननिकल के तौर पर मंज़ूरी दें.clean
: यह आउटपुट फ़ाइलों को हटाता है और सर्वर को बंद करता है.cquery
: विश्लेषण के बाद डिपेंडेंसी ग्राफ़ क्वेरी लागू करता है.dump
: Basel सर्वर की प्रोसेस की इंटरनल स्थिति को खारिज करता है.help
: निर्देशों या इंडेक्स के लिए प्रिंट मददगार होते हैं.info
: bazel सर्वर के बारे में रनटाइम की जानकारी दिखाता है.fetch
: किसी टारगेट की सभी बाहरी डिपेंडेंसी फ़ेच करता है.mobile-install
: मोबाइल डिवाइसों पर ऐप्लिकेशन इंस्टॉल करता है.query
: यह एक डिपेंडेंसी ग्राफ़ क्वेरी लागू करता है.run
: तय किए गए टारगेट को चलाता है.shutdown
: Basel सर्वर को रोकता है.test
: तय किए गए टेस्ट टारगेट बनाता और चलाता है.version
: Basel के वर्शन की जानकारी प्रिंट करता है.
सहायता पाना
bazel help command
: प्रिंट सहायता औरcommand
के लिए विकल्प.bazel help
startup_options
: Bazel को होस्ट करने वाले JVM के विकल्प.bazel help
target-syntax
: टारगेट तय करने के सिंटैक्स के बारे में बताता है.bazel help info-keys
: यह जानकारी कमांड में इस्तेमाल की गई कुंजियों की सूची दिखाता है.
bazel
टूल कई फ़ंक्शन करता है. इन्हें निर्देश कहा जाता है. आम तौर पर, bazel build
और bazel test
का इस्तेमाल किया जाता है. bazel help
का इस्तेमाल करके, ऑनलाइन सहायता
मैसेज ब्राउज़ किए जा सकते हैं.
एक टारगेट बनाया जा रहा है
कोई बिल्ड शुरू करने से पहले, आपके पास वर्कस्पेस होना चाहिए. वर्कस्पेस एक डायरेक्ट्री ट्री होता है. इसमें आपके ऐप्लिकेशन को बनाने के लिए ज़रूरी सभी सोर्स फ़ाइलें होती हैं. Basel आपको पूरी तरह से रीड-ओनली वॉल्यूम से बिल्ड करने की सुविधा देता है.
Bazel की मदद से प्रोग्राम बनाने के लिए, bazel build
टाइप करें. इसके बाद, वह टारगेट टाइप करें जिसे आपको बनाना है.
bazel build //foo
//foo
बनाने का निर्देश देने के बाद, आपको इससे मिलता-जुलता आउटपुट दिखेगा:
INFO: Analyzed target //foo:foo (14 packages loaded, 48 targets configured).
INFO: Found 1 target...
Target //foo:foo up-to-date:
bazel-bin/foo/foo
INFO: Elapsed time: 9.905s, Critical Path: 3.25s
INFO: Build completed successfully, 6 total actions
सबसे पहले, Basel आपके टारगेट के डिपेंडेंसी ग्राफ़ में मौजूद सभी पैकेज को लोड करता है. इसमें एलान की गई डिपेंडेंसी शामिल हैं. ये फ़ाइलें, टारगेट की BUILD
फ़ाइल में सीधे तौर पर शामिल होती हैं. साथ ही, इसमें ट्रांज़िशन डिपेंडेंसी भी शामिल हैं. ये फ़ाइलें, टारगेट की डिपेंडेंसी की BUILD
फ़ाइलों में शामिल होती हैं. सभी डिपेंडेंसी की पहचान करने के बाद, BaZ चैनल उनका विश्लेषण
करते हैं और उनके सही होने की जांच करते हैं. साथ ही, बिल्ड ऐक्शन बनाते हैं. आखिर में, Bazel, बाइल्ड के कंपाइलर और अन्य टूल इस्तेमाल करता है.
बिल्ड को एक्ज़ीक्यूट करने के दौरान, Basel, प्रोग्रेस मैसेज को प्रिंट करता है. प्रोग्रेस मैसेज में, बिल्ड के मौजूदा चरण (जैसे कि कंपाइलर या लिंकर) के शुरू होते ही उसे शामिल किया जाता है. साथ ही, बिल्ड ऐक्शन की कुल संख्या के हिसाब से उसे पूरा किया जाता है. बिल्ड शुरू होने पर, अक्सर कुल कार्रवाइयों की संख्या बढ़ जाती है. ऐसा इसलिए होता है, क्योंकि Bazel पूरे ऐक्शन ग्राफ़ का पता लगाता है. हालांकि, कुछ सेकंड में यह संख्या स्थिर हो जाती है.
बिल्ड के आखिर में, Bazel यह जानकारी दिखाता है कि किन टारगेट का अनुरोध किया गया था, वे बिल्ड हुए या नहीं, और अगर बिल्ड हुए हैं, तो आउटपुट फ़ाइलें कहां मिल सकती हैं. बिल्ड चलाने वाली स्क्रिप्ट, इस आउटपुट को भरोसेमंद तरीके से पार्स कर सकती हैं. ज़्यादा जानकारी के लिए, --show_result
देखें.
अगर आप वही निर्देश फिर से टाइप करते हैं, तो बिल्ड ज़्यादा तेज़ी से काम करता है.
bazel build //foo
INFO: Analyzed target //foo:foo (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //foo:foo up-to-date:
bazel-bin/foo/foo
INFO: Elapsed time: 0.144s, Critical Path: 0.00s
INFO: Build completed successfully, 1 total action
यह शून्य बिल्ड है. कोई बदलाव न होने की वजह से, रीफ़्रेश करने के लिए कोई पैकेज नहीं है और न ही कोई बिल्ड चरण है. अगर 'foo' या इसकी डिपेंडेंसी में कोई बदलाव होता है, तो Basel, बिल्ड से जुड़ी कुछ कार्रवाइयों को फिर से लागू करेगा या इंक्रीमेंटल बिल्ड पूरा करेगा.
एक से ज़्यादा टारगेट बनाना
Bazel में, बिल्ड किए जाने वाले टारगेट की जानकारी देने के कई तरीके हैं. इन्हें टारगेट पैटर्न कहा जाता है. इस सिंटैक्स का इस्तेमाल build
, test
या query
जैसे निर्देशों में किया जाता है.
लेबल का इस्तेमाल, अलग-अलग टारगेट तय करने के लिए किया जाता है. जैसे, BUILD
फ़ाइलों में डिपेंडेंसी का एलान करने के लिए. वहीं, Bazel के टारगेट पैटर्न से कई टारगेट तय किए जाते हैं. टारगेट पैटर्न, वाइल्डकार्ड का इस्तेमाल करके टारगेट के सेट के लिए लेबल सिंटैक्स का सामान्यीकरण है. सबसे सामान्य स्थिति में, कोई भी मान्य लेबल एक मान्य टारगेट पैटर्न होता है. इससे सिर्फ़ एक टारगेट के सेट की पहचान की जाती है.
//
से शुरू होने वाले सभी टारगेट पैटर्न का समाधान, मौजूदा फ़ाइल फ़ोल्डर के हिसाब से किया जाता है.
//foo/bar:wiz |
सिर्फ़ एक टारगेट //foo/bar:wiz . |
//foo/bar |
//foo/bar:bar के बराबर. |
//foo/bar:all |
पैकेज foo/bar में मौजूद सभी नियम टारगेट. |
//foo/... |
डायरेक्ट्री foo के नीचे मौजूद सभी पैकेज में मौजूद सभी नियम टारगेट. |
//foo/...:all |
डायरेक्ट्री foo के नीचे मौजूद सभी पैकेज में मौजूद सभी नियम टारगेट. |
//foo/...:* |
foo डायरेक्ट्री के नीचे मौजूद सभी पैकेज में सभी टारगेट (नियम और फ़ाइलें). |
//foo/...:all-targets |
foo डायरेक्ट्री के नीचे मौजूद सभी पैकेज में सभी टारगेट (नियम और फ़ाइलें). |
//... |
फ़ाइल फ़ोल्डर में मौजूद पैकेज में मौजूद सभी टारगेट. इसमें बाहरी रिपॉज़िटरी के टारगेट शामिल नहीं हैं. |
//:all |
अगर वर्कस्पेस के रूट में `BUILD` फ़ाइल मौजूद है, तो टॉप-लेवल पैकेज के सभी टारगेट. |
//
से शुरू न होने वाले टारगेट पैटर्न, मौजूदा वर्किंग डायरेक्ट्री के हिसाब से हल किए जाते हैं. इन उदाहरणों में, foo
की ऐक्टिव डायरेक्ट्री के बारे में बताया गया है:
:foo |
//foo:foo के बराबर. |
bar:wiz |
//foo/bar:wiz के बराबर. |
bar/wiz |
इसके बराबर:
|
bar:all |
//foo/bar:all के बराबर. |
:all |
//foo:all की तरह काम करता है. |
...:all |
//foo/...:all के बराबर. |
... |
//foo/...:all के बराबर. |
bar/...:all |
//foo/bar/...:all के बराबर. |
डिफ़ॉल्ट रूप से, बार-बार होने वाले टारगेट पैटर्न के लिए डायरेक्ट्री सिमलिंक को फ़ॉलो किया जाता है. हालांकि, उन मामलों को छोड़कर जो आउटपुट बेस के नीचे ले जाते हैं. जैसे, वर्कस्पेस की रूट डायरेक्ट्री में बनाए गए सुविधा सिमलिंक.
इसके अलावा, Bazel किसी भी डायरेक्ट्री में, बार-बार इस्तेमाल होने वाले टारगेट पैटर्न का आकलन करते समय, सिमलिंक का इस्तेमाल नहीं करता. इस डायरेक्ट्री में, इस तरह का नाम वाली फ़ाइल होनी चाहिए:
DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN
foo/...
, पैकेज के लिए वाइल्डकार्ड है. यह डायरेक्ट्री foo
के नीचे मौजूद सभी पैकेज के बारे में बताता है. यह पैकेज पाथ के सभी रूट के लिए होता है. :all
, टारगेट के लिए वाइल्डकार्ड है. यह किसी पैकेज में मौजूद सभी नियमों से मैच करता है. इन दोनों को एक साथ इस्तेमाल किया जा सकता है, जैसे कि foo/...:all
में. दोनों वाइल्डकार्ड का इस्तेमाल करने पर, इसे foo/...
के तौर पर छोटा किया जा सकता है.
इसके अलावा, :*
(या :all-targets
) एक वाइल्डकार्ड है, जो मैच किए गए पैकेज में हर टारगेट से मैच करता है. इसमें ऐसी फ़ाइलें भी शामिल हैं जो आम तौर पर किसी नियम के हिसाब से नहीं बनाई जाती हैं. जैसे, java_binary
नियमों से जुड़ी _deploy.jar
फ़ाइलें.
इसका मतलब है कि :*
, :all
के सुपरसेट को दिखाता है. हालांकि, यह सिंटैक्स कुछ हद तक भ्रमित करता है. हालांकि, यह सिंटैक्स सामान्य :all
वाइल्डकार्ड का इस्तेमाल सामान्य बिल्ड के लिए करता है, जहां _deploy.jar
जैसे बिल्डिंग टारगेट की ज़रूरत नहीं होती.
इसके अलावा, लेबल सिंटैक्स के लिए ज़रूरी कोलन के बजाय, स्लैश का इस्तेमाल किया जा सकता है. Bash फ़ाइल नाम को बड़ा करने की सुविधा का इस्तेमाल करते समय, यह अक्सर सुविधाजनक होता है.
उदाहरण के लिए, अगर कोई पैकेज foo/bar
है, तो foo/bar/wiz
वैल्यू //foo/bar:wiz
के बराबर होगी. अगर कोई पैकेज foo
है, तो foo/bar/wiz
वैल्यू //foo:bar/wiz
के बराबर होगी.
Bazel के कई निर्देश, आर्ग्युमेंट के तौर पर टारगेट पैटर्न की सूची स्वीकार करते हैं. साथ ही, ये सभी निर्देश, प्रीफ़िक्स नेगेटिव ऑपरेटर -
का इस्तेमाल करते हैं. इसका इस्तेमाल, पिछले आर्ग्युमेंट से तय किए गए सेट से, टारगेट के किसी सेट को घटाने के लिए किया जा सकता है. ध्यान दें कि इसका मतलब है कि क्रम का ध्यान रखना ज़रूरी है. उदाहरण के लिए,
bazel build foo/... bar/...
इसका मतलब है, "सभी टारगेट foo
से कम बनाएं और सभी टारगेट bar
से कम बनाएं", जबकि
bazel build -- foo/... -foo/bar/...
का मतलब है कि "foo/bar
के नीचे मौजूद टारगेट को छोड़कर, foo
के नीचे मौजूद सभी टारगेट बनाएं". (-
से शुरू होने वाले बाद के आर्ग्युमेंट को अतिरिक्त विकल्पों के तौर पर समझने से रोकने के लिए, --
आर्ग्युमेंट ज़रूरी है.)
हालांकि, यह ध्यान रखना ज़रूरी है कि इस तरीके से टारगेट को घटाने से
इस बात की गारंटी नहीं मिलती कि उन्हें बनाया नहीं गया है.
क्योंकि हो सकता है कि ये उन टारगेट पर निर्भर हों जिन्हें हटाया नहीं गया है. उदाहरण के लिए, अगर अन्य टारगेट //foo:all-apis
के अलावा, अन्य टारगेट //foo/bar:api
पर निर्भर होते हैं, तो बाद वाला टारगेट पिछले टारगेट के हिस्से के तौर पर बनाया जाएगा.
tags = ["manual"]
वाले टारगेट, bazel build
और bazel test
जैसे निर्देशों में बताए जाने पर, वाइल्डकार्ड टारगेट पैटर्न (...
, :*
, :all
वगैरह) में शामिल नहीं किए जाते. अगर आपको Bazel को इन टारगेट को बनाने/जांच करने के लिए कहना है, तो आपको कमांड लाइन पर साफ़ तौर पर टारगेट पैटर्न के साथ ऐसे टेस्ट टारगेट बताने चाहिए. इसके उलट, bazel query
अपने-आप ऐसा कोई फ़िल्टर नहीं करता. ऐसा करने से, bazel query
का मकसद पूरा नहीं होगा.
बाहरी डिपेंडेंसी फ़ेच की जा रही है
डिफ़ॉल्ट रूप से, Basel, बिल्ड के दौरान बाहरी डिपेंडेंसी को डाउनलोड
और सिमलिंक करेगा. हालांकि, ऐसा करने की ज़रूरत नहीं हो सकती, क्योंकि आपको यह जानना है कि नई बाहरी डिपेंडेंसी कब जोड़ी जाती हैं या आपको "प्रीफ़ेच" डिपेंडेंसी कब करनी हैं (जैसे, किसी ऐसी फ़्लाइट से पहले जहां आप ऑफ़लाइन होंगे). अगर आपको बिल्ड के दौरान नई डिपेंडेंसी जोड़ने से रोकना है, तो --fetch=false
फ़्लैग का इस्तेमाल करें. ध्यान दें कि यह फ़्लैग सिर्फ़ डेटा स्टोर करने की जगह के उन नियमों पर लागू होता है जो लोकल फ़ाइल सिस्टम में किसी डायरेक्ट्री पर नहीं ले जाते. उदाहरण के लिए, local_repository
, new_local_repository
, Android SDK, और एनडीके डेटा स्टोर करने की जगह के नियमों में किए गए बदलाव हमेशा लागू होंगे. भले ही, --fetch
वैल्यू कोई भी हो.
अगर आपने बिल्ड के दौरान फ़ेच करने की अनुमति नहीं दी है और Bazel को नई बाहरी डिपेंडेंसी मिलती हैं, तो आपका बिल्ड पूरा नहीं होगा.
bazel fetch
चलाकर, डिपेंडेंसी को मैन्युअल तरीके से फ़ेच किया जा सकता है. अगर आपने बिल्ड के दौरान फ़ेच करने की अनुमति नहीं दी है, तो आपको bazel fetch
को चलाना होगा:
- पहली बार बनाने से पहले.
- नई बाहरी डिपेंडेंसी जोड़ने के बाद.
इसे चलाने के बाद, जब तक WORKSPACE फ़ाइल में बदलाव नहीं होता, तब तक आपको इसे फिर से चलाने की ज़रूरत नहीं पड़ेगी.
fetch
, डिपेंडेंसी फ़ेच करने के लिए टारगेट की सूची लेता है. उदाहरण के लिए, इससे //foo:bar
और //bar:baz
को बनाने के लिए ज़रूरी डिपेंडेंसी फ़ेच होंगी:
bazel fetch //foo:bar //bar:baz
किसी वर्कस्पेस की सभी बाहरी डिपेंडेंसी फ़ेच करने के लिए, इसे चलाएं:
bazel fetch //...
अगर आपके पास अपने फ़ाइल फ़ोल्डर के रूट में, इस्तेमाल किए जा रहे सभी टूल (लाइब्रेरी जार से लेकर JDK तक) हैं, तो आपको बेज़ल फ़ेच चलाने की ज़रूरत नहीं है.
हालांकि, अगर Workspace डायरेक्ट्री के बाहर की किसी चीज़ का इस्तेमाल किया जा रहा है, तो Bazel, bazel build
को चलाने से पहले bazel fetch
को अपने-आप चला देगा.
डेटा स्टोर करने की कैश मेमोरी
बेज़ल एक ही फ़ाइल को कई बार फ़ेच करने से बचने की कोशिश करता है. भले ही, अलग-अलग फ़ाइल फ़ोल्डर में एक ही फ़ाइल की ज़रूरत हो या किसी एक्सटर्नल डेटा स्टोर करने की जगह की परिभाषा बदल गई हो, लेकिन डाउनलोड करने के लिए एक ही फ़ाइल की ज़रूरत हो. ऐसा करने के लिए,
bazel, डाउनलोड की गई सभी फ़ाइलों को रिपॉज़िटरी कैश में कैश मेमोरी में सेव करता है. यह कैश मेमोरी डिफ़ॉल्ट रूप से ~/.cache/bazel/_bazel_$USER/cache/repos/v1/
में मौजूद होती है. --repository_cache
विकल्प का इस्तेमाल करके, जगह की जानकारी में बदलाव किया जा सकता है. कैश मेमोरी, सभी वर्कस्पेस और bazel के इंस्टॉल किए गए वर्शन के बीच शेयर की जाती है.
अगर बैजेल को यह पता है कि उसके पास सही फ़ाइल की कॉपी है, तो कैश मेमोरी से एक एंट्री ली जाती है. इसका मतलब है कि अगर डाउनलोड करने के अनुरोध में बताई गई फ़ाइल का SHA256 योग है और उस हैश वाली फ़ाइल कैश मेमोरी में मौजूद है. इसलिए, हर बाहरी फ़ाइल के लिए हैश तय करना, सुरक्षा के लिहाज़ से ही नहीं, बल्कि ग़ैर-ज़रूरी डाउनलोड से बचने के लिए भी एक अच्छा आइडिया है.
कैश मेमोरी में सेव होने वाले हर हिट के बाद, कैश मेमोरी में मौजूद फ़ाइल में बदलाव का समय अपडेट हो जाता है. इस तरह, कैश मेमोरी में सेव की गई डायरेक्ट्री में फ़ाइल के आखिरी बार इस्तेमाल किए जाने का पता आसानी से लगाया जा सकता है. उदाहरण के लिए, कैश मेमोरी को मैन्युअल तरीके से खाली करने का तरीका. कैश मेमोरी कभी भी अपने-आप नहीं मिटती, क्योंकि इसमें किसी ऐसी फ़ाइल की कॉपी हो सकती है जो अब अपस्ट्रीम उपलब्ध नहीं है.
डिस्ट्रिब्यूशन फ़ाइल डायरेक्ट्री
डिस्ट्रिब्यूशन डायरेक्ट्री, Bazel का एक और तरीका है. इसका इस्तेमाल, ग़ैर-ज़रूरी डाउनलोड से बचने के लिए किया जाता है. Baज़र, डेटा स्टोर करने की जगह की कैश मेमोरी से पहले, डिस्ट्रिब्यूशन डायरेक्ट्री खोजता है. मुख्य अंतर यह है कि डिस्ट्रिब्यूशन डायरेक्ट्री को मैन्युअल तरीके से तैयार करना पड़ता है.
--distdir=/path/to-directory
विकल्प का इस्तेमाल करके, फ़ाइलों को फ़ेच करने के बजाय, उन्हें देखने के लिए, सिर्फ़ पढ़ने के लिए उपलब्ध अन्य डायरेक्ट्री तय की जा सकती हैं. ऐसी डायरेक्ट्री से किसी फ़ाइल को तब लिया जाता है, जब उसका नाम, यूआरएल के बेस नाम के बराबर होता है. इसके अलावा, फ़ाइल का हैश, डाउनलोड अनुरोध में दिए गए नाम के बराबर होता है. यह सिर्फ़ तब काम करता है, जब WORKSPACE एलान में फ़ाइल हैश की जानकारी दी गई हो.
हालांकि, फ़ाइल के नाम पर शर्त सही होने के लिए ज़रूरी नहीं है, लेकिन यह तय की गई हर डायरेक्ट्री के लिए, कैंडिडेट फ़ाइलों की संख्या को एक कर देती है. इस तरह, डिस्ट्रिब्यूशन फ़ाइलों की डायरेक्ट्री तय करना कारगर रहता है. भले ही, ऐसी डायरेक्ट्री में फ़ाइलों की संख्या ज़्यादा हो.
एयरगेप्ड माहौल में बेज़ल दौड़ते हुए
Baze की बाइनरी साइज़ को छोटा रखने के लिए, पहली बार चलते समय Baज़ल की इंप्लिसिट डिपेंडेंसी को नेटवर्क पर फ़ेच किया जाता है. इन इंप्लिसिट डिपेंडेंसी में टूलचेन और नियम होते हैं, जो शायद सभी के लिए ज़रूरी न हों. उदाहरण के लिए, Android टूल को सिर्फ़ Android प्रोजेक्ट बनाते समय अनबंडल किया जाता है और फ़ेच किया जाता है.
हालांकि, ये इंप्लिसिट डिपेंडेंसी होने से एयरगेप किए गए एनवायरमेंट में बैजेल चलाते समय समस्या हो सकती है, भले ही आपने अपनी सभी वर्कस्पेस डिपेंडेंसी वेंडर कर ली हो. इस समस्या को हल करने के लिए, नेटवर्क ऐक्सेस वाली मशीन पर इन डिपेंडेंसी से जुड़ी डिस्ट्रिब्यूशन डायरेक्ट्री तैयार करें. इसके बाद, ऑफ़लाइन अप्रोच की मदद से इन डिपेंडेंसी को एयरगेप किए गए एनवायरमेंट में ट्रांसफ़र करें.
डिस्ट्रिब्यूशन डायरेक्ट्री तैयार करने के लिए, --distdir
फ़्लैग का इस्तेमाल करें. आपको हर नए Basel बाइनरी वर्शन के लिए ऐसा एक बार करना होगा, क्योंकि
हर रिलीज़ के लिए इंप्लिसिट डिपेंडेंसी अलग-अलग हो सकती हैं.
अपने एयरगैप किए गए एनवायरमेंट के बाहर इन डिपेंडेंसी को बनाने के लिए, सबसे पहले सही वर्शन में Bazel सोर्स ट्री को चेक आउट करें:
git clone https://github.com/bazelbuild/bazel "$BAZEL_DIR"
cd "$BAZEL_DIR"
git checkout "$BAZEL_VERSION"
इसके बाद, उस खास Bazel वर्शन के लिए, रनटाइम की लागू डिपेंडेंसी वाला टार्बॉल बनाएं:
bazel build @additional_distfiles//:archives.tar
इस टारबॉल को किसी ऐसी डायरेक्ट्री में एक्सपोर्ट करें जिसे आपके एयरगेप किए गए एनवायरमेंट में कॉपी किया जा सके. --strip-components
फ़्लैग पर ध्यान दें, क्योंकि --distdir
डायरेक्ट्री नेस्टिंग लेवल के साथ काफ़ी मुश्किल हो सकता है:
tar xvf bazel-bin/external/additional_distfiles/archives.tar \
-C "$NEW_DIRECTORY" --strip-components=3
आखिर में, अपने एयरगैप किए गए एनवायरमेंट में Bazel का इस्तेमाल करते समय, डायरेक्ट्री पर ले जाने वाला --distdir
फ़्लैग पास करें. आसानी के लिए, इसे .bazelrc
एंट्री के तौर पर जोड़ा जा सकता है:
build --distdir=path/to/directory
बिल्ड कॉन्फ़िगरेशन और क्रॉस-कंपाइलेशन
किसी खास बिल्ड के व्यवहार और नतीजे की जानकारी देने वाले सभी इनपुट को दो अलग-अलग कैटगरी में बांटा जा सकता है. पहली तरह की जानकारी आपके प्रोजेक्ट की BUILD
फ़ाइलों में सेव की गई अंदरूनी जानकारी होती है: बिल्ड रूल, इसके एट्रिब्यूट की वैल्यू, और इसकी ट्रांज़िटिव डिपेंडेंसी का पूरा सेट.
दूसरा टाइप, बाहरी या पर्यावरण से जुड़ा डेटा होता है. इसे उपयोगकर्ता या बिल्ड टूल से उपलब्ध कराया जाता है: टारगेट आर्किटेक्चर, कंपाइलेशन, और लिंक करने के विकल्प, और टूलचेन कॉन्फ़िगरेशन के अन्य विकल्प. हम पर्यावरण से जुड़े डेटा के पूरे सेट को कॉन्फ़िगरेशन कहते हैं.
किसी भी बिल्ड में, एक से ज़्यादा कॉन्फ़िगरेशन हो सकते हैं. क्रॉस-कंपाइलेशन का इस्तेमाल करें, जिसमें 64-बिट आर्किटेक्चर के लिए //foo:bin
एक्ज़ीक्यूटेबल बनाया जा सकता है. हालांकि, आपका वर्कस्टेशन 32-बिट मशीन है. साफ़ तौर पर, बिल्ड के लिए ऐसे टूलचेन का इस्तेमाल करके //foo:bin
बनाना होगा जो 64-बिट एक्ज़ीक्यूटेबल बनाने में सक्षम हो. हालांकि, बिल्ड सिस्टम में खुद बनाने के दौरान इस्तेमाल होने वाले अलग-अलग टूल भी बनाने चाहिए. उदाहरण के लिए, सोर्स से बनाए गए टूल, बाद में उन टूल में इस्तेमाल किए जाने वाले टूल, जैसे कि जेनरुल—और इन्हें आपके वर्कस्टेशन पर चलाने के लिए बनाया जाना चाहिए. इस तरह, हम दो कॉन्फ़िगरेशन की पहचान कर सकते हैं: होस्ट कॉन्फ़िगरेशन, जिसका इस्तेमाल बिल्ड के दौरान चलने वाले टूल बनाने के लिए किया जाता है और टारगेट कॉन्फ़िगरेशन (या कॉन्फ़िगरेशन का अनुरोध करें, लेकिन हम "टारगेट कॉन्फ़िगरेशन" को ज़्यादा कहते हैं. भले ही, उस शब्द के पहले से ही कई मतलब हों) जिसका इस्तेमाल आपने असल में अनुरोध की गई बाइनरी बनाने के लिए किया है.
आम तौर पर, ऐसी कई लाइब्रेरी होती हैं जो अनुरोध किए गए बिल्ड टारगेट (//foo:bin
) और एक या उससे ज़्यादा होस्ट टूल, दोनों के लिए ज़रूरी होती हैं. उदाहरण के लिए, कुछ बेस लाइब्रेरी. ऐसी लाइब्रेरी को दो बार बनाया जाना चाहिए. एक बार होस्ट कॉन्फ़िगरेशन के लिए और एक बार टारगेट कॉन्फ़िगरेशन के लिए. Bazel यह पक्का करता है कि दोनों वैरिएंट बनाए जाएं और इंटरफ़ियरेंस से बचने के लिए, डेरिव्ड फ़ाइलों को अलग रखा जाए. आम तौर पर, ऐसे टारगेट एक साथ बनाए जा सकते हैं, क्योंकि वे एक-दूसरे से अलग होते हैं. अगर आपको प्रोग्रेस मैसेज दिखते हैं, जिनसे पता चलता है कि किसी टारगेट को दो बार बनाया जा रहा है, तो इसकी वजह यह हो सकती है.
Basel, --distinct_host_configuration
विकल्प के आधार पर होस्ट कॉन्फ़िगरेशन को चुनने के लिए, दो में से किसी एक तरीके का इस्तेमाल करता है. यह बूलियन विकल्प थोड़ा मुश्किल है. साथ ही, इस सेटिंग से आपके बिल्ड की स्पीड बेहतर या खराब हो सकती है.
--distinct_host_configuration=false
इस विकल्प के गलत होने पर, होस्ट और अनुरोध के कॉन्फ़िगरेशन एक जैसे होते हैं: बिल्ड के दौरान ज़रूरी सभी टूल, टारगेट प्रोग्राम की तरह ही बनाए जाएंगे. इस सेटिंग का मतलब है कि एक बिल्ड के दौरान किसी भी लाइब्रेरी को दो बार बनाने की ज़रूरत नहीं होती.
हालांकि, इसका मतलब है कि आपके अनुरोध कॉन्फ़िगरेशन में किए गए किसी भी बदलाव का असर, आपके होस्ट कॉन्फ़िगरेशन पर भी पड़ता है. इस वजह से, सभी टूल फिर से बनाए जाते हैं. इसके बाद, टूल के आउटपुट पर निर्भर रहने वाली हर चीज़ को भी फिर से बनाया जाता है. उदाहरण के लिए, बिल्ड के बीच लिंकर के विकल्प को बदलने से, सभी टूल फिर से लिंक हो सकते हैं. इसके बाद, उनका इस्तेमाल करके की गई सभी कार्रवाइयां फिर से की जा सकती हैं. इस तरह, बहुत ज़्यादा रीबिल्ड होता है.
--distinct_host_configuration=true
(डिफ़ॉल्ट)
अगर यह विकल्प 'सही' पर सेट है, तो होस्ट और अनुरोध के लिए एक ही कॉन्फ़िगरेशन का इस्तेमाल करने के बजाय, पूरी तरह से अलग होस्ट कॉन्फ़िगरेशन का इस्तेमाल किया जाता है. होस्ट कॉन्फ़िगरेशन, टारगेट कॉन्फ़िगरेशन से इस तरह लिया जाता है:
- अनुरोध कॉन्फ़िगरेशन में बताए गए Crosstool (
--crosstool_top
) के उसी वर्शन का इस्तेमाल करें, जब तक कि--host_crosstool_top
की जानकारी न दी गई हो. --cpu
के लिए--host_cpu
की वैल्यू का इस्तेमाल करें (डिफ़ॉल्ट:k8
).- अनुरोध कॉन्फ़िगरेशन में बताई गई वैल्यू का इस्तेमाल करें:
--compiler
,--use_ijars
. अगर--host_crosstool_top
का इस्तेमाल किया जाता है, तो होस्ट कॉन्फ़िगरेशन के लिए, क्रॉसटूल मेंdefault_toolchain
को खोजने के लिए--host_cpu
की वैल्यू का इस्तेमाल किया जाता है (--compiler
को अनदेखा किया जाता है). --javabase
के लिए--host_javabase
की वैल्यू का इस्तेमाल करें--java_toolchain
के लिए--host_java_toolchain
की वैल्यू का इस्तेमाल करें- C++ कोड (
-c opt
) के लिए ऑप्टिमाइज़ किए गए बिल्ड का इस्तेमाल करें. - डीबग करने से जुड़ी कोई जानकारी जनरेट न करें (
--copt=-g0
). - रन किए जा सकने वाले प्रोग्राम और शेयर की गई लाइब्रेरी से डीबग की जानकारी हटाएं (
--strip=always
). - प्राप्त की गई सभी फ़ाइलों को किसी खास जगह पर रखें, जो किसी भी संभावित अनुरोध कॉन्फ़िगरेशन में इस्तेमाल की जाने वाली जगह से अलग हो.
- बिल्डर डेटा के साथ बाइनरी को स्टैंप करने की सुविधा बंद करें (
--embed_*
विकल्प देखें). - अन्य सभी वैल्यू, डिफ़ॉल्ट रूप से सेट रहती हैं.
अनुरोध कॉन्फ़िगरेशन से अलग होस्ट कॉन्फ़िगरेशन चुनने की कई वजहें हो सकती हैं. इनमें से कुछ के बारे में यहां बताना बेहद गोपनीय है, लेकिन इनमें से दो के बारे में बताना ज़रूरी है.
सबसे पहले, ऑप्टिमाइज़ की गई बाइनरी का इस्तेमाल करके, टूल को लिंक करने और एक्ज़ीक्यूट करने में लगने वाले समय को कम किया जा सकता है. साथ ही, टूल से लिए गए डिस्क स्टोरेज और डिस्ट्रिब्यूट किए गए बिल्ड में नेटवर्क I/O में लगने वाले समय को भी कम किया जा सकता है.
दूसरी बात, सभी बिल्ड में होस्ट और अनुरोध कॉन्फ़िगरेशन को अलग करने से, आपको फिर से बिल्ड करने की ज़रूरत नहीं पड़ती. ऐसा, अनुरोध कॉन्फ़िगरेशन में छोटे-मोटे बदलाव करने की वजह से होता है. जैसे, लिंकर के विकल्पों में बदलाव करना. इस बारे में पहले बताया गया है.
इसलिए, कुछ बिल्ड के लिए यह विकल्प परेशानी हो सकता है. खास तौर पर, ऐसे बिल्ड जिनमें कॉन्फ़िगरेशन के बदलाव कभी-कभी होते हैं (खास तौर पर कुछ Java बिल्ड) और ऐसे बिल्ड जिसमें होस्ट और टारगेट कॉन्फ़िगरेशन, दोनों में बनाए जाने वाले कोड की संख्या ज़्यादा हो, हो सकता है कि इससे फ़ायदा न हो.
इंक्रीमेंटल रीबिल्ड को ठीक करना
Bazel प्रोजेक्ट का एक मुख्य लक्ष्य, यह पक्का करना है कि इंक्रीमेंटल रीबिल्ड सही तरीके से हो. पहले के बिल्ड टूल, खास तौर पर वे टूल जो Make पर आधारित होते हैं, इंक्रीमेंटल बिल्ड को लागू करने के बारे में कई गलत अनुमान लगाते हैं.
सबसे पहले, फ़ाइलों के टाइमस्टैंप एक ही तरह से बढ़ जाते हैं. हालांकि, यह एक सामान्य स्थिति है, लेकिन इस ग़लतफ़हमी से वाकिफ़ होना बहुत आसान है. फ़ाइल के शुरुआती बदलाव के साथ सिंक करने से फ़ाइल का बदलाव करने में लगने वाला समय घट सकता है; मेक-आधारित सिस्टम फिर से नहीं बनेंगे.
आम तौर पर, जब 'बनाएं' फ़ाइलों में हुए बदलावों का पता लगाता है, तब यह कमांड में हुए बदलावों का पता नहीं लगाता. अगर किसी बिल्ड चरण में, कंपाइलर को पास किए गए विकल्पों में बदलाव किया जाता है, तो Make कंपाइलर को फिर से नहीं चलाएगा. साथ ही, make clean
का इस्तेमाल करके, पिछले बिल्ड के अमान्य आउटपुट को मैन्युअल तरीके से खारिज करना ज़रूरी है.
साथ ही, Make किसी सब-प्रोसेस के आउटपुट फ़ाइल में लिखना शुरू करने के बाद, उस सब-प्रोसेस को बंद नहीं कर पाता. Make का मौजूदा वर्शन काम नहीं करेगा. हालांकि, Make का अगला वर्शन, काट-छांट की गई आउटपुट फ़ाइल को मान्य मान लेगा, क्योंकि यह अपने इनपुट से नई है. साथ ही, इसे फिर से नहीं बनाया जाएगा. इसी तरह, अगर 'बनाएं' प्रोसेस खत्म हो जाती है, तो ऐसी ही स्थिति पैदा हो सकती है.
Bazel, इन और अन्य अनुमान से बचता है. Baज़ल, पहले हो चुके सभी कामों का डेटाबेस रखता है. बिल्ड चरण को सिर्फ़ तब मिटाता है, जब उसे पता चलता है कि इनपुट फ़ाइलों का सेट (और उनके टाइमस्टैंप) उस बिल्ड स्टेप के साथ और उस बिल्ड चरण के लिए कंपाइलेशन कमांड, डेटाबेस में मौजूद एक से एग्ज़ैक्ट मैच करती है. साथ ही, डेटाबेस एंट्री के लिए आउटपुट फ़ाइलों का सेट (और उनके टाइमस्टैंप) डिस्क पर मौजूद फ़ाइलों के टाइमस्टैंप से एग्ज़ैक्ट मैच करता है. इनपुट फ़ाइलों या आउटपुट फ़ाइलों में या कमांड में किए जाने वाले किसी भी बदलाव की वजह से, बिल्ड चरण फिर से लागू होगा.
सही इंक्रीमेंटल बिल्ड का इस्तेमाल करने से, उपयोगकर्ताओं को ये फ़ायदे मिलते हैं: भ्रम की वजह से कम समय बर्बाद होता है. (साथ ही, make
clean
के इस्तेमाल की वजह से इमारत को फिर से बनाने में लगने वाले इंतज़ार में कम समय लगता है, चाहे वह ज़रूरी हो या पहले से.)
नियमित तौर पर वीडियो बनाते रहें और लगातार बढ़ाएं
औपचारिक तौर पर, जब सभी अनुमानित आउटपुट फ़ाइलें मौजूद होती हैं और उनका कॉन्टेंट सही होता है, तो बिल्ड की स्थिति एक जैसी के तौर पर होती है. यह स्थिति, उन्हें बनाने के ज़रूरी चरणों या नियमों में बताई गई होती है. जब किसी सोर्स फ़ाइल में बदलाव किया जाता है, तो बिल्ड की स्थिति को अनियमित कहा जाता है. साथ ही, जब तक बिल्ड टूल को अगली बार पूरी तरह से नहीं चलाया जाता, तब तक बिल्ड की स्थिति में बदलाव नहीं होता. हम इस स्थिति को अस्थिरी के साथ होने वाला बदलाव कहते हैं, क्योंकि यह सिर्फ़ कुछ समय के लिए होता है. साथ ही, बिल्ड टूल को चलाने पर, यह स्थिति फिर से पहले जैसी हो जाती है.
हालांकि, एक और तरह की गड़बड़ी हो सकती है, जो नुकसान पहुंचाने वाली है: असमानता. अगर बिल्ड, एक जैसी स्थिति में नहीं रहता है, तो बिल्ड टूल को बार-बार इस्तेमाल करने से भी बिल्ड एक जैसा नहीं रहता: बिल्ड "स्टक" हो जाता है और आउटपुट गलत रहते हैं. मेक (और अन्य बिल्ड टूल) के make clean
टाइप का इस्तेमाल करने वाले उपयोगकर्ताओं की मुख्य वजह, लगातार एक जैसी नहीं रहने वाली स्थितियां हैं.
यह पता लगाना कि बिल्ड टूल इस तरह से काम नहीं कर रहा है और फिर उससे ठीक होना, समय लेने वाला और बहुत परेशान करने वाला हो सकता है.
सैद्धांतिक तौर पर, एक जैसा बिल्ड बनाने का सबसे आसान तरीका यह है कि आप पिछले सभी बिल्ड आउटपुट का इस्तेमाल न करें और फिर से शुरुआत करें: हर बिल्ड को एक क्लीन बिल्ड बनाएं. यह तरीका, शायद रिलीज़ इंजीनियर के अलावा, किसी और के लिए काम का नहीं है. ऐसा इसलिए है, क्योंकि इसमें काफ़ी समय लगता है. इसलिए, यह ज़रूरी है कि बिल्ड टूल, एक जैसी परफ़ॉर्मेंस बनाए रखते हुए, इंक्रीमेंटल बिल्ड कर सके.
इंक्रीमेंटल डिपेंडेंसी का सही विश्लेषण करना मुश्किल है. जैसा कि ऊपर बताया गया है, कई अन्य बिल्ड टूल, इंक्रीमेंटल बिल्ड के दौरान स्थिर और गलत स्टेटस से बचने के लिए खराब तरीके से काम करते हैं. इसके उलट, Bazel इस बात की गारंटी देता है: बगैर किसी बदलाव के, बाइल्ड टूल को इस्तेमाल करने के बाद, बाइल्ड एक जैसा रहेगा. (अगर बिल्ड के दौरान सोर्स फ़ाइलों में बदलाव किया जाता है, तो Basel, मौजूदा बिल्ड के नतीजे को एक जैसा बनाए रखने की कोई गारंटी नहीं देता है. हालांकि, इससे यह गारंटी मिलती है कि अगले बिल्ड के नतीजों से, एक जैसी परफ़ॉर्मेंस वापस आ जाएगी.)
जैसा कि सभी गारंटी के साथ किया जाता है, इसके कुछ अच्छे प्रिंट भी आते हैं: Basel के साथ स्थिर स्थिति में रहने के कुछ जाने-पहचाने तरीके हैं. हम इस बात की गारंटी नहीं देते कि हम इस तरह की समस्याओं की जांच करने की कोशिश करेंगे.
अगर आपको कभी Babel के साथ स्थिर और असंगत स्थिति का पता चलता है, तो कृपया एक बग की रिपोर्ट करें.
सैंडबॉक्स किया गया एक्ज़ीक्यूशन
बेज़ल, सैंडबॉक्स का इस्तेमाल करके यह गारंटी देते हैं कि कार्रवाइयां सही तरीके से और सही तरीके से की जाएं. Baज़ल, सैंडबॉक्स में spawns (कम शब्दों में जानकारी देने वाली: कार्रवाइयां) चलाता है. इसमें सिर्फ़ उन फ़ाइलों का कम सेट होता है जिनकी ज़रूरत टूल को अपना काम करने के लिए होती है. फ़िलहाल, सैंडबॉक्स, Linux 3.12 या इसके बाद के वर्शन पर काम करता है. हालांकि, इसमें CONFIG_USER_NS
विकल्प चालू है. यह macOS 10.11 या इसके बाद के वर्शन पर भी काम करती है.
अगर आपके सिस्टम में सैंडबॉक्सिंग की सुविधा काम नहीं करती है,
तो आपको बेज़ल से यह चेतावनी मिलेगी कि बिल्ड के हर्मेटिक होने की गारंटी नहीं है और
यह होस्ट सिस्टम पर अनजान तरीकों से असर डाल सकता है. इस चेतावनी को बंद करने के लिए, Bazel को --ignore_unsupported_sandboxing
फ़्लैग पास किया जा सकता है.
Google Kubernetes
Engine क्लस्टर नोड या Debian जैसे प्लैटफ़ॉर्म पर, सुरक्षा से जुड़ी समस्याओं की वजह से उपयोगकर्ता नेमस्पेस को डिफ़ॉल्ट रूप से बंद कर दिया जाता है. इसकी जांच /proc/sys/kernel/unprivileged_userns_clone
फ़ाइल को देखकर की जा सकती है: अगर यह मौजूद है और इसमें 0 है, तो उपयोगकर्ता नेमस्पेस को sudo sysctl kernel.unprivileged_userns_clone=1
की मदद से चालू किया जा सकता है.
कुछ मामलों में, सिस्टम सेटअप की वजह से Bazel सैंडबॉक्स, नियमों को लागू नहीं कर पाता. आम तौर पर, गड़बड़ी का पता तब चलता है, जब namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory
जैसा मैसेज दिखता है.
ऐसे मामले में, जनरेटिव नियम के लिए --strategy=Genrule=standalone
और दूसरे नियमों के लिए --spawn_strategy=standalone
के साथ सैंडबॉक्स को बंद करने की कोशिश करें. कृपया हमारे समस्या ट्रैकर पर भी गड़बड़ी की शिकायत करें. साथ ही, यह भी बताएं कि आपने कौनसा Linux डिस्ट्रिब्यूशन इस्तेमाल किया है, ताकि हम इसकी जांच कर सकें और अगली रिलीज़ में इसे ठीक कर सकें.
बिल्ड के चरण
Basel में, बिल्ड तीन अलग-अलग फ़ेज़ में होता है. एक उपयोगकर्ता के तौर पर, इन दोनों के बीच के अंतर को समझने से बिल्ड को कंट्रोल करने वाले विकल्पों के बारे में अहम जानकारी मिलती है (नीचे देखें).
लोड होने का चरण
पहली फ़ाइल, लोडिंग होती है. इस दौरान, शुरुआती टारगेट के लिए सभी ज़रूरी बिल्ड फ़ाइलें लोड होती हैं, पार्स की जाती हैं, आकलन की जाती हैं, और कैश मेमोरी में सेव की जाती हैं.
बेज़ल सर्वर के चालू होने के बाद, पहले बिल्ड के लिए लोड होने का चरण आम तौर पर कई सेकंड लगता है. ऐसा इसलिए होता है, क्योंकि फ़ाइल सिस्टम से कई बिल्ड फ़ाइलें लोड होती हैं. बाद में बनाए जाने वाले बिल्ड काफ़ी तेज़ी से लोड होते हैं. खास तौर पर तब, जब किसी बिल्ड फ़ाइल में बदलाव न किया गया हो.
इस चरण के दौरान रिपोर्ट की गई गड़बड़ियों में ये शामिल हैं: पैकेज नहीं मिला, टारगेट नहीं मिला, BUILD फ़ाइल में लेक्सिकल और व्याकरण से जुड़ी गड़बड़ियां, और आकलन से जुड़ी गड़बड़ियां.
विश्लेषण का चरण
दूसरा चरण, विश्लेषण है. इसमें हर बिल्ड नियम का सेमेटिक विश्लेषण और पुष्टि की जाती है. साथ ही, बिल्ड डिपेंडेंसी ग्राफ़ बनाया जाता है और यह तय किया जाता है कि बिल्ड के हर चरण में क्या काम करना है.
लोड होने की तरह ही, विश्लेषण में पूरी तरह से गणना होने में भी कुछ सेकंड लगते हैं. हालांकि, Baze, डिपेंडेंसी ग्राफ़ को एक बिल्ड से दूसरे बिल्ड में कैश करता है और सिर्फ़ अपनी मौजूदा ज़रूरतों का फिर से विश्लेषण करता है. इससे इंक्रीमेंटल बिल्ड को ऐसे मामले में बहुत तेज़ी से बनाया जा सकता है जहां पिछले बिल्ड के बाद से पैकेज में कोई बदलाव न हुआ हो.
इस चरण में रिपोर्ट की गई गड़बड़ियों में ये शामिल हैं: डिपेंडेंसी गलत है, नियम के लिए अमान्य इनपुट, और नियम से जुड़ी गड़बड़ी के सभी मैसेज.
लोड होने और विश्लेषण करने की प्रोसेस तेज़ी से होती है, क्योंकि Bazel इस चरण में फ़ाइल के ग़ैर-ज़रूरी I/O से बचता है. साथ ही, यह सिर्फ़ BUILD फ़ाइलों को पढ़ता है, ताकि यह तय किया जा सके कि क्या करना है. यह डिज़ाइन के हिसाब से है. इससे Bazel, विश्लेषण टूल के लिए एक अच्छा फ़ाउंडेशन बन जाता है. जैसे, Bazel का क्वेरी कमांड, जो लोड करने के फ़ेज़ के ऊपर लागू किया जाता है.
प्लान लागू करने का चरण
बिल्ड का तीसरा और आखिरी चरण लागू करना है. इस चरण से यह पक्का होता है कि बिल्ड के हर चरण के आउटपुट, उसके इनपुट से मेल खाते हों. साथ ही, ज़रूरत के मुताबिक कंपाइलेशन/लिंक करने/वगैरह. इस चरण में, बिल्ड का ज़्यादातर समय बीतता है. बड़े बिल्ड के लिए, इसमें कुछ सेकंड से लेकर एक घंटे से ज़्यादा समय लग सकता है. इस चरण के दौरान रिपोर्ट की गई गड़बड़ियों में ये शामिल हैं: सोर्स फ़ाइलें मौजूद न होना, बिल्ड ऐक्शन से लागू किए गए टूल में गड़बड़ियां या आउटपुट का उम्मीद के मुताबिक सेट बनाने में टूल का नाकाम होना.