इस पेज पर, Windows के साथ काम करने वाले नियम लिखने, पोर्टेबल नियम लिखने से जुड़ी सामान्य समस्याओं, और उनके कुछ समाधानों के बारे में बताया गया है.
पथ
समस्याएं:
पाथ की लंबाई की सीमा: पाथ की लंबाई ज़्यादा से ज़्यादा 259 वर्ण हो सकती है.
Windows में, लंबे पाथ (32,767 वर्णों तक) का भी इस्तेमाल किया जा सकता है. हालांकि, कई प्रोग्राम कम वर्ण सीमा के साथ बनाए जाते हैं.
कार्रवाइयों में चलाए जाने वाले प्रोग्राम के बारे में यह जानकारी ध्यान में रखें.
वर्किंग डायरेक्ट्री: इसमें भी 259 से ज़्यादा वर्ण इस्तेमाल नहीं किए जा सकते.
प्रोसेस, 259 वर्णों से ज़्यादा लंबी डायरेक्ट्री में
cd
नहीं हो सकतीं.केस-सेंसिटिविटी: Windows पाथ केस-इनसेंसिटिव होते हैं, जबकि Unix पाथ केस-सेंसिटिव होते हैं.
कार्रवाइयों के लिए कमांड लाइन बनाते समय, इस बात का ध्यान रखें.
पाथ सेपरेटर: बैकस्लैश (
\`), not forward slash (
/`) होते हैं.Bazel, Unix-स्टाइल में पाथ सेव करता है. इसके लिए,
/
सेपरेटर का इस्तेमाल किया जाता है. हालांकि, कुछ Windows प्रोग्राम Unix-स्टाइल वाले पाथ के साथ काम करते हैं, लेकिन अन्य प्रोग्राम ऐसा नहीं करते. 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")
से एक ही नतीजा मिलता है. (यह अन्य भाषाओं पर भी लागू होता है.)Hermeticity: कार्रवाइयों में, कस्टम एनवायरमेंट वैरिएबल का कम से कम इस्तेमाल किया जाना चाहिए.
एनवायरमेंट वैरिएबल, कार्रवाई की कैश मेमोरी की कुंजी का हिस्सा होते हैं. अगर किसी कार्रवाई में ऐसे एनवायरमेंट वैरिएबल का इस्तेमाल किया जाता है जिनमें अक्सर बदलाव होता है या जो उपयोगकर्ताओं के हिसाब से कस्टम होते हैं, तो इससे नियम को कम समय के लिए कैश मेमोरी में सेव किया जा सकता है.
समाधान:
सिर्फ़ बड़े अक्षरों वाले एनवायरमेंट वैरिएबल के नामों का इस्तेमाल करें.
यह सुविधा 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 कमांड चलाने से बचें.
Bash, Unix जैसे सिस्टम पर काफ़ी इस्तेमाल किया जाता है. हालांकि, यह अक्सर Windows पर उपलब्ध नहीं होता. Bazel, Bash (MSYS2) पर कम से कम निर्भर है. इसलिए, आने वाले समय में उपयोगकर्ताओं को Bazel के साथ MSYS2 इंस्टॉल करने की ज़रूरत नहीं होगी. Windows पर नियमों का आसानी से इस्तेमाल करने के लिए, कार्रवाइयों में Bash कमांड न चलाएं.
लाइन खत्म होने के निशान: Windows में CRLF (
\r\n
) का इस्तेमाल किया जाता है. वहीं, Unix जैसे सिस्टम में LF (\n
) का इस्तेमाल किया जाता है.टेक्स्ट फ़ाइलों की तुलना करते समय, इस बात का ध्यान रखें. Git की सेटिंग का ध्यान रखें. खास तौर पर, चेक आउट या कमिट करते समय लाइन के आखिर में मौजूद वर्णों का ध्यान रखें. (Git की
core.autocrlf
सेटिंग देखें.)
समाधान:
खास तौर पर बनाए गए, बिना बैश वाले नियम का इस्तेमाल करें.
native.genrule()
, बैश कमांड के लिए एक रैपर है. इसका इस्तेमाल अक्सर फ़ाइल कॉपी करने या टेक्स्ट फ़ाइल लिखने जैसी सामान्य समस्याओं को हल करने के लिए किया जाता है. Bash पर भरोसा करने से बचें और पहिए को फिर से न बनाएं: देखें कि क्या bazel-skylib में आपकी ज़रूरतों के लिए, खास तौर पर बनाया गया कोई नियम है. Windows पर इन्हें बनाने/टेस्ट करने के दौरान, इनमें से कोई भी Bash पर निर्भर नहीं करता.नियमों के उदाहरण:
copy_file()
(source, documentation): copies a file somewhere else, optionally making it executablewrite_file()
(source, documentation): यह फ़ंक्शन, टेक्स्ट फ़ाइल बनाता है. इसमें लाइन के आखिर मेंauto
,unix
याwindows
में से कोई एक वर्ण होता है. इसके अलावा, यह फ़ंक्शन फ़ाइल को एक्ज़ीक्यूटेबल भी बना सकता है (अगर यह स्क्रिप्ट है)run_binary()
(source, documentation): यह दिए गए इनपुट और अनुमानित आउटपुट के साथ, बाइनरी (या*_binary
नियम) को बिल्ड ऐक्शन के तौर पर चलाता है (यहctx.actions.run
के लिए बिल्ड नियम रैपर है)native_binary()
(सोर्स, दस्तावेज़): यह नेटिव बाइनरी को*_binary
नियम में रैप करता है. इसेbazel run
किया जा सकता है याrun_binary()
केtool
एट्रिब्यूट याnative.genrule()
केtools
एट्रिब्यूट में इस्तेमाल किया जा सकता है
नियम की जांच के उदाहरण:
diff_test()
(source, documentation): यह टेस्ट, दो फ़ाइलों के कॉन्टेंट की तुलना करता हैnative_test()
(source, documentation): wraps a native binary in a*_test
rule, which you canbazel test
Windows पर, सामान्य कामों के लिए
.bat
स्क्रिप्ट का इस्तेमाल करें..sh
स्क्रिप्ट के बजाय,.bat
स्क्रिप्ट की मदद से सामान्य टास्क पूरे किए जा सकते हैं.उदाहरण के लिए, अगर आपको ऐसी स्क्रिप्ट चाहिए जो कुछ न करे या कोई मैसेज प्रिंट करे या किसी तय किए गए गड़बड़ी कोड के साथ बंद हो जाए, तो इसके लिए एक सामान्य
.bat
फ़ाइल काफ़ी होगी. अगर आपके नियम सेDefaultInfo()
provider वैल्यू मिलती है, तोexecutable
फ़ील्ड, Windows पर मौजूद उस.bat
फ़ाइल को दिखा सकता है.macOS और Linux पर फ़ाइल एक्सटेंशन से कोई फ़र्क़ नहीं पड़ता. इसलिए,
.bat
को हमेशा एक्सटेंशन के तौर पर इस्तेमाल किया जा सकता है. भले ही, यह शेल स्क्रिप्ट के लिए हो.ध्यान रखें कि खाली
.bat
फ़ाइलों को नहीं चलाया जा सकता. अगर आपको खाली स्क्रिप्ट चाहिए, तो उसमें एक स्पेस डालें.Bash का इस्तेमाल सिद्धांतों के मुताबिक करें.
Starlark की बिल्ड और टेस्ट से जुड़े नियमों में,
ctx.actions.run_shell
का इस्तेमाल करके Bash स्क्रिप्ट और Bash कमांड को कार्रवाइयों के तौर पर चलाएं.Starlark मैक्रो में, Bash स्क्रिप्ट और कमांड को
native.sh_binary()
याnative.genrule()
में रैप करें. Bazel यह जांच करेगा कि Bash उपलब्ध है या नहीं. इसके बाद, Bash के ज़रिए स्क्रिप्ट या कमांड चलाएगा.Starlark रिपॉज़िटरी के नियमों में, Bash का इस्तेमाल न करें. फ़िलहाल, Bazel में रिपॉज़िटरी के नियमों में, Bash कमांड को सही तरीके से चलाने का कोई तरीका नहीं है.
फ़ाइलें मिटाना
समस्याएं:
खुली हुई फ़ाइलों को मिटाया नहीं जा सकता.
खुली हुई फ़ाइलों को डिफ़ॉल्ट रूप से मिटाया नहीं जा सकता. ऐसा करने पर, "ऐक्सेस नहीं दिया गया" गड़बड़ियां दिखती हैं. अगर किसी फ़ाइल को मिटाया नहीं जा सकता, तो हो सकता है कि कोई प्रोसेस अब भी उसे खोले हुए हो.
चल रही प्रोसेस की वर्किंग डायरेक्ट्री को मिटाया नहीं जा सकता.
प्रोसेस के पास अपनी वर्किंग डायरेक्ट्री का ओपन हैंडल होता है. साथ ही, प्रोसेस खत्म होने तक डायरेक्ट्री को मिटाया नहीं जा सकता.
समाधान:
अपने कोड में, फ़ाइलों को तुरंत बंद करने की कोशिश करें.
Java में,
try-with-resources
का इस्तेमाल करें. Python में,with open(...) as f:
का इस्तेमाल करें. सिद्धांत के तौर पर, हैंडल को जल्द से जल्द बंद करने की कोशिश करें.