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

किसी समस्या की शिकायत करें सोर्स देखें Nightly · 7.4 .

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

पथ

सवाल:

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

    हालांकि, Windows में 32,767 वर्णों तक के लंबे पाथ का इस्तेमाल किया जा सकता है, लेकिन कई प्रोग्राम कम वर्णों के साथ बनाए जाते हैं.

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

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

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

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

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

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

    बेज़ल, / सेपरेटर के साथ यूनिक्स-स्टाइल में बने पाथ स्टोर करता है. हालांकि, कुछ 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") में एक जैसा नतीजा मिलता है. (यह अन्य भाषाओं पर भी लागू होता है.)

  • 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 पर निर्भर रहने और फिर से पहिया बनाने से बचा जा सकता है: देखें कि 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 फ़ाइलों को लागू नहीं किया जा सकता. अगर आपको कोई खाली स्क्रिप्ट चाहिए, तो उसमें एक स्पेस लिखें.

  • बैश का इस्तेमाल सिद्धांत के साथ करें.

    Starlark के बिल्ड और टेस्ट नियमों में, Bash स्क्रिप्ट और Bash कमांड को कार्रवाइयों के तौर पर चलाने के लिए, ctx.actions.run_shell का इस्तेमाल करें.

    Starlark मैक्रो में, Bash स्क्रिप्ट और कमांड को native.sh_binary() या native.genrule() में रैप करें. Basel यह जांच करेगा कि Bash उपलब्ध है या नहीं. साथ ही, Bash की मदद से स्क्रिप्ट या कमांड चलाएं.

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

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

सवाल:

  • फ़ाइलें खुली होने पर उन्हें मिटाया नहीं जा सकता.

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

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

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

समाधान:

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

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