आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम

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

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

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

फ़ंक्शनल पर्सपेक्टिव

आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम और फ़ंक्शनल प्रोग्रामिंग के बीच आसानी से तुलना की जा सकती है. Java, C, और Python जैसी प्रोग्रामिंग की पारंपरिक भाषाओं में, एक के बाद एक निर्देशों की सूचियां दी जाती हैं. ठीक उसी तरह जैसे टास्क पर आधारित बिल्ड सिस्टम, प्रोग्रामर को निर्देशों को एक के बाद एक लागू करने की सुविधा देते हैं. इसके उलट, फ़ंक्शनल प्रोग्रामिंग लैंग्वेज (जैसे, Haskell और ML) का स्ट्रक्चर, गणितीय समीकरणों की सीरीज़ की तरह होता है. फ़ंक्शनल लैंग्वेज में, प्रोग्रामर कैलकुलेशन करने का तरीका बताता है. हालांकि, वह यह नहीं बताता कि कैलकुलेशन कब और कैसे किया जाएगा. यह जानकारी कंपाइलर को देनी होती है.

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

आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम को समझना

Google का बिल्ड सिस्टम, Blaze, आर्टफ़ैक्ट पर आधारित पहला बिल्ड सिस्टम था. Bazel, Blaze का ओपन-सोर्स वर्शन है.

Bazel में, बिल्डफ़ाइल (आम तौर पर इसका नाम BUILD होता है) इस तरह दिखती है:

java_binary(
    name = "MyBinary",
    srcs = ["MyBinary.java"],
    deps = [
        ":mylib",
    ],
)
java_library(
    name = "mylib",
    srcs = ["MyLibrary.java", "MyHelper.java"],
    visibility = ["//java/com/example/myproduct:__subpackages__"],
    deps = [
        "//java/com/example/common",
        "//java/com/example/myproduct/otherlib",
    ],
)

Bazel में, BUILD फ़ाइलें टारगेट तय करती हैं—यहां दो तरह के टारगेट होते हैं—java_binary और java_library. हर टारगेट, सिस्टम से बनाए गए आर्टफ़ैक्ट से जुड़ा होता है: बाइनरी टारगेट, ऐसी बाइनरी बनाते हैं जिन्हें सीधे तौर पर चलाया जा सकता है. वहीं, लाइब्रेरी टारगेट, ऐसी लाइब्रेरी बनाते हैं जिनका इस्तेमाल बाइनरी या अन्य लाइब्रेरी कर सकती हैं. हर टारगेट में ये चीज़ें होती हैं:

  • name: कमांड लाइन और अन्य टारगेट पर टारगेट का रेफ़रंस कैसे दिया जाता है
  • srcs: टारगेट के लिए आर्टफ़ैक्ट बनाने के लिए, कंपाइल की जाने वाली सोर्स फ़ाइलें
  • deps: ऐसे अन्य टारगेट जिन्हें इस टारगेट से पहले बनाया जाना चाहिए और उससे लिंक किया जाना चाहिए

डिपेंडेंसी, एक ही पैकेज में हो सकती हैं (जैसे, MyBinary की :mylib पर डिपेंडेंसी) या एक ही सोर्स हैरारकी में किसी दूसरे पैकेज पर हो सकती हैं (जैसे, mylib की //java/com/example/common पर डिपेंडेंसी).

टास्क पर आधारित बिल्ड सिस्टम की तरह ही, Bazel के कमांड-लाइन टूल का इस्तेमाल करके बिल्ड किए जाते हैं. MyBinary टारगेट बनाने के लिए, bazel build :MyBinary चलाएं. किसी क्लीन रिपॉज़िटरी में पहली बार यह कमांड डालने के बाद, Bazel:

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

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

हालांकि, इसके फ़ायदे पैरलल प्रोसेसिंग से भी ज़्यादा हैं. इस तरीके से हमें एक और फ़ायदा मिलता है. यह तब पता चलता है, जब डेवलपर कोई बदलाव किए बिना bazel build :MyBinary को दूसरी बार टाइप करता है: Bazel एक सेकंड से भी कम समय में बंद हो जाता है और यह मैसेज दिखाता है कि टारगेट अप-टू-डेट है. ऐसा, फ़ंक्शनल प्रोग्रामिंग पैराडाइम की वजह से होता है. हमने इस बारे में पहले बात की थी—Bazel को पता है कि हर टारगेट, सिर्फ़ Java कंपाइलर को चलाने का नतीजा है. साथ ही, यह भी पता है कि Java कंपाइलर का आउटपुट सिर्फ़ उसके इनपुट पर निर्भर करता है. इसलिए, जब तक इनपुट में बदलाव नहीं होता, तब तक आउटपुट का फिर से इस्तेमाल किया जा सकता है. यह विश्लेषण हर लेवल पर काम करता है. अगर MyBinary.java में बदलाव होता है, तो Bazel को MyBinary को फिर से बनाना होगा, लेकिन mylib का फिर से इस्तेमाल करना होगा. अगर //java/com/example/common के लिए कोई सोर्स फ़ाइल बदलती है, तो Bazel उस लाइब्रेरी, mylib, और MyBinary को फिर से बनाता है. हालांकि, वह //java/com/example/myproduct/otherlib का फिर से इस्तेमाल करता है. Bazel हर चरण में इस्तेमाल होने वाले टूल की प्रॉपर्टी के बारे में जानता है. इसलिए, वह हर बार आर्टफ़ैक्ट का सिर्फ़ कम से कम सेट फिर से बना पाता है. साथ ही, यह भी पक्का करता है कि पुराने बिल्ड न बनें.

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

Bazel की अन्य आसान सुविधाएं

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

डिपेंडेंसी के तौर पर टूल

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

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

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

  • होस्ट कॉन्फ़िगरेशन: बिल्ड के दौरान चलने वाले बिल्डिंग टूल
  • टारगेट कॉन्फ़िगरेशन: वह बाइनरी बनाना जिसका आपने अनुरोध किया था

बिल्ड सिस्टम को बेहतर बनाना

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

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

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

एनवायरमेंट को अलग करना

ऐसा लगता है कि कार्रवाइयों में, दूसरे सिस्टम में टास्क से जुड़ी समस्याएं आ सकती हैं—क्या अब भी ऐसी कार्रवाइयां लिखी जा सकती हैं जो एक ही फ़ाइल में लिखती हैं और एक-दूसरे से मेल नहीं खाती हैं? असल में, Bazel सैंडबॉक्सिंग का इस्तेमाल करके, इन संघर्षों को रोकता है. जिन सिस्टम पर यह सुविधा काम करती है उन पर फ़ाइल सिस्टम सैंडबॉक्स की मदद से, हर कार्रवाई को एक-दूसरे से अलग रखा जाता है. असल में, हर कार्रवाई फ़ाइल सिस्टम का सिर्फ़ सीमित व्यू देख सकती है. इसमें, ऐसे इनपुट शामिल होते हैं जिन्हें उसने एलान किया है और ऐसे आउटपुट जो उसने जनरेट किए हैं. इसे Linux पर LXC जैसे सिस्टम लागू करते हैं. यह वही टेक्नोलॉजी है जिस पर Docker काम करता है. इसका मतलब है कि कार्रवाइयां एक-दूसरे के साथ कभी भी संघर्ष नहीं कर सकतीं, क्योंकि वे ऐसी किसी भी फ़ाइल को नहीं पढ़ सकतीं जिसका एलान न किया गया हो. साथ ही, ऐसी किसी भी फ़ाइल को लिखने के बाद, कार्रवाई पूरी होने पर उसे हटा दिया जाएगा जिसका एलान न किया गया हो. Bazel, सैंडबॉक्स का इस्तेमाल करके भी कार्रवाई को नेटवर्क के ज़रिए कम्यूनिकेट करने से रोकता है.

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

हालांकि, अब भी एक समस्या बाकी है: अक्सर, बिल्ड सिस्टम को डिपेंडेंसी (चाहे वे टूल हों या लाइब्रेरी) को सीधे तौर पर बनाने के बजाय, बाहरी सोर्स से डाउनलोड करना पड़ता है. उदाहरण में, @com_google_common_guava_guava//jar डिपेंडेंसी के ज़रिए इसे देखा जा सकता है. यह डिपेंडेंसी, Maven से JAR फ़ाइल डाउनलोड करती है.

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

मूल समस्या यह है कि हम चाहते हैं कि सोर्स कंट्रोल में इन फ़ाइलों को शामिल किए बिना, बिल्ड सिस्टम को इन फ़ाइलों के बारे में पता हो. किसी डिपेंडेंसी को अपडेट करने का फ़ैसला सोच-समझकर लिया जाना चाहिए. हालांकि, यह फ़ैसला किसी एक इंजीनियर या सिस्टम के अपने-आप मैनेज होने के बजाय, एक ही जगह पर एक बार लिया जाना चाहिए. इसकी वजह यह है कि “Live at Head” मॉडल के साथ भी, हम चाहते हैं कि बिल्ड डिटरमिनिस्टिक हों. इसका मतलब है कि अगर पिछले हफ़्ते के किसी कमिट को चेक किया जाता है, तो आपको अपनी डिपेंडेंसी अब की तरह नहीं, बल्कि उस समय की तरह दिखनी चाहिए.

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

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

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