यह पेज Windows के साथ काम करने वाले नियमों को लिखने, पोर्टेबल नियम लिखने में आने वाली आम समस्याओं, और कुछ समाधानों पर फ़ोकस करता है.
पथ
समस्याएं:
अवधि सीमा: पाथ की ज़्यादा से ज़्यादा लंबाई 259 वर्ण है.
Windows पर ज़्यादा से ज़्यादा 32,767 वर्णों का पाथ भी सेट किया जा सकता है. हालांकि, कई प्रोग्राम कम सीमा के साथ बनाए जाते हैं.
कार्रवाइयों में चलाए जाने वाले प्रोग्राम के बारे में ध्यान रखें.
वर्किंग डायरेक्ट्री: इसमें भी 259 वर्ण हो सकते हैं.
प्रोसेस, 259 वर्णों से ज़्यादा लंबी डायरेक्ट्री में
cd
नहीं हो सकतीं.केस-सेंसिटिव (बड़े और छोटे अक्षरों में अंतर): Windows के पाथ केस-इनसेंसिटिव होते हैं. वहीं, Unix पाथ केस-सेंसिटिव (बड़े और छोटे अक्षरों में अंतर) होते हैं.
कार्रवाइयों के लिए कमांड लाइन बनाते समय इस बात का ध्यान रखें.
पाथ सेपरेटर: बैकस्लैश (
\`), not forward slash (
/`) होते हैं.Bazel, यूनिक्स-स्टाइल में
/
सेपरेटर को स्टोर करता है. हालांकि, 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]: साफ़ शब्दों में जंक्शन, सिंबलिक लिंक नहीं होते, लेकिन बिल बनाने से जुड़ी कार्रवाइयों के लिए, जंक्शन को डायरेक्ट्री सिंलिंक के तौर पर माना जा सकता है.
कार्रवाइयां / एनवायरमेंट के पाथ में,
/
को `` से बदलें.किसी कार्रवाई के लिए कमांड लाइन या एनवायरमेंट वैरिएबल बनाते समय, पाथ को 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 की तरह आर्बिट्रेरी फ़ाइलें नहीं चलाई जा सकतीं.बैश कमांड: पोर्टेबिलिटी के लिए, सीधे कार्रवाइयों में बैश कमांड चलाने से बचें.
बैश, Unix जैसे सिस्टम पर बहुत बड़ा है, लेकिन यह अक्सर Windows पर उपलब्ध नहीं होता. Bazel, Bash (MSYS2) पर कम और कम भरोसा कर रहा है. इसलिए, आने वाले समय में उपयोगकर्ताओं के लिए Bazel के साथ MSYS2 इंस्टॉल होने की संभावना कम होगी. Windows पर नियमों का आसानी से इस्तेमाल करने के लिए, कार्रवाइयों में बैश कमांड चलाने से बचें.
लाइन के आखिरी हिस्से: Windows, CRLF (
\r\n
) का इस्तेमाल करता है, यूनिक्स जैसे सिस्टम, LF (\n
) का इस्तेमाल करते हैं.टेक्स्ट फ़ाइलों की तुलना करते समय इसका ध्यान रखें. अपनी Git सेटिंग का ध्यान रखें, खास तौर पर चेकआउट या कमिटिंग करते समय लाइन एंडिंग को ध्यान में रखें. (Git की
core.autocrlf
सेटिंग देखें.)
समाधान:
बैश-लेस, खास मकसद से बनाए गए नियम का इस्तेमाल करें.
native.genrule()
, बैश कमांड के लिए एक रैपर है. इसका इस्तेमाल अक्सर, फ़ाइल कॉपी करने या टेक्स्ट फ़ाइल लिखने जैसी सामान्य समस्याओं को हल करने के लिए किया जाता है. आप बैश पर भरोसा करने (और पहिए को नया रूप देने) से बच सकते हैं: देखें कि क्या bazel-skylib का आपकी ज़रूरतों के लिए कोई खास मकसद बनाया हुआ नियम है. इनमें से कोई भी, Windows पर बनाए/टेस्ट किए जाने पर बैश पर निर्भर नहीं करता.नियम बनाएं के उदाहरण:
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()
provider देता है, तोexecutable
फ़ील्ड Windows पर उस.bat
फ़ाइल का हवाला दे सकता है.macOS और Linux पर फ़ाइल एक्सटेंशन से कोई फ़र्क़ नहीं पड़ता. इसलिए, शेल स्क्रिप्ट के लिए भी एक्सटेंशन के तौर पर
.bat
का इस्तेमाल किया जा सकता है.ध्यान रखें कि खाली
.bat
फ़ाइलें नहीं चलाई जा सकतीं. अगर आपको खाली स्क्रिप्ट की ज़रूरत है, तो इसमें एक स्पेस लिखें.बैश का इस्तेमाल, सिद्धांत के हिसाब से करें.
Starlark के बिल्ड और जांच के नियमों में, बैश स्क्रिप्ट और बैश कमांड को कार्रवाइयों के तौर पर चलाने के लिए,
ctx.actions.run_shell
का इस्तेमाल करें.Starlark मैक्रो में, बैश स्क्रिप्ट और कमांड को
native.sh_binary()
याnative.genrule()
में रैप करें. Bazel जांच करेगा कि क्या Bash उपलब्ध है और बैश के ज़रिए स्क्रिप्ट या कमांड चलाएं.Starlark डेटा स्टोर करने की जगह के नियमों में, बैश से पूरी तरह बचने की कोशिश करें. फ़िलहाल, Bazel, डेटा स्टोर करने की जगहों के नियमों के हिसाब से, बैश कमांड चलाने का कोई तरीका नहीं देता है.
फ़ाइलें मिटाना
समस्याएं:
फ़ाइल खुली होने पर मिटाई नहीं जा सकती.
खुली हुई फ़ाइलों को मिटाया नहीं जा सकता (डिफ़ॉल्ट रूप से), कोशिश करने पर "ऐक्सेस नहीं दिया गया" जैसी गड़बड़ियां मिलती हैं. अगर आप कोई फ़ाइल नहीं मिटा पा रहे हैं, तो हो सकता है कि किसी चल रही प्रोसेस में वह अब भी खुली हो.
किसी चल रही प्रोसेस की वर्किंग डायरेक्ट्री को मिटाया नहीं जा सकता.
प्रोसेस की वर्किंग डायरेक्ट्री के लिए एक ओपन हैंडल होता है. प्रोसेस के खत्म होने तक, डायरेक्ट्री को मिटाया नहीं जा सकता.
समाधान:
अपने कोड में, फ़ाइलें तेज़ी से बंद करने की कोशिश करें.
Java में,
try-with-resources
इस्तेमाल करें. Python में,with open(...) as f:
इस्तेमाल करें. इसलिए, हैंडल को जल्द से जल्द बंद करने की कोशिश करें.