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

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

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

पथ

सवाल:

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

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

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

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

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

  • केस-सेंसिटिविटी: Windows के पाथ, केस-इनसेंसिटिव होते हैं. साथ ही, यूनिक्स पाथ केस-सेंसिटिव होते हैं.

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

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

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

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

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

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

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

समाधान:

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

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

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

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

    Baज़ल आउटपुट के लिए, एक छोटा पाथ तय करने के लिए, --output_user_root=<path> फ़्लैग का इस्तेमाल करें. सिर्फ़ Baze आउटपुट के लिए, ड्राइव (या वर्चुअल ड्राइव) का इस्तेमाल करना बेहतर होगा. जैसे, D:\`), and adding this line to your.baज़ेनrc` फ़ाइल:

    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") में एक ही नतीजा मिलता है. (यह अन्य भाषाओं पर भी लागू होता है.)

  • हर्मेटिकिटी: कार्रवाइयों में कम से कम कस्टम एनवायरमेंट वैरिएबल का इस्तेमाल होना चाहिए.

    एनवायरमेंट वैरिएबल, कार्रवाई की कैश कुंजी का हिस्सा होते हैं. अगर कोई कार्रवाई ऐसे एनवायरमेंट वैरिएबल का इस्तेमाल करती है जो अक्सर बदलते रहते हैं या उपयोगकर्ताओं के हिसाब से तय होते हैं, तो इससे नियम कम कैश मेमोरी में सेव हो पाएगा.

समाधान:

  • सिर्फ़ अपर-केस एनवायरमेंट वैरिएबल के नामों का इस्तेमाल करें.

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

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

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

समाधान:

  • बैश-लेस-बेस-मेड नियम का इस्तेमाल करें.

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

    टेस्ट के नियम के उदाहरण:

    • diff_test() (सोर्स, दस्तावेज़): यह एक टेस्ट है, जिसमें दो फ़ाइलों के कॉन्टेंट की तुलना की जाती है

    • native_test() (सोर्स, दस्तावेज़): *_test नियम में नेटिव बाइनरी को रैप करता है, जिसे bazel test किया जा सकता है

  • 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() में रैप करें. BaZ चैनल यह जांच करेगा कि Bash उपलब्ध है या नहीं. साथ ही, Bash की मदद से स्क्रिप्ट या कमांड चलाएं.

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

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

सवाल:

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

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

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

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

समाधान:

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

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