Bazel की मदद से प्रोग्राम बनाएं

इस पेज पर, Bazel की मदद से प्रोग्राम बनाने, बिल्ड कमांड सिंटैक्स, और टारगेट पैटर्न सिंटैक्स के बारे में बताया गया है.

क्विकस्टार्ट

Bazel को चलाने के लिए, अपने बेस workspace डायरेक्ट्री या उसकी किसी भी सबडायरेक्ट्री पर जाएं और bazel टाइप करें. अगर आपको नया फ़ाइल फ़ोल्डर बनाना है, तो बनाएं पर जाएं.

bazel help
                             [Bazel release bazel version]
Usage: bazel command options ...

उपलब्ध निर्देश

  • analyze-profile: यह कुकी, बिल्ड प्रोफ़ाइल के डेटा का विश्लेषण करती है.
  • aquery: यह पोस्ट-ऐनलिसिस ऐक्शन ग्राफ़ पर क्वेरी को लागू करता है.
  • build: इससे तय किए गए टारगेट बनाए जाते हैं.
  • canonicalize-flags: Bazel फ़्लैग को कैननिकल करें.
  • clean: इससे आउटपुट फ़ाइलें हट जाती हैं. साथ ही, सर्वर को बंद करने का विकल्प भी मिलता है.
  • cquery: यह विश्लेषण के बाद डिपेंडेंसी ग्राफ़ क्वेरी को एक्ज़ीक्यूट करता है.
  • dump: Bazel सर्वर प्रोसेस की इंटरनल स्थिति को डंप करता है.
  • help: इससे कमांड या इंडेक्स के बारे में मदद मिलती है.
  • info: इससे Bazel सर्वर के रनटाइम की जानकारी दिखती है.
  • fetch: यह कमांड, टारगेट की सभी बाहरी डिपेंडेंसी फ़ेच करती है.
  • mobile-install: इससे मोबाइल डिवाइसों पर ऐप्लिकेशन इंस्टॉल किए जाते हैं.
  • query: डिपेंडेंसी ग्राफ़ क्वेरी को एक्ज़ीक्यूट करता है.
  • run: इससे तय किया गया टारगेट पूरा किया जाता है.
  • shutdown: Bazel सर्वर को बंद करता है.
  • test: इससे तय किए गए टेस्ट टारगेट बनाए जाते हैं और उन्हें चलाया जाता है.
  • version: Bazel के वर्शन की जानकारी दिखाता है.

सहायता पाना

  • bazel help command: command के लिए मदद और विकल्प प्रिंट करता है.
  • bazel helpstartup_options: Bazel को होस्ट करने वाले JVM के लिए विकल्प.
  • bazel helptarget-syntax: इससे टारगेट तय करने के सिंटैक्स के बारे में पता चलता है.
  • bazel help info-keys: इस विकल्प को चुनने पर, जानकारी देने वाली कमांड के लिए इस्तेमाल की गई कुंजियों की सूची दिखती है.

bazel टूल कई फ़ंक्शन करता है. इन्हें कमांड कहा जाता है. सबसे ज़्यादा इस्तेमाल होने वाले फ़ॉर्मैट bazel build और bazel test हैं. bazel help का इस्तेमाल करके, ऑनलाइन मदद से जुड़े मैसेज ब्राउज़ किए जा सकते हैं.

एक टारगेट बनाना

बिल्ड शुरू करने से पहले, आपके पास वर्कस्पेस होना चाहिए. वर्कस्पेस, डायरेक्ट्री ट्री होता है. इसमें आपके ऐप्लिकेशन को बनाने के लिए ज़रूरी सभी सोर्स फ़ाइलें होती हैं. Bazel की मदद से, सिर्फ़ रीड-ओनली वॉल्यूम से बिल्ड किया जा सकता है.

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

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

बिल्ड के एक्ज़ीक्यूशन फ़ेज़ के दौरान, Bazel प्रोग्रेस मैसेज प्रिंट करता है. प्रोग्रेस मैसेज में, मौजूदा बिल्ड स्टेप (जैसे कि कंपाइलर या लिंकर) शामिल होता है. साथ ही, इसमें बिल्ड की कुल कार्रवाइयों में से पूरी हो चुकी कार्रवाइयों की संख्या भी शामिल होती है. बिल्ड शुरू होने पर, कुल कार्रवाइयों की संख्या अक्सर बढ़ जाती है, क्योंकि 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' या उसकी डिपेंडेंसी में कोई बदलाव होता है, तो Bazel कुछ बिल्ड ऐक्शन को फिर से लागू करेगा या इंक्रीमेंटल बिल्ड को पूरा करेगा.

