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

किसी समस्या की शिकायत करें सोर्स देखें Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

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

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

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

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

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

सहायता पाना

  • bazel help command: प्रिंट सहायता और command के लिए विकल्प.
  • bazel helpstartup_options: JVM होस्ट करने वाले बैजल के लिए विकल्प.
  • bazel helptarget-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

सबसे पहले, Bazel आपके टारगेट के डिपेंडेंसी ग्राफ़ में सभी पैकेज लोड करता है. इसमें एलान की गई डिपेंडेंसी शामिल हैं. ये फ़ाइलें, टारगेट की BUILD फ़ाइल में सीधे तौर पर शामिल होती हैं. साथ ही, इसमें ट्रांज़िशन डिपेंडेंसी भी शामिल हैं. ये फ़ाइलें, टारगेट की डिपेंडेंसी की BUILD फ़ाइलों में शामिल होती हैं. सभी डिपेंडेंसी की पहचान करने के बाद, 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 इसके बराबर:
  • //foo/bar/wiz:wiz अगर foo/bar/wiz पैकेज है
  • अगर foo/bar एक पैकेज है, तो //foo/bar:wiz
  • अन्य मामलों में//foo:bar/wiz
bar:all //foo/bar:all के बराबर.
:all //foo:all के बराबर.
...:all //foo/...:all के बराबर.
... //foo/...:all के बराबर.
bar/...:all //foo/bar/...:all के बराबर.

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

इसके अलावा, 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 और bar के नीचे मौजूद सभी टारगेट बनाएं", जबकि

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

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

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

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

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

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

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

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

  • पहली बार बनाने से पहले.
  • नई बाहरी डिपेंडेंसी जोड़ने के बाद.

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

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

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

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

bazel fetch //...

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

bazel fetch

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

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

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

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

[अब काम नहीं करती] डिस्ट्रिब्यूशन फ़ाइलों की डायरेक्ट्री

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

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

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

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

एयरगेप्ड माहौल में बेज़ल दौड़ते हुए

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

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

डेटा स्टोर करने की जगह की कैश मेमोरी (Bazu 7 या उसके बाद के वर्शन के साथ)

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

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

mkdir empty_workspace && cd empty_workspace
touch MODULE.bazel

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

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

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

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

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

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

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

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

डिस्ट्रिब्यूशन डायरेक्ट्री तैयार करने के लिए, --distdir फ़्लैग का इस्तेमाल करें. आपको हर नए 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

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

build --distdir=path/to/directory

बिल्ड कॉन्फ़िगरेशन और क्रॉस-कंपाइलेशन

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

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

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

टारगेट कॉन्फ़िगरेशन से, exec कॉन्फ़िगरेशन इस तरह बनाया जाता है:

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

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

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

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

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

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

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

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

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

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

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

नियमित तौर पर वीडियो बनाते रहें और लगातार बढ़ाएं

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

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

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

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

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

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

सैंडबॉक्स में चलाने की सुविधा

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

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

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 फ़ाइलों को पढ़ता है, ताकि यह तय किया जा सके कि क्या करना है. यह डिज़ाइन के हिसाब से बनाया गया है. साथ ही, इसकी वजह से Basel का query निर्देश, विश्लेषण टूल के लिए एक अच्छा आधार है. इसे लोड होने के चरण के ऊपर लागू किया जाता है.

लागू करने का फ़ेज़

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