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

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

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

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