एक से ज़्यादा टारगेट बनाना

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 इसके बराबर है:
  • //foo/bar/wiz:wiz अगर foo/bar/wiz एक पैकेज है
  • //foo/bar:wiz अगर foo/bar एक पैकेज है
  • अन्य मामलों में //foo: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 जैसे बिल्डिंग टारगेट का इस्तेमाल नहीं किया जाता.

इसके अलावा, Bazel में लेबल सिंटैक्स के लिए ज़रूरी कोलन के बजाय, स्लैश का इस्तेमाल किया जा सकता है. Bash फ़ाइल के नाम को बड़ा करने की सुविधा का इस्तेमाल करते समय, यह अक्सर काम आता है. उदाहरण के लिए, foo/bar/wiz, //foo/bar:wiz के बराबर है (अगर कोई पैकेज foo/bar है) या //foo:bar/wiz के बराबर है (अगर कोई पैकेज foo है).

Bazel की कई कमांड, टारगेट पैटर्न की सूची को आर्ग्युमेंट के तौर पर स्वीकार करती हैं. साथ ही, वे सभी प्रीफ़िक्स नेगेशन ऑपरेटर - का पालन करती हैं. इसका इस्तेमाल, पहले दिए गए आर्ग्युमेंट से तय किए गए सेट से टारगेट के सेट को घटाने के लिए किया जा सकता है. ध्यान दें कि इसका मतलब है कि क्रम मायने रखता है. उदाहरण के लिए,

bazel build foo/... bar/...

का मतलब है "foo and के नीचे मौजूद सभी टारगेट और bar के नीचे मौजूद सभी टारगेट बनाएं", जबकि

bazel build -- foo/... -foo/bar/...

का मतलब है कि "foo/bar के नीचे मौजूद टारगेट को foo के नीचे मौजूद सभी टारगेट में शामिल न करें". (-- आर्ग्युमेंट इसलिए ज़रूरी है, ताकि - से शुरू होने वाले बाद के आर्ग्युमेंट को अतिरिक्त विकल्प के तौर पर न समझा जाए.)

हालांकि, यह बताना ज़रूरी है कि इस तरह से टारगेट हटाने से यह गारंटी नहीं मिलती कि उन्हें नहीं बनाया जाएगा. ऐसा इसलिए, क्योंकि हो सकता है कि वे उन टारगेट की डिपेंडेंसी हों जिन्हें हटाया नहीं गया है. उदाहरण के लिए, अगर कोई टारगेट //foo:all-apis है और वह //foo/bar:api पर निर्भर करता है, तो //foo:all-apis को बनाते समय //foo/bar:api को भी बनाया जाएगा.

tags = ["manual"] वाले टारगेट, वाइल्डकार्ड टारगेट पैटर्न (..., :*, :all वगैरह) में शामिल नहीं होते हैं. ऐसा तब होता है, जब उन्हें bazel build और bazel test जैसी कमांड में शामिल किया जाता है. हालांकि, ये नेगेटिव वाइल्डकार्ड टारगेट पैटर्न में शामिल होते हैं. इसका मतलब है कि इन्हें घटा दिया जाएगा. अगर आपको Bazel से इन टेस्ट टारगेट को बनाना/टेस्ट करना है, तो आपको कमांड लाइन पर टारगेट पैटर्न के साथ ऐसे टेस्ट टारगेट तय करने होंगे. इसके उलट, bazel query इस तरह की कोई भी फ़िल्टरिंग अपने-आप नहीं करता. ऐसा करने से, bazel query का मकसद पूरा नहीं होगा.

बाहरी डिपेंडेंसी फ़ेच की जा रही हैं

डिफ़ॉल्ट रूप से, Bazel बिल्ड के दौरान बाहरी डिपेंडेंसी को डाउनलोड और सिंक करेगा. हालांकि, ऐसा हो सकता है कि आपको यह पसंद न आए. इसकी वजह यह हो सकती है कि आपको यह जानना हो कि नई बाहरी डिपेंडेंसी कब जोड़ी गई हैं या आपको डिपेंडेंसी को "प्रीफ़ेच" करना हो. जैसे, किसी फ़्लाइट से पहले, जहां आपको इंटरनेट की सुविधा नहीं मिलेगी. अगर आपको बिल्ड के दौरान नई डिपेंडेंसी जोड़ने से रोकना है, तो --fetch=false फ़्लैग का इस्तेमाल करें. ध्यान दें कि यह फ़्लैग सिर्फ़ उन रिपॉज़िटरी नियमों पर लागू होता है जो लोकल फ़ाइल सिस्टम में किसी डायरेक्ट्री की ओर इशारा नहीं करते. बदलाव, जैसे कि local_repository, new_local_repository और Android SDK और NDK रिपॉज़िटरी के नियमों में बदलाव, --fetch की वैल्यू कुछ भी हो, हमेशा लागू होंगे .

अगर आपने बिल्ड के दौरान फ़ेच करने की अनुमति नहीं दी है और Bazel को नई बाहरी डिपेंडेंसी मिलती हैं, तो आपका बिल्ड पूरा नहीं हो पाएगा.

bazel fetch चलाकर, डिपेंडेंसी को मैन्युअल तरीके से फ़ेच किया जा सकता है. अगर आपने बिल्ड के दौरान फ़ेच करने की अनुमति नहीं दी है, तो आपको bazel fetch चलाना होगा:

  • पहली बार ऐप्लिकेशन बनाने से पहले.
  • बाहरी तौर पर निर्भर रहने वाली कोई नई सुविधा जोड़ने के बाद.

एक बार इस कमांड को चलाने के बाद, आपको इसे तब तक दोबारा चलाने की ज़रूरत नहीं होगी, जब तक MODULE.bazel फ़ाइल में बदलाव नहीं होता.

fetch, उन टारगेट की सूची लेता है जिनके लिए डिपेंडेंसी फ़ेच करनी होती हैं. उदाहरण के लिए, इससे //foo:bar और //bar:baz को बनाने के लिए ज़रूरी डिपेंडेंसी फ़ेच की जाएंगी:

bazel fetch //foo:bar //bar:baz

किसी वर्कस्पेस के लिए सभी बाहरी डिपेंडेंसी फ़ेच करने के लिए, यह कमांड चलाएं:

bazel fetch //...

अगर आपने Bzlmod चालू किया है, तो Bazel 7 या इसके बाद के वर्शन में, सभी बाहरी डिपेंडेंसी को भी फ़ेच किया जा सकता है. इसके लिए, आपको यह कमांड चलानी होगी

bazel fetch

अगर आपके पास अपने वर्कस्पेस रूट में, इस्तेमाल किए जा रहे सभी टूल (लाइब्रेरी जार से लेकर JDK तक) हैं, तो आपको bazel fetch चलाने की ज़रूरत नहीं है. हालांकि, अगर वर्कस्पेस डायरेक्ट्री के बाहर किसी चीज़ का इस्तेमाल किया जा रहा है, तो Bazel, bazel fetch को चलाने से पहले bazel build को अपने-आप चला देगा.

रिपॉज़िटरी की कैश मेमोरी

Bazel एक ही फ़ाइल को कई बार फ़ेच करने से बचता है. भले ही, एक ही फ़ाइल की ज़रूरत अलग-अलग वर्कस्पेस में हो या बाहरी रिपॉज़िटरी की परिभाषा बदल गई हो, लेकिन उसे डाउनलोड करने के लिए अब भी उसी फ़ाइल की ज़रूरत हो. इसके लिए, Bazel, रिपॉज़िटरी कैश में डाउनलोड की गई सभी फ़ाइलों को कैश मेमोरी में सेव करता है. डिफ़ॉल्ट रूप से, यह ~/.cache/bazel/_bazel_$USER/cache/repos/v1/ पर मौजूद होता है. --repository_cache विकल्प से जगह की जानकारी बदली जा सकती है. कैश को सभी वर्कस्पेस और Bazel के इंस्टॉल किए गए वर्शन के बीच शेयर किया जाता है. कैश से कोई एंट्री तब ली जाती है, जब Bazel को यह पक्का पता हो कि उसके पास सही फ़ाइल की कॉपी है. इसका मतलब है कि अगर डाउनलोड करने के अनुरोध में बताई गई फ़ाइल का SHA256 सम है और उस हैश वाली फ़ाइल कैश में मौजूद है, तो कैश से कोई एंट्री ली जाती है. इसलिए, हर बाहरी फ़ाइल के लिए हैश तय करना, सुरक्षा के लिहाज़ से न सिर्फ़ एक अच्छा विचार है, बल्कि इससे गैर-ज़रूरी डाउनलोड से बचने में भी मदद मिलती है.

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

[बंद कर दिया गया] डिस्ट्रिब्यूशन फ़ाइलों की डायरेक्ट्री

इस्तेमाल बंद कर दिया गया है: ऑफ़लाइन बिल्ड के लिए, रिपॉज़िटरी कैश का इस्तेमाल करना बेहतर होता है.

डिस्ट्रिब्यूशन डायरेक्ट्री, Bazel का एक और तरीका है. इससे गैर-ज़रूरी डाउनलोड से बचा जा सकता है. Bazel, रिपॉज़िटरी कैश से पहले डिस्ट्रिब्यूशन डायरेक्ट्री खोजता है. इन दोनों में मुख्य अंतर यह है कि डिस्ट्रिब्यूशन डायरेक्ट्री को मैन्युअल तरीके से तैयार करना होता है.

--distdir=/path/to-directory विकल्प का इस्तेमाल करके, सिर्फ़ पढ़ने के लिए उपलब्ध अतिरिक्त डायरेक्ट्री तय की जा सकती हैं. इससे फ़ाइलों को फ़ेच करने के बजाय, उन्हें ढूंढा जा सकता है. किसी फ़ाइल को ऐसी डायरेक्ट्री से तब लिया जाता है, जब फ़ाइल का नाम यूआरएल के बेस नेम के बराबर हो. साथ ही, फ़ाइल का हैश, डाउनलोड करने के अनुरोध में दिए गए हैश के बराबर हो. यह सिर्फ़ तब काम करता है, जब रिपॉज़िटरी के नियम के एलान में फ़ाइल हैश के बारे में बताया गया हो.

फ़ाइल के नाम के लिए यह शर्त ज़रूरी नहीं है. हालांकि, इससे हर डायरेक्ट्री के लिए, कैंडिडेट फ़ाइलों की संख्या कम होकर एक हो जाती है. इस तरह, डिस्ट्रिब्यूशन फ़ाइलों की डायरेक्ट्री तय करना ज़्यादा असरदार होता है. भले ही, ऐसी डायरेक्ट्री में फ़ाइलों की संख्या बढ़ जाए.

एयरगैप्ड एनवायरमेंट में Bazel का इस्तेमाल करना

Bazel के बाइनरी साइज़ को छोटा रखने के लिए, Bazel की इंप्लिसिट डिपेंडेंसी को पहली बार चलाने के दौरान नेटवर्क से फ़ेच किया जाता है. इन इंप्लिसिट डिपेंडेंसी में टूलचेन और ऐसे नियम शामिल होते हैं जो सभी के लिए ज़रूरी नहीं होते. उदाहरण के लिए, Android टूल को अनबंडल किया जाता है और Android प्रोजेक्ट बनाते समय ही फ़ेच किया जाता है.

हालांकि, एयरगैप्ड एनवायरमेंट में Bazel को चलाने पर, इन इंप्लिसिट डिपेंडेंसी की वजह से समस्याएं आ सकती हैं. भले ही, आपने अपनी सभी बाहरी डिपेंडेंसी को वेंडर किया हो. इस समस्या को हल करने के लिए, नेटवर्क ऐक्सेस वाले किसी मशीन पर इन डिपेंडेंसी वाली रिपॉज़िटरी कैश मेमोरी (Bazel 7 या इसके बाद के वर्शन के साथ) या डिस्ट्रिब्यूशन डायरेक्ट्री (Bazel 7 से पहले के वर्शन के साथ) तैयार की जा सकती है. इसके बाद, इन्हें ऑफ़लाइन तरीके से एयरगैप्ड एनवायरमेंट में ट्रांसफ़र किया जा सकता है.

डेटाबेस की कैश मेमोरी (Bazel 7 या इसके बाद के वर्शन के साथ)

रिपॉज़िटरी कैश मेमोरी तैयार करने के लिए, --repository_cache फ़्लैग का इस्तेमाल करें. आपको हर नए Bazel बाइनरी वर्शन के लिए, ऐसा एक बार करना होगा. ऐसा इसलिए, क्योंकि हर रिलीज़ के लिए, इंप्लिसिट डिपेंडेंसी अलग-अलग हो सकती हैं.

अपने एयरगैप्ड एनवायरमेंट के बाहर उन डिपेंडेंसी को फ़ेच करने के लिए, सबसे पहले एक खाली फ़ाइल फ़ोल्डर बनाएं:

mkdir empty_workspace && cd empty_workspace
touch MODULE.bazel

पहले से मौजूद Bzlmod डिपेंडेंसी फ़ेच करने के लिए, यह कमांड चलाएं

bazel fetch --repository_cache="path/to/repository/cache"

अगर आपको अब भी लेगसी WORKSPACE फ़ाइल का इस्तेमाल करना है, तो बिल्ट-इन WORKSPACE डिपेंडेंसी फ़ेच करने के लिए, यह कमांड चलाएं

bazel sync --repository_cache="path/to/repository/cache"

आखिर में, एयरगैप्ड एनवायरमेंट में Bazel का इस्तेमाल करते समय, उसी --repository_cache फ़्लैग को पास करें. आसानी के लिए, इसे .bazelrc एंट्री के तौर पर जोड़ा जा सकता है:

common --repository_cache="path/to/repository/cache"

इसके अलावा, आपको BCR को स्थानीय तौर पर क्लोन करने की भी ज़रूरत पड़ सकती है. साथ ही, --registry फ़्लैग का इस्तेमाल करके, अपनी स्थानीय कॉपी को पॉइंट करना पड़ सकता है, ताकि Bazel इंटरनेट के ज़रिए BCR को ऐक्सेस न कर पाए. अपनी .bazelrc फ़ाइल में यह लाइन जोड़ें:

common --registry="path/to/local/bcr/registry"
डिस्ट्रिब्यूशन डायरेक्ट्री (Bazel 7 से पहले)

डिस्ट्रिब्यूशन डायरेक्ट्री तैयार करने के लिए, --distdir फ़्लैग का इस्तेमाल करें. आपको हर नए Bazel बाइनरी वर्शन के लिए, ऐसा एक बार करना होगा. ऐसा इसलिए, क्योंकि हर रिलीज़ के लिए, इंप्लिसिट डिपेंडेंसी अलग-अलग हो सकती हैं.

एयरगैप्ड एनवायरमेंट के बाहर इन डिपेंडेंसी को बनाने के लिए, सबसे पहले 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-बिट एक्ज़ीक्यूटेबल बना सके. हालांकि, बिल्ड सिस्टम को बिल्ड के दौरान इस्तेमाल किए जाने वाले अलग-अलग टूल भी बनाने होंगे. उदाहरण के लिए, ऐसे टूल जो सोर्स से बनाए जाते हैं. इसके बाद, इनका इस्तेमाल, मान लें कि किसी genrule में किया जाता है. साथ ही, इन्हें आपके वर्कस्टेशन पर चलाने के लिए बनाया जाना चाहिए. इसलिए, हम दो कॉन्फ़िगरेशन की पहचान कर सकते हैं: exec कॉन्फ़िगरेशन, जिसका इस्तेमाल बिल्ड के दौरान चलने वाले टूल बनाने के लिए किया जाता है. दूसरा, टारगेट कॉन्फ़िगरेशन (या अनुरोध कॉन्फ़िगरेशन, लेकिन हम "टारगेट कॉन्फ़िगरेशन" का इस्तेमाल ज़्यादा करते हैं, भले ही इस शब्द के पहले से ही कई मतलब हों). इसका इस्तेमाल, उस बाइनरी को बनाने के लिए किया जाता है जिसका आपने अनुरोध किया था.

आम तौर पर, कई ऐसी लाइब्रेरी होती हैं जो अनुरोध किए गए बिल्ड टारगेट (//foo:bin) और एक या उससे ज़्यादा एक्ज़ेक टूल, दोनों के लिए ज़रूरी होती हैं. उदाहरण के लिए, कुछ बेस लाइब्रेरी. ऐसी लाइब्रेरी को दो बार बनाना होगा. एक बार एक्ज़ेक कॉन्फ़िगरेशन के लिए और दूसरी बार टारगेट कॉन्फ़िगरेशन के लिए. Bazel यह पक्का करता है कि दोनों वैरिएंट बनाए गए हों और उनसे मिली फ़ाइलों को अलग रखा गया हो, ताकि कोई रुकावट न आए. आम तौर पर, ऐसे टारगेट एक साथ बनाए जा सकते हैं, क्योंकि वे एक-दूसरे से अलग होते हैं. अगर आपको प्रोग्रेस मैसेज दिखते हैं, जिनसे पता चलता है कि किसी टारगेट को दो बार बनाया जा रहा है, तो इसकी वजह यही हो सकती है.

एक्ज़ेक कॉन्फ़िगरेशन, टारगेट कॉन्फ़िगरेशन से इस तरह मिलता है:

  • अनुरोध के कॉन्फ़िगरेशन में बताए गए Crosstool (--crosstool_top) के उसी वर्शन का इस्तेमाल करें. हालांकि, अगर --host_crosstool_top के बारे में बताया गया है, तो उसका इस्तेमाल करें.
  • --cpu के लिए --host_cpu की वैल्यू का इस्तेमाल करें (डिफ़ॉल्ट: k8).
  • इन विकल्पों की वही वैल्यू इस्तेमाल करें जो अनुरोध कॉन्फ़िगरेशन में दी गई हैं: --compiler, --use_ijars. अगर --host_crosstool_top का इस्तेमाल किया जाता है, तो exec कॉन्फ़िगरेशन के लिए, --host_cpu की वैल्यू का इस्तेमाल Crosstool में default_toolchain को खोजने के लिए किया जाता है. इसमें --compiler को अनदेखा किया जाता है.
  • --javabase के लिए --host_javabase की वैल्यू का इस्तेमाल करें
  • --java_toolchain के लिए --host_java_toolchain की वैल्यू का इस्तेमाल करें
  • C++ कोड (-c opt) के लिए, ऑप्टिमाइज़ की गई बिल्ड का इस्तेमाल करें.
  • डीबग करने की कोई जानकारी जनरेट न करें (--copt=-g0).
  • एक्ज़ीक्यूटेबल और शेयर की गई लाइब्रेरी से डीबग करने की जानकारी हटाएं (--strip=always).
  • सभी डिराइव की गई फ़ाइलों को एक खास जगह पर रखें. यह जगह, अनुरोध कॉन्फ़िगरेशन के लिए इस्तेमाल की गई जगह से अलग होनी चाहिए.
  • बाइनरी पर बिल्ड डेटा की स्टैंपिंग को बंद करें (--embed_* विकल्प देखें).
  • अन्य सभी वैल्यू, डिफ़ॉल्ट पर सेट रहती हैं.

अनुरोध के कॉन्फ़िगरेशन से अलग एक्ज़ेक कॉन्फ़िगरेशन चुनने की कई वजहें हो सकती हैं. सबसे ज़रूरी बात:

सबसे पहले, स्ट्रिप्ड और ऑप्टिमाइज़ किए गए बाइनरी का इस्तेमाल करके, टूल को लिंक और एक्ज़ीक्यूट करने में लगने वाला समय कम किया जा सकता है. साथ ही, टूल के लिए डिस्क स्पेस और डिस्ट्रिब्यूटेड बिल्ड में नेटवर्क I/O का समय भी कम किया जा सकता है.

दूसरा, सभी बिल्ड में एक्ज़ेक और अनुरोध कॉन्फ़िगरेशन को अलग करके, आपको बहुत महंगे रीबिल्ड से बचने में मदद मिलती है. ये रीबिल्ड, अनुरोध कॉन्फ़िगरेशन में मामूली बदलावों की वजह से होते हैं. जैसे, लिंक करने वाले विकल्प को बदलने से होता है. इसके बारे में पहले बताया गया है.

इंक्रीमेंटल रीबिल्ड की प्रोसेस को ठीक करना

Bazel प्रोजेक्ट का मुख्य लक्ष्य, यह पक्का करना है कि इंक्रीमेंटल रीबिल्ड सही तरीके से हों. पिछले बिल्ड टूल, खास तौर पर Make पर आधारित टूल, इंक्रीमेंटल बिल्ड को लागू करने में कई गलत अनुमान लगाते हैं.

पहला, फ़ाइलों के टाइमस्टैंप लगातार बढ़ते रहने चाहिए. हालांकि, आम तौर पर ऐसा ही होता है, लेकिन इस अनुमान के हिसाब से काम करना बहुत आसान है. किसी फ़ाइल के पिछले वर्शन के साथ सिंक करने से, उस फ़ाइल में बदलाव करने का समय कम हो जाता है. मेक पर आधारित सिस्टम, फिर से नहीं बनाए जाएंगे.

आम तौर पर, Make फ़ाइलों में हुए बदलावों का पता लगाता है, लेकिन यह कमांड में हुए बदलावों का पता नहीं लगाता. अगर किसी बिल्ड स्टेप में कंपाइलर को पास किए गए विकल्पों में बदलाव किया जाता है, तो Make कंपाइलर को फिर से नहीं चलाएगा. साथ ही, make clean का इस्तेमाल करके, पिछली बिल्ड के अमान्य आउटपुट को मैन्युअल तरीके से खारिज करना ज़रूरी है.

इसके अलावा, Make इस बात का पता नहीं लगा पाता कि कोई सबप्रोसेस अपनी आउटपुट फ़ाइल में लिखना शुरू करने के बाद, बंद हो गई है या नहीं. फ़िलहाल, Make का मौजूदा प्रोसेस पूरा नहीं हो पाएगा. हालांकि, Make का बाद का प्रोसेस यह मान लेगा कि काटी गई आउटपुट फ़ाइल मान्य है, क्योंकि यह इनपुट फ़ाइलों से नई है. इसलिए, इसे फिर से नहीं बनाया जाएगा. इसी तरह, अगर Make प्रोसेस बंद हो जाती है, तो ऐसी ही स्थिति पैदा हो सकती है.

Bazel इन और अन्य मान्यताओं से बचता है. Bazel, पहले किए गए सभी कामों का डेटाबेस बनाए रखता है. यह सिर्फ़ तब किसी बिल्ड स्टेप को छोड़ता है, जब उसे पता चलता है कि उस बिल्ड स्टेप के लिए इनपुट फ़ाइलों का सेट (और उनके टाइमस्टैंप) और उस बिल्ड स्टेप के लिए कंपाइल करने का कमांड, डेटाबेस में मौजूद किसी एक से पूरी तरह मेल खाता है. साथ ही, डेटाबेस एंट्री के लिए आउटपुट फ़ाइलों का सेट (और उनके टाइमस्टैंप), डिस्क पर मौजूद फ़ाइलों के टाइमस्टैंप से पूरी तरह मेल खाता है. इनपुट फ़ाइलों, आउटपुट फ़ाइलों या कमांड में किसी भी तरह का बदलाव करने पर, बिल्ड स्टेप फिर से लागू होगा.

सही इंक्रीमेंटल बिल्ड से उपयोगकर्ताओं को यह फ़ायदा मिलता है: भ्रम की वजह से कम समय बर्बाद होता है. (इसके अलावा, make clean का इस्तेमाल करने की वजह से, फिर से बनाने में लगने वाला समय भी कम हो जाता है. भले ही, यह ज़रूरी हो या पहले से किया गया हो.)

लगातार और धीरे-धीरे बेहतर बनाना

हम किसी बिल्ड की स्थिति को एक जैसी तब कहते हैं, जब सभी ज़रूरी आउटपुट फ़ाइलें मौजूद हों और उनका कॉन्टेंट सही हो. यह कॉन्टेंट, उन्हें बनाने के लिए ज़रूरी चरणों या नियमों के मुताबिक होना चाहिए. सोर्स फ़ाइल में बदलाव करने पर, बिल्ड की स्थिति को असंगत कहा जाता है. यह स्थिति तब तक बनी रहती है, जब तक बिल्ड टूल को फिर से चलाकर बिल्ड को पूरा नहीं किया जाता. हम इस स्थिति को अस्थिरता कहते हैं, क्योंकि यह सिर्फ़ कुछ समय के लिए होती है. बिल्ड टूल चलाने पर, स्थिरता वापस आ जाती है.

एक और तरह की गड़बड़ी होती है, जो नुकसान पहुंचा सकती है: स्थिर गड़बड़ी. अगर बिल्ड, लगातार बदलती हुई स्टेबल स्थिति में पहुंच जाता है, तो बिल्ड टूल को बार-बार इस्तेमाल करने से भी बिल्ड की स्थिति ठीक नहीं होती. बिल्ड "अटक" जाता है और आउटपुट गलत बने रहते हैं. स्थिरता से जुड़ी समस्याएं, Make और अन्य बिल्ड टूल के उपयोगकर्ताओं के लिए मुख्य समस्या हैं make clean. यह पता लगाने में समय लग सकता है कि बिल्ड टूल इस तरह से काम नहीं कर रहा है. साथ ही, इससे ठीक होने में भी समय लग सकता है. इससे आपको काफ़ी परेशानी हो सकती है.

लगातार बिल्ड करने का सबसे आसान तरीका यह है कि पिछली सभी बिल्ड आउटपुट को हटा दिया जाए और फिर से शुरू किया जाए. हर बिल्ड को क्लीन बिल्ड बनाएं. यह तरीका बहुत ज़्यादा समय लेता है. इसलिए, इसका इस्तेमाल नहीं किया जा सकता. हालांकि, रिलीज़ इंजीनियर इसका इस्तेमाल कर सकते हैं. इसलिए, बिल्ड टूल को लगातार बिल्ड करने में सक्षम होना चाहिए, ताकि बिल्ड की स्थिरता से समझौता न करना पड़े.

इंक्रीमेंटल डिपेंडेंसी का सही विश्लेषण करना मुश्किल है. ऊपर बताया गया है कि कई अन्य बिल्ड टूल, इंक्रीमेंटल बिल्ड के दौरान स्टेबल इनकंसिस्टेंट स्टेट से बचने के लिए सही तरीके से काम नहीं करते हैं. इसके उलट, Bazel यह गारंटी देता है कि बिल्ड टूल को सही तरीके से इस्तेमाल करने के बाद, बिल्ड एक जैसी स्थिति में होगा. इस दौरान, आपने कोई बदलाव नहीं किया होगा. (अगर बिल्ड के दौरान सोर्स फ़ाइलों में बदलाव किया जाता है, तो Bazel इस बात की कोई गारंटी नहीं देता कि मौजूदा बिल्ड के नतीजे एक जैसे होंगे. हालांकि, इससे यह गारंटी मिलती है कि अगले बिल्ड के नतीजे पहले जैसे ही होंगे.)

सभी गारंटी की तरह, इसमें भी कुछ बारीक बातें हैं: Bazel के साथ, कुछ ऐसे तरीके हैं जिनसे आपको लगातार अलग-अलग नतीजे मिल सकते हैं. हम इंक्रीमेंटल डिपेंडेंसी विश्लेषण में गड़बड़ियां ढूंढने के जान-बूझकर किए गए प्रयासों से होने वाली ऐसी समस्याओं की जांच करने की गारंटी नहीं देते. हालांकि, हम बिल्ड टूल के सामान्य या "सही" इस्तेमाल से होने वाली सभी स्टेबल इनकंसिस्टेंट स्थितियों की जांच करेंगे और उन्हें ठीक करने की पूरी कोशिश करेंगे.

अगर आपको कभी Bazel में कोई ऐसी स्थिति दिखती है जिसमें बदलाव नहीं हो रहा है, लेकिन वह सही नहीं है, तो कृपया गड़बड़ी की शिकायत करें.

सैंडबॉक्स में स्क्रिप्ट को एक्ज़ीक्यूट करना

Bazel, सैंडबॉक्स का इस्तेमाल करता है. इससे यह पक्का किया जाता है कि कार्रवाइयां, हर्मेटिक तरीके से और सही तरीके से चलें. Bazel, सैंडबॉक्स में स्पॉन (आसान शब्दों में: कार्रवाइयां) करता है. इन सैंडबॉक्स में सिर्फ़ वे फ़ाइलें होती हैं जिनकी ज़रूरत टूल को अपना काम करने के लिए होती है. फ़िलहाल, सैंडबॉक्सिंग की सुविधा Linux 3.12 या इसके बाद के वर्शन पर काम करती है. इसके लिए, CONFIG_USER_NS विकल्प चालू होना चाहिए. यह सुविधा macOS 10.11 या इसके बाद के वर्शन पर भी काम करती है.

अगर आपका सिस्टम सैंडबॉक्सिंग के साथ काम नहीं करता है, तो Bazel एक चेतावनी प्रिंट करेगा. इससे आपको यह सूचना मिलेगी कि बिल्ड के हर्मेटिक होने की गारंटी नहीं है. साथ ही, यह होस्ट सिस्टम को अनजाने तरीकों से प्रभावित कर सकता है. इस चेतावनी को बंद करने के लिए, 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 का कौनसा डिस्ट्रिब्यूशन इस्तेमाल किया जा रहा है, ताकि हम इसकी जांच कर सकें और आने वाले समय में इसे ठीक कर सकें.

बिल्ड के चरण

Bazel में, बिल्ड तीन अलग-अलग चरणों में होता है. उपयोगकर्ता के तौर पर, इन चरणों के बीच के अंतर को समझने से, उन विकल्पों के बारे में जानकारी मिलती है जो बिल्ड को कंट्रोल करते हैं (नीचे देखें).

लोडिंग फ़ेज़

पहला चरण लोडिंग का होता है. इस दौरान, शुरुआती टारगेट और उनकी ट्रांज़िटिव क्लोज़र डिपेंडेंसी के लिए सभी ज़रूरी BUILD फ़ाइलें लोड की जाती हैं. इसके बाद, उन्हें पार्स किया जाता है, उनका आकलन किया जाता है, और उन्हें कैश मेमोरी में सेव किया जाता है.

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

इस फ़ेज़ के दौरान ये गड़बड़ियां रिपोर्ट की जाती हैं: पैकेज नहीं मिला, टारगेट नहीं मिला, BUILD फ़ाइल में लेक्सिकल और व्याकरण से जुड़ी गड़बड़ियां, और आकलन से जुड़ी गड़बड़ियां.

विश्लेषण का चरण

दूसरे चरण, विश्लेषण में, हर बिल्ड नियम का सिमैंटिक विश्लेषण और पुष्टि करना, बिल्ड डिपेंडेंसी ग्राफ़ बनाना, और यह तय करना शामिल है कि बिल्ड के हर चरण में क्या काम करना है.

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

इस चरण में ये गड़बड़ियां रिपोर्ट की जाती हैं: गलत डिपेंडेंसी, किसी नियम के लिए अमान्य इनपुट, और नियम से जुड़ी सभी गड़बड़ी के मैसेज.

लोडिंग और विश्लेषण के चरण तेज़ी से पूरे होते हैं, क्योंकि Bazel इस चरण में फ़ाइल के बेवजह I/O से बचता है. यह सिर्फ़ BUILD फ़ाइलों को पढ़ता है, ताकि यह तय किया जा सके कि कौनसे काम करने हैं. यह डिज़ाइन के हिसाब से है. इससे Bazel, विश्लेषण टूल के लिए एक अच्छा प्लैटफ़ॉर्म बन जाता है. जैसे, Bazel की query कमांड, जिसे लोडिंग फ़ेज़ के ऊपर लागू किया जाता है.

लागू करने का चरण

बनाने की प्रोसेस का तीसरा और आखिरी चरण, एक्ज़ीक्यूशन है. इस फ़ेज़ में यह पक्का किया जाता है कि बिल्ड के हर चरण के आउटपुट, उसके इनपुट के मुताबिक हों. साथ ही, ज़रूरत के मुताबिक कंपाइलेशन/लिंकिंग वगैरह के टूल को फिर से चलाया जाता है. इस चरण में, बिल्ड को ज़्यादा समय लगता है. बड़े बिल्ड के लिए, इसमें कुछ सेकंड से लेकर एक घंटे से ज़्यादा समय लग सकता है. इस चरण के दौरान रिपोर्ट की गई गड़बड़ियों में ये शामिल हैं: सोर्स फ़ाइलें मौजूद न होना, कुछ बिल्ड ऐक्शन से लागू किए गए टूल में गड़बड़ियां होना या टूल के ज़रिए उम्मीद के मुताबिक आउटपुट न मिलना.