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

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

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

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

Basel का इस्तेमाल करने के लिए, अपने बुनियादी फ़ाइल फ़ोल्डर की डायरेक्ट्री पर जाएं या इसकी किसी भी सबडायरेक्ट्री और टाइप bazel को शामिल करें. बिल्ड देखें अगर नया फ़ाइल फ़ोल्डर बनाना होगा.

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

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

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

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

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

Baज़ल, लक्ष्यों को तय करने के कई तरीके देते हैं. सामूहिक रूप से, इन्हें टारगेट पैटर्न कहा जाता है. इस सिंटैक्स का इस्तेमाल 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 हो).

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

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 टूल और NDK रिपॉज़िटरी के नियमों में किए गए बदलाव, --fetch की वैल्यू के बावजूद हमेशा लागू होंगे.

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

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

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

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

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

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

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

bazel fetch //...

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

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

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

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

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

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

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

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

एयरगैप वाले एनवायरमेंट में Bazel को चलाना

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

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

डिस्ट्रिब्यूशन डायरेक्ट्री तैयार करने के लिए, --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

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

build --distdir=path/to/directory

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

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

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

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

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

  • अनुरोध टारगेट के लिए इस्तेमाल किया गया प्लैटफ़ॉर्म, टारगेट कॉन्फ़िगरेशन के लिए टारगेट प्लैटफ़ॉर्म बन जाता है.
  • अनुरोध कॉन्फ़िगरेशन में बताए गए 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_* विकल्प देखें).
  • अन्य सभी वैल्यू अपनी डिफ़ॉल्ट वैल्यू पर सेट रहती हैं.

सही इंक्रीमेंटल रीबिल्ड

बेज़ल प्रोजेक्ट का एक मुख्य लक्ष्य यह पक्का करना है कि सही तरीके से बढ़ोतरी हो कारोबार में बढ़ोतरी होती है. पहले से बनाए गए बिल्ड टूल, खास तौर पर वे टूल जो बना रहे हैं. हमारे प्लैटफ़ॉर्म पर पहले से इंक्रीमेंटल बिल्ड को लागू करने में गलत धारणाओं के बारे में बताता है.

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

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

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

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

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

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

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

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

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

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

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

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

सैंडबॉक्स किया गया एक्ज़ीक्यूशन

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

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

Google Kubernetes जैसे कुछ प्लैटफ़ॉर्म पर इंजन क्लस्टर नोड या Debian, सुरक्षा की वजह से, उपयोगकर्ता नेमस्पेस को डिफ़ॉल्ट रूप से बंद कर दिया जाता है समस्याएं हल करें. इसकी जांच करने के लिए, /proc/sys/kernel/unprivileged_userns_clone फ़ाइल देखें: अगर यह मौजूद है और इसमें 0 है, तो sudo sysctl kernel.unprivileged_userns_clone=1 की मदद से उपयोगकर्ता नेमस्पेस चालू किए जा सकते हैं.

कुछ मामलों में, सिस्टम की वजह से Baज़ल सैंडबॉक्स, नियमों को लागू नहीं कर पाता सेटअप. आम तौर पर, लक्षण की वजह से ऐसा मैसेज नहीं दिखता है जो namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory. ऐसे मामले में, जेन रूल के लिए सैंडबॉक्स को बंद करने की कोशिश करें --strategy=Genrule=standalone और इसके साथ अन्य नियमों के लिए --spawn_strategy=standalone. साथ ही, कृपया इस गड़बड़ी की शिकायत करें समस्या को ट्रैक करने वाला टूल सेट करें और बताएं कि आपका कौनसा Linux डिस्ट्रिब्यूशन इस्तेमाल किया जा रहा है. इससे हम जांच करें और आने वाली रिलीज़ में समाधान उपलब्ध कराएं.

बिल्ड के चरण

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

लोडिंग का चरण

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

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

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

विश्लेषण का फ़ेज़

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

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

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

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

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

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