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

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

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

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

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

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

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

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

सहायता पाना

  • bazel help command: command के लिए प्रिंट करने से जुड़ी मदद और विकल्प.
  • bazel helpstartup_options: Bazel को होस्ट करने वाले 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 उनकी सही होने की जांच करता है और बिल्ड ऐक्शन बनाता है. आखिर में, Bazel, बाइल्ड के कंपाइलर और अन्य टूल इस्तेमाल करता है.

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

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

कई लक्ष्य बनाना

Baज़ल, लक्ष्यों को तय करने के कई तरीके देते हैं. इन्हें एक साथ, टारगेट पैटर्न कहा जाता है. इस सिंटैक्स का इस्तेमाल इन कमांड में किया जाता है build, test या query.

लेबल का इस्तेमाल, अलग-अलग टारगेट तय करने के लिए किया जाता है. जैसे, BUILD फ़ाइलों में डिपेंडेंसी का एलान करने के लिए. वहीं, Bazel के टारगेट पैटर्न से कई टारगेट तय किए जाते हैं. टारगेट पैटर्न, वाइल्डकार्ड का इस्तेमाल करके टारगेट के सेट के लिए लेबल सिंटैक्स का सामान्यीकरण है. सबसे आसान मामले में, कोई भी मान्य लेबल एक मान्य टारगेट पैटर्न भी है. इससे ठीक वैसे ही के सेट की पहचान होती है टारगेट.

// से शुरू होने वाले सभी टारगेट पैटर्न को मौजूदा पैटर्न के आधार पर हल किया जाता है name@yourcompany.com जैसा कोई प्रोफ़ेशनल ईमेल पता बनाएं. इससे आपका कारोबार ज़्यादा भरोसेमंद बनेगा.

//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 टॉप-लेवल पैकेज में सभी टारगेट, अगर मूल फ़ाइल फ़ोल्डर है.

// से शुरू न होने वाले टारगेट पैटर्न, मौजूदा वर्किंग डायरेक्ट्री के हिसाब से हल किए जाते हैं. इन उदाहरणों में, foo की वर्किंग डायरेक्ट्री का इस्तेमाल किया गया है:

:foo //foo:foo की तरह काम करता है.
bar:wiz //foo/bar:wiz के बराबर.
bar/wiz इसके बराबर:
  • //foo/bar/wiz: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 के बराबर.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

bazel fetch //...

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

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

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

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

डिस्ट्रिब्यूशन फ़ाइल डायरेक्ट्री

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

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

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

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

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

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

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

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

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) और एक या उससे ज़्यादा exec टूल, जैसे कि कुछ बेस लाइब्रेरी. ऐसी लाइब्रेरी दो बार बनाई जानी चाहिए, एक बार exec के लिए एक बार इस्तेमाल किया जा सकता है. 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 पर आधारित सिस्टम, फ़ाइल को फिर से नहीं बनाएंगे.

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

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

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

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

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

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

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

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

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

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

अगर आपको कभी Babel के साथ स्थिर और असंगत स्थिति का पता चलता है, तो कृपया एक बग की रिपोर्ट करें.

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

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

अगर चेतावनी देने के लिए, आपके सिस्टम पर सैंडबॉक्सिंग की सुविधा काम नहीं करती, तो Bagel एक चेतावनी प्रिंट करेगा आपको इस बात की गारंटी नहीं है कि बिल्ड हर्मेटिक होगी और होस्ट सिस्टम को अज्ञात तरीकों से करता है. इस चेतावनी को बंद करने के लिए, 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 फ़ाइलें लोड की जाती हैं, पार्स की जाती हैं, उनका आकलन किया जाता है, और उन्हें कैश मेमोरी में सेव किया जाता है.

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

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

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

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

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

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

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

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

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