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

किसी समस्या की शिकायत करना सोर्स देखना Nightly · 8.0 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

पथ

समस्याएं:

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

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

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

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

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

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

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

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

    Bazel, पाथ को यूनिक्स स्टाइल में / सेपरेटर के साथ सेव करता है. हालांकि, कुछ 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 (बैच स्क्रिप्ट) एक्सटेंशन का इस्तेमाल किया जाता है.

    ध्यान रखें कि Windows पर शेल स्क्रिप्ट (.sh) को चलाया नहीं जा सकता. इन्हें 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 सेटिंग देखें.)

समाधान:

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

  • 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: का इस्तेमाल करें. आम तौर पर, हैंडल को जल्द से जल्द बंद करने की कोशिश करें.