इस पेज पर Windows के साथ काम करने वाले नियम, पोर्टेबल नियमों को लिखने में होने वाली आम समस्याओं और कुछ समाधानों के बारे में बताया गया है.
पथ
समस्याएं:
लंबाई की सीमा: पाथ की ज़्यादा से ज़्यादा लंबाई 259 वर्ण की होनी चाहिए.
हालांकि, Windows पर लंबे पाथ (ज़्यादा से ज़्यादा 32,767 वर्ण) भी इस्तेमाल किए जा सकते हैं, लेकिन कई प्रोग्राम निचली सीमा वाले होते हैं.
कार्रवाइयों में चलाए जाने वाले प्रोग्राम के बारे में ध्यान रखें.
काम करने वाली निर्देशिका: 259 वर्णों तक भी सीमित है.
प्रोसेस, 259 वर्णों से ज़्यादा वाली डायरेक्ट्री में
cd
नहीं हो सकतीं.केस-सेंसिटिव (बड़े और छोटे अक्षरों में अंतर): Windows पाथ केस-इनसेंसिटिव होते हैं. यूनिक्स पाथ केस-सेंसिटिव होते हैं.
कार्रवाइयों के लिए कमांड लाइन बनाते समय इस बात का ध्यान रखें.
पाथ सेपरेटर: बैकस्लैश (
\`), not forward slash (
/` हैं).Bazel ने
/
विभाजक के साथ Unix शैली के पाथ स्टोर किए हैं. कुछ Windows प्रोग्राम, यूनिक्स-स्टाइल के पाथ पर काम करते हैं, जबकि बाकी प्रोग्राम में नहीं होते. cmd.exe के कुछ बिल्ट-इन निर्देश उनका समर्थन करते हैं, कुछ नहीं.कार्रवाइयों के लिए कमांड लाइन और एनवायरमेंट वैरिएबल बनाते समय, हमेशा
\` separators on Windows: replace
/with
का इस्तेमाल करना सबसे अच्छा होता है.निरपेक्ष पाथ: स्लैश (
/
) से शुरू न करें.Windows पर निरपेक्ष पाथ एक डिस्क अक्षर से शुरू होते हैं, जैसे कि
C:\foo\bar.txt
. कोई एक फ़ाइल सिस्टम रूट नहीं है.अगर आपका नियम यह जांच करता है कि कोई पाथ सटीक है या नहीं, तो इस बात का ध्यान रखें. एब्सोल्यूट पाथ से बचना चाहिए, क्योंकि वे अक्सर पोर्टेबल नहीं होते.
समाधान:
पाथों को छोटा रखें.
लंबे डायरेक्ट्री नामों, लंबी फ़ाइल के नामों, लंबे फ़ाइल नामों, फ़ाइल फ़ोल्डर के लंबे नामों, लंबे टारगेट नामों के इस्तेमाल से बचें.
ये सभी, ऐक्शन की इनपुट फ़ाइलों के पाथ कॉम्पोनेंट बन सकते हैं और पाथ की लंबाई की सीमा को खत्म कर सकते हैं.
छोटे आउटपुट रूट का इस्तेमाल करें.
Bazel आउटपुट के लिए एक छोटा पाथ तय करने के लिए,
--output_user_root=<path>
फ़्लैग का इस्तेमाल करें. सिर्फ़ Bazel आउटपुट के लिए, एक ड्राइव (या वर्चुअल ड्राइव) होना चाहिए (जैसे किD:\`), and adding this line to your
.bazelrc` फ़ाइल):build --output_user_root=D:/
या
build --output_user_root=C:/_bzl
जंक्शन का इस्तेमाल करना.
जंक्शन, सामान्य भाषा में बोल रहे हैं[1], डायरेक्ट्री सिमलिंक. जंक्शन बनाना आसान है और वे लंबे पाथ के लिए, डायरेक्ट्री (उसी कंप्यूटर पर) की ओर इशारा कर सकते हैं. अगर बिल्ड ऐक्शन में ऐसा जंक्शन होता है जिसका पाथ छोटा होता है और उसका टारगेट बड़ा होता है, तो छोटे पाथ की सीमा वाले टूल, जंक्शन की डायरेक्ट्री में मौजूद फ़ाइलों को ऐक्सेस कर सकते हैं.
.bat
फ़ाइलों में या cmd.exe में, आप इस तरह के जंक्शन बना सकते हैं:mklink /J c:\path\to\junction c:\path\to\very\long\target\path
[1]: पूरी तरह से बोलने पर जंक्शन, सिंबल लिंक नहीं होते. हालांकि, बिल्ड ऐक्शन के लिए, जंक्शन को डायरेक्ट्री सिमलिंक माना जा सकता है.
/
को, कार्रवाइयों / envvars के पाथ में `` से बदलें.किसी कार्रवाई के लिए कमांड लाइन या एनवायरमेंट वैरिएबल बनाते समय, पाथ को Windows स्टाइल में बनाएं. उदाहरणः
def as_path(p, is_windows): if is_windows: return p.replace("/", "\\") else: return p
एनवायरमेंट वैरिएबल
समस्याएं:
केस-सेंसिटिव (बड़े और छोटे अक्षरों में अंतर): Windows एनवायरमेंट के वैरिएबल के नाम केस-इनसेंसिटिव होते हैं.
जैसे, Java
System.getenv("SystemRoot")
औरSystem.getenv("SYSTEMROOT")
में, एक ही नतीजा मिलता है. (यह अन्य भाषाओं पर भी लागू होता है.)उपयोगिता: कार्रवाइयों में कम से कम कस्टम परिवेश वैरिएबल का इस्तेमाल करना चाहिए.
एनवायरमेंट वैरिएबल, कार्रवाई की कैश कुंजी का हिस्सा होते हैं. अगर किसी कार्रवाई में ऐसे एनवायरमेंट वैरिएबल का इस्तेमाल किया जाता है जो अक्सर बदलता रहता है या उपयोगकर्ताओं के लिए कस्टम होता है, तो इस नियम से कैश मेमोरी में सेव होने की संभावना कम हो जाती है.
समाधान:
सिर्फ़ अपर-केस एनवायरमेंट के वैरिएबल नामों का इस्तेमाल करें.
यह Windows, macOS, और Linux पर काम करता है.
ऐक्शन एनवायरमेंट को कम से कम करें.
ctx.actions.run
का इस्तेमाल करते समय, एनवायरमेंट कोctx.configuration.default_shell_env
पर सेट करें. अगर कार्रवाई के लिए ज़्यादा एनवायरमेंट वैरिएबल चाहिए, तो उन सभी को शब्दकोश में रखें और कार्रवाई में पास करें. उदाहरणःload("@bazel_skylib//lib:dicts.bzl", "dicts") def _make_env(ctx, output_file, is_windows): out_path = output_file.path if is_windows: out_path = out_path.replace("/", "\\") return dicts.add(ctx.configuration.default_shell_env, {"MY_OUTPUT": out_path})
कार्रवाइयां
समस्याएं:
एक्ज़ीक्यूटेबल आउटपुट: एक्ज़ीक्यूटेबल फ़ाइल में एक्ज़ीक्यूटेबल एक्सटेंशन होना ज़रूरी है.
सबसे सामान्य एक्सटेंशन
.exe
(बाइनरी फ़ाइलें) और.bat
(बैच स्क्रिप्ट) हैं.ध्यान रखें कि शेल स्क्रिप्ट (
.sh
) Windows पर एक्ज़ीक्यूटेबल नहीं हो सकती; आप उन्हेंctx.actions.run
केexecutable
के रूप में तय नहीं कर सकते.+x
की कोई अनुमति नहीं है, इसलिए आप Linux जैसी आर्बिट्रेरी फ़ाइलें एक्ज़ीक्यूट नहीं कर सकते.Bash कमांड: पोर्टेबिलिटी के लिए, Bash कमांड को सीधे कार्रवाइयों में शामिल करने से बचें.
बैश, यूनिक्स जैसे सिस्टम पर बहुत बड़ा है, लेकिन यह Windows पर अक्सर उपलब्ध नहीं होता है. Bazel पर, Bash (MSYS2) के इस्तेमाल पर कम और कम निर्भर रहेगा. इसलिए, आने वाले समय में उपयोगकर्ताओं को Bazel का इस्तेमाल करके, MSYS2 इंस्टॉल करने की संभावना कम पड़ेगी. Windows पर नियमों को आसानी से इस्तेमाल करने के लिए, कार्रवाइयों में Bash निर्देशों का इस्तेमाल करने से बचें.
लाइन के आखिरी हिस्से: Windows, CRLF (
\r\n
) का इस्तेमाल करता है, Unix जैसे सिस्टम LF (\n
) का इस्तेमाल करते हैं.टेक्स्ट फ़ाइलों की तुलना करते समय इस बात का ध्यान रखें. अपनी Git Settings के बारे में सावधान रहें. खास तौर पर, चेक आउट करते समय या तय करते समय लाइन के आखिरी हिस्से का ध्यान रखें. (GitHub की
core.autocrlf
सेटिंग देखें.)
समाधान:
बिना हैश किए हुए, बनाए गए नियम का इस्तेमाल करें.
Bash कमांड के लिए
native.genrule()
एक रैपर है. आम तौर पर, इसका इस्तेमाल फ़ाइल को कॉपी करने या टेक्स्ट फ़ाइल लिखने जैसी सामान्य समस्याओं को हल करने के लिए किया जाता है. आप बैश पर भरोसा करने से बच सकते हैं (और व्हील में किए गए बदलाव को नया रूप देकर): यह देख सकते हैं कि क्या bazel-skylib ने आपकी ज़रूरतों के हिसाब से कोई नियम बनाया है. इनमें से कोई भी Windows पर बनाते/जांच करते समय Bash पर निर्भर करता है.नियम बनाने के उदाहरण:
copy_file()
(स्रोत, दस्तावेज़): फ़ाइल को कहीं और कॉपी करता है, वैकल्पिक रूप से उसे एक्ज़ीक्यूटेबल बनाता हैwrite_file()
(स्रोत, दस्तावेज़): इसकी मदद से, टेक्स्ट फ़ाइल को अपनी पसंद के मुताबिक, जिसके आखिर में लाइन (auto
,unix
याwindows
) लिखा जाता है (अगर यह स्क्रिप्ट के तौर पर उपलब्ध हो, तो उसे एक्ज़ीक्यूट किया जा सकता है)run_binary()
(स्रोत, दस्तावेज़): बिल्ड ऐक्शन के तौर पर, दिए गए इनपुट और अनुमानित आउटपुट के साथ बाइनरी (या*_binary
नियम) चलाता है (यहctx.actions.run
के लिए बिल्ड नियम का रैपर है)native_binary()
(स्रोत, दस्तावेज़): यह*_binary
नियम में नेटिव बाइनरी को रैप करता है, जिसे आपbazel run
याrun_binary()
केtool
एट्रिब्यूट याnative.genrule()
केtools
एट्रिब्यूट में इस्तेमाल कर सकते हैं
टेस्ट के नियम के उदाहरण:
Windows पर, ग़ैर-ज़रूरी चीज़ों के लिए
.bat
स्क्रिप्ट का इस्तेमाल करें..sh
स्क्रिप्ट के बजाय, आप.bat
स्क्रिप्ट के छोटे से टास्क हल कर सकते हैं.उदाहरण के लिए, अगर आपको ऐसी स्क्रिप्ट की ज़रूरत है जो कुछ नहीं करती या मैसेज प्रिंट करती है या तय गड़बड़ी कोड के साथ बाहर आती है, तो एक सामान्य
.bat
फ़ाइल ही काफ़ी होगी. अगर आपका नियमDefaultInfo()
की सेवा देने वाली कंपनी को दिखाता है, तोexecutable
फ़ील्ड, Windows पर उस.bat
फ़ाइल का रेफ़रंस दे सकता है.साथ ही, macOS और Linux पर फ़ाइल एक्सटेंशन की कोई अहमियत नहीं होती. इसलिए, शेल स्क्रिप्ट के लिए भी, एक्सटेंशन के तौर पर
.bat
का इस्तेमाल किया जा सकता है.ध्यान रखें कि
.bat
की खाली फ़ाइलें एक्ज़ीक्यूट नहीं की जा सकतीं. अगर आपको किसी खाली स्क्रिप्ट की ज़रूरत है, तो उसमें एक स्पेस लिखें.Bash का इस्तेमाल खास तौर पर करें.
Starlark बिल्ड और टेस्ट नियमों में, Bash स्क्रिप्ट और Bash कमांड कमांड के तौर पर चलाने के लिए,
ctx.actions.run_shell
का इस्तेमाल करें.Starlark मैक्रो में, Bash स्क्रिप्ट और कमांड को
native.sh_binary()
याnative.genrule()
में रैप करें. बैज़ेल यह जांच करेगा कि क्या Bash उपलब्ध है और Bash की मदद से स्क्रिप्ट या निर्देश चलाएं.Starlark रिपॉज़िटरी के नियमों में, Bash को पूरी तरह इस्तेमाल करने से बचें. फ़िलहाल, बेज़ेल डेटा स्टोर करने की जगह के नियमों में सिद्धांत के हिसाब से Bash कमांड चलाने का कोई तरीका नहीं बताता है.
फ़ाइलें मिटाना
समस्याएं:
खुला रहने पर फ़ाइलें हटाई नहीं जा सकतीं.
खुली हुई फ़ाइलों को मिटाया नहीं जा सकता (डिफ़ॉल्ट रूप से, कोशिश करने के दौरान "ऐक्सेस अस्वीकार किया गया" गड़बड़ियां दिखती हैं. अगर आप किसी फ़ाइल को नहीं मिटा पा रहे हैं, तो हो सकता है कि चल रही प्रोसेस को अब भी खोला जाए.
चल रही प्रक्रिया की वर्क डायरेक्ट्री को मिटाया नहीं जा सकता.
प्रोसेस का काम करने वाले डायरेक्ट्री पर खुला हैंडल होता है. इस प्रोसेस के खत्म होने तक डायरेक्ट्री को मिटाया नहीं जा सकता.
समाधान:
अपने कोड में, फ़ाइलों को तुरंत बंद करने की कोशिश करें.
Java में,
try-with-resources
का इस्तेमाल करें. Python में,with open(...) as f:
का इस्तेमाल करें. सिद्धांत के तौर पर, जल्द से जल्द हैंडल बंद करें.