रिमोट एक्ज़ीक्यूशन के लिए, Bazel के नियमों को अपनाना

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

रिमोट एक्ज़ीक्यूशन की मदद से Bazel, किसी अलग प्लैटफ़ॉर्म पर कार्रवाइयां कर सकता है. जैसे, डेटा सेंटर. Bazel, रिमोट एक्ज़ीक्यूशन के लिए gRPC प्रोटोकॉल का इस्तेमाल करता है. रिमोट एक्ज़ीक्यूशन को bazel-buildfarm के साथ आज़माया जा सकता है. यह एक ओपन-सोर्स प्रोजेक्ट है. इसका मकसद, डिस्ट्रिब्यूटेड रिमोट एक्ज़ीक्यूशन प्लैटफ़ॉर्म उपलब्ध कराना है.

इस पेज पर, अलग-अलग एनवायरमेंट टाइप या प्लैटफ़ॉर्म के बारे में बताते समय, इन शब्दों का इस्तेमाल किया गया है:

  • होस्ट प्लैटफ़ॉर्म - जहां Bazel चलता है.
  • एक्ज़ीक्यूशन प्लैटफ़ॉर्म - जहां Bazel की कार्रवाइयां चलती हैं.
  • टारगेट प्लैटफ़ॉर्म - जहां बिल्ड आउटपुट (और कुछ कार्रवाइयां) चलती हैं.

खास जानकारी

रिमोट एक्ज़ीक्यूशन के लिए Bazel बिल्ड को कॉन्फ़िगर करते समय, आपको इस पेज पर बताई गई गाइडलाइन का पालन करना होगा. इससे यह पक्का किया जा सकेगा कि बिल्ड, बिना किसी गड़बड़ी के रिमोट तरीके से एक्ज़ीक्यूट हो. ऐसा रिमोट एक्ज़ीक्यूशन की वजह से होता है. जैसे:

  • बिल्ड की कार्रवाइयों को अलग करना. बिल्ड टूल, स्थिति और डिपेंडेंसी को बनाए नहीं रखते हैं. साथ ही, डिपेंडेंसी एक-दूसरे के बीच लीक नहीं हो सकती हैं.

  • अलग-अलग एक्ज़ीक्यूशन एनवायरमेंट. लोकल बिल्ड कॉन्फ़िगरेशन, रिमोट एक्ज़ीक्यूशन एनवायरमेंट के लिए हमेशा सही नहीं होता.

इस पेज पर, रिमोट एक्ज़ीक्यूशन के लिए कस्टम Bazel बिल्ड और टेस्ट के नियम लागू करते समय आने वाली समस्याओं के बारे में बताया गया है. साथ ही, इनसे बचने का तरीका भी बताया गया है. इसमें इन विषयों के बारे में बताया गया है:

टूलचेन के नियमों के ज़रिए बिल्ड टूल को लागू करना

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

फ़िलहाल, टूलचेन के नियम, Bazel के बिल्ड और टेस्ट के नियमों के लिए उपलब्ध हैं. ये नियम Scala, Rust, और Go के लिए उपलब्ध हैं. साथ ही, अन्य भाषाओं और टूल के लिए नए टूलचेन के नियम बनाए जा रहे हैं. जैसे, bash. अगर आपके नियम में इस्तेमाल किए गए टूल के लिए कोई टूलचेन नियम मौजूद नहीं है, तो टूलचेन नियम बनाएं.

इंप्लिसिट डिपेंडेंसी मैनेज करना

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

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

डिपेंडेंसी से जुड़ी इन समस्याओं का पता लगाने और उन्हें ठीक करने के लिए, Bazel 0.14.1 में लोकल Docker सैंडबॉक्स की सुविधा उपलब्ध है. इसमें डिपेंडेंसी के लिए वही पाबंदियां लागू होती हैं जो रिमोट एक्ज़ीक्यूशन के लिए लागू होती हैं. सैंडबॉक्स का इस्तेमाल करके, रिमोट एक्ज़ीक्यूशन के लिए अपनी बिल्ड तैयार करें. इसके लिए, डिपेंडेंसी से जुड़ी बिल्ड की गड़बड़ियों का पता लगाएं और उन्हें ठीक करें. ज़्यादा जानकारी के लिए, Docker Sandbox की मदद से Bazel Remote Execution से जुड़ी समस्या हल करना लेख पढ़ें.

प्लैटफ़ॉर्म पर निर्भर बाइनरी मैनेज करना

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

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

  • टूल के सोर्स कोड को शिप करें या बाहरी तौर पर रेफ़रंस दें, ताकि इसे रिमोट एक्ज़ीक्यूशन प्लैटफ़ॉर्म के लिए बनाया जा सके.

  • अगर टूल का वर्शन स्टेबल है, तो उसे रिमोट एक्ज़ीक्यूशन एनवायरमेंट (उदाहरण के लिए, टूलचेन कंटेनर) में पहले से इंस्टॉल करें. साथ ही, टूलचेन के नियमों का इस्तेमाल करके, उसे अपने बिल्ड में चलाएं.

WORKSPACE के कॉन्फ़िगरेशन से जुड़े नियमों को मैनेज करना

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

WORKSPACE नियमों के ज़रिए की जाने वाली ये कार्रवाइयां, रिमोट एक्ज़ीक्यूशन के साथ काम नहीं करतीं:

  • बाइनरी बनाई जा रही हैं. WORKSPACE नियमों में कंपाइल करने की कार्रवाइयां करने से, ऐसे बाइनरी मिलते हैं जो रिमोट एक्ज़ीक्यूशन प्लैटफ़ॉर्म के साथ काम नहीं करते. ऐसा तब होता है, जब रिमोट एक्ज़ीक्यूशन प्लैटफ़ॉर्म, होस्ट प्लैटफ़ॉर्म से अलग होता है.

  • pip पैकेज इंस्टॉल किए जा रहे हैं. WORKSPACE नियमों के ज़रिए इंस्टॉल किए गए pip पैकेज के लिए, यह ज़रूरी है कि उनकी डिपेंडेंसी, होस्ट प्लैटफ़ॉर्म पर पहले से इंस्टॉल हों. होस्ट प्लैटफ़ॉर्म के लिए खास तौर पर बनाए गए ऐसे पैकेज, रिमोट एक्ज़ीक्यूशन प्लैटफ़ॉर्म के साथ काम नहीं करेंगे. ऐसा तब होगा, जब रिमोट एक्ज़ीक्यूशन प्लैटफ़ॉर्म, होस्ट प्लैटफ़ॉर्म से अलग होगा.

  • स्थानीय टूल या आर्टफ़ैक्ट से सिंबल लिंक करना. WORKSPACE नियमों का इस्तेमाल करके, होस्ट प्लैटफ़ॉर्म पर इंस्टॉल किए गए टूल या लाइब्रेरी के लिए बनाए गए सिंबल लिंक की वजह से, रिमोट एक्ज़ीक्यूशन प्लैटफ़ॉर्म पर बिल्ड नहीं हो पाएगा. ऐसा इसलिए होगा, क्योंकि Bazel उन्हें ढूंढ नहीं पाएगा. इसके बजाय, स्टैंडर्ड बिल्ड ऐक्शन का इस्तेमाल करके सिंबल लिंक बनाएं, ताकि सिंबल लिंक किए गए टूल और लाइब्रेरी, Bazel के runfiles ट्री से ऐक्सेस की जा सकें. बाहरी रेपो डायरेक्ट्री से बाहर की टारगेट फ़ाइलों को सिंबल के तौर पर लिंक करने के लिए, repository_ctx.symlink का इस्तेमाल न करें.

  • होस्ट प्लैटफ़ॉर्म में बदलाव करना. Bazel runfiles ट्री के बाहर फ़ाइलें बनाने, एनवायरमेंट वैरिएबल बनाने, और इसी तरह की अन्य कार्रवाइयां करने से बचें. ऐसा इसलिए, क्योंकि ये रिमोट एक्ज़ीक्यूशन प्लैटफ़ॉर्म पर उम्मीद के मुताबिक काम नहीं कर सकती हैं.

Workspace के नियमों के लॉग का इस्तेमाल करके, संभावित नॉन-हर्मेटिक व्यवहार का पता लगाया जा सकता है.

अगर कोई बाहरी डिपेंडेंसी, होस्ट प्लैटफ़ॉर्म पर निर्भर कुछ खास कार्रवाइयां करती है, तो आपको उन कार्रवाइयों को WORKSPACE और बिल्ड नियमों के बीच इस तरह से बांटना चाहिए:

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

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

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

उदाहरण के लिए, cuda और python के लिए Tensorflow के नियमों के लिए, WORKSPACE नियम यहां दिए गए BUILD files बनाते हैं. लोकल एक्ज़ीक्यूशन के लिए, होस्ट एनवायरमेंट की जांच करके बनाई गई फ़ाइलों का इस्तेमाल किया जाता है. रिमोट तरीके से लागू करने के लिए, एनवायरमेंट वैरिएबल पर शर्त वाला स्टेटमेंट, नियम को उन फ़ाइलों का इस्तेमाल करने की अनुमति देता है जिन्हें रिपॉज़िटरी में चेक किया गया है.

BUILD फ़ाइलें, genrules का एलान करती हैं. इन्हें स्थानीय और रिमोट, दोनों तरह से चलाया जा सकता है. साथ ही, ये ज़रूरी प्रोसेसिंग करती हैं. यह प्रोसेसिंग पहले repository_ctx.symlink के ज़रिए की जाती थी. इसके बारे में यहां बताया गया है.