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

इस पेज पर, आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम और उन्हें बनाने के पीछे की वजह बताई गई है. 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's की डिपेंडेंसी :mylib पर है. इसके अलावा, यह एक ही सोर्स के क्रम में मौजूद किसी दूसरे पैकेज में भी हो सकती है . जैसे, mylib's की डिपेंडेंसी //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 फ़ाइल डाउनलोड करती है.

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

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

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

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

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