Windows पर नियम लिखने की सुविधा

इस पेज पर, Windows के साथ काम करने वाले नियम लिखने, पोर्टेबल नियम लिखने से जुड़ी आम समस्याओं, और उनके कुछ समाधानों के बारे में बताया गया है.

पथ

सवाल:

  • लंबाई की सीमा: पाथ की ज़्यादा से ज़्यादा लंबाई 259 वर्ण हो सकती है.

    हालांकि Windows पर लंबे पाथ (32767 वर्ण तक) भी काम करते हैं, लेकिन बहुत से प्रोग्राम कम सीमा के साथ बनाए जाते हैं.

    कार्रवाइयों में इस्तेमाल किए जाने वाले प्रोग्राम के बारे में ध्यान रखें.

  • वर्किंग डायरेक्ट्री: इसमें ज़्यादा से ज़्यादा 259 वर्ण हो सकते हैं.

    प्रोसेस, 259 वर्णों से ज़्यादा लंबी डायरेक्ट्री में cd नहीं कर सकतीं.

  • बड़े और छोटे अक्षरों में अंतर: Windows पाथ केस-इनसेंसिटिव होते हैं, जबकि Unix पाथ केस-सेंसिटिव होते हैं.

    कार्रवाइयों के लिए कमांड लाइन बनाते समय इसका ध्यान रखें.

  • पाथ सेपरेटर: बैकस्लैश (\`), not forward slash (/`) होते हैं.

    बेज़ल, / सेपरेटर के साथ यूनिक्स-स्टाइल में बने पाथ स्टोर करता है. हालांकि, कुछ Windows प्रोग्राम में यूनिक्स स्टाइल के पाथ काम करते हैं, लेकिन कुछ में नहीं. cmd.exe में पहले से मौजूद कुछ निर्देशों के साथ, ये फ़ंक्शन काम करते हैं, जबकि कुछ के साथ नहीं.

    ऐक्शन के लिए कमांडलाइन और एनवायरमेंट वैरिएबल बनाते समय, हमेशा \` separators on Windows: replace/with` का इस्तेमाल करना सबसे अच्छा होता है.

  • ऐब्सलूट पाथ: स्लैश (/) से शुरू न करें.

    Windows पर एब्सोलूट पाथ, ड्राइव लेटर से शुरू होते हैं, जैसे कि C:\foo\bar.txt. फ़ाइल सिस्टम का कोई एक रूट नहीं होता.

    अगर आपका नियम यह जांच करता है कि कोई पाथ एब्सोल्यूट है या नहीं, तो इस बात का ध्यान रखें. ऐब्सलूट पाथ का इस्तेमाल नहीं किया जाना चाहिए, क्योंकि अक्सर वे पोर्टेबल नहीं होते.

समाधान:

  • पाथ को छोटा रखें.

    डायरेक्ट्री के लंबे नाम, डीप नेस्ट की गई डायरेक्ट्री स्ट्रक्चर, फ़ाइल के बड़े नाम, फ़ाइल फ़ोल्डर के लंबे नाम, और टारगेट के लंबे नामों से बचें.

    ये सभी, कार्रवाइयों की इनपुट फ़ाइलों के पाथ कॉम्पोनेंट बन सकते हैं. साथ ही, पाथ की लंबाई की सीमा खत्म हो सकती है.

  • आउटपुट के किसी छोटे रूट का इस्तेमाल करें.

    Baज़ल आउटपुट के लिए, एक छोटा पाथ तय करने के लिए, --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-style बनाएं. उदाहरण:

    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 पर उपलब्ध नहीं होता. बेज़ल, Bash (MSYS2) पर लगातार भरोसा कर रहे हैं. इसलिए, हो सकता है कि आने वाले समय में उपयोगकर्ताओं के पास Baज़ल के साथ MSYS2 इंस्टॉल हो जाने की संभावना भी कम हो जाए. Windows पर नियमों को आसानी से इस्तेमाल करने के लिए, ऐक्शन में Bash कमांड चलाने से बचें.

  • लाइन के आखिरी हिस्से: Windows, CRLF (\r\n) का इस्तेमाल करता है. Unix-जैसे सिस्टम LF (\n) का इस्तेमाल करते हैं.

    टेक्स्ट फ़ाइलों की तुलना करते समय इसका ध्यान रखें. Git की सेटिंग का ध्यान रखें. खास तौर पर, चेक आउट या कमिट करते समय लाइन के आखिर में लगाए जाने वाले चिह्नों का ध्यान रखें. (Git की core.autocrlf सेटिंग देखें.)

समाधान:

  • अपनी ज़रूरत के हिसाब से बनाए गए, Bash-less नियम का इस्तेमाल करें.

    native.genrule(), Bash निर्देशों के लिए एक रैपर है. इसका इस्तेमाल अक्सर आसान समस्याओं को हल करने के लिए किया जाता है. जैसे, किसी फ़ाइल को कॉपी करना या टेक्स्ट फ़ाइल लिखना. अब Bash पर भरोसा करने से बचा जा सकता है (और व्हील को नए अंदाज़ में पेश करने से बचा जा सकता है): देखें कि क्या baaz-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() में रैप करें. Bazel यह जांच करेगा कि Bash उपलब्ध है या नहीं. साथ ही, स्क्रिप्ट या कमांड को Bash के ज़रिए चलाएगा.

    Starlark रिपॉज़िटरी के नियमों में, Bash का इस्तेमाल पूरी तरह से न करें. फ़िलहाल, Bard के नियमों में बैश कमांड को रिपॉज़िटरी के नियमों में चलाने का कोई तरीका नहीं है.

फ़ाइलें मिटाना

सवाल:

  • फ़ाइलों को खोलने के दौरान, मिटाया नहीं जा सकता.

    खुली हुई फ़ाइलों को मिटाया नहीं जा सकता (डिफ़ॉल्ट रूप से), कोशिश करने पर "ऐक्सेस करने की मंज़ूरी नहीं दी गई" गड़बड़ी होती है. अगर किसी फ़ाइल को मिटाया नहीं जा सकता, तो हो सकता है कि कोई प्रोसेस अब भी उसे खोला हुआ हो.

  • चल रही प्रोसेस की वर्किंग डायरेक्ट्री को मिटाया नहीं जा सकता.

    प्रोसेस में, काम करने वाली डायरेक्ट्री का एक ओपन हैंडल होता है. जब तक प्रोसेस खत्म नहीं हो जाती, तब तक डायरेक्ट्री को मिटाया नहीं जा सकता.

समाधान:

  • अपने कोड में, फ़ाइलों को जल्द से जल्द बंद करने की कोशिश करें.

    Java में, try-with-resources का इस्तेमाल करें. Python में, with open(...) as f: का इस्तेमाल करें. हमारा सुझाव है कि जितनी जल्दी हो सके, हैंडल बंद करने की कोशिश करें.