वैरिएबल बनाएं

"Make" वैरिएबल, स्ट्रिंग वैरिएबल की एक खास क्लास है. इसे "Make वैरिएबल" के तौर पर मार्क किए गए एट्रिब्यूट के लिए इस्तेमाल किया जा सकता है.

उदाहरण के लिए, इनका इस्तेमाल उपयोगकर्ता के बनाए गए बिल्ड ऐक्शन में, टूलचेन के खास पाथ डालने के लिए किया जा सकता है.

Bazel, पहले से तय वैरिएबल और कस्टम वैरिएबल, दोनों उपलब्ध कराता है. पहले से तय वैरिएबल, सभी टारगेट के लिए उपलब्ध होते हैं. वहीं, कस्टम वैरिएबल, डिपेंडेंसी टारगेट में तय किए जाते हैं और सिर्फ़ उन टारगेट के लिए उपलब्ध होते हैं जो उन पर निर्भर होते हैं.

"Make" शब्द का इस्तेमाल, इतिहास की वजह से किया जाता है. इन वैरिएबल के सिंटैक्स और सिमैंटिक को मूल रूप से GNU Make से मैच करने के लिए बनाया गया था.

इस्तेमाल करें

"Make वैरिएबल" के तौर पर मार्क किए गए एट्रिब्यूट, "Make" वैरिएबल FOO को इस तरह रेफ़र कर सकते हैं:

my_attr = "prefix $(FOO) suffix"

दूसरे शब्दों में, $(FOO) से मैच करने वाली किसी भी सबस्ट्रिंग को FOO's वैल्यू में एक्सपैंड किया जाता है. अगर वह वैल्यू "bar" है, तो फ़ाइनल स्ट्रिंग यह बन जाती है:

my_attr = "prefix bar suffix"

अगर FOO किसी ऐसे वैरिएबल से मेल नहीं खाता है जो इस्तेमाल करने वाले टारगेट को पता है, तो Bazel में गड़बड़ी होती है.

"Make" वैरिएबल के नाम, अक्षरों के अलावा अन्य सिंबल हो सकते हैं. जैसे, @. इन्हें सिर्फ़ डॉलर के निशान का इस्तेमाल करके भी रेफ़र किया जा सकता है. इसके लिए, ब्रैकेट का इस्तेमाल करने की ज़रूरत नहीं होती. उदाहरण के लिए:

my_attr = "prefix $@ suffix"

$ को स्ट्रिंग लिटरल के तौर पर लिखने के लिए (यानी, वैरिएबल के एक्सपैंशन को रोकने के लिए), $$ लिखें.

पहले से तय वैरिएबल

पहले से तय "Make" वैरिएबल को, किसी भी टारगेट पर "Make वैरिएबल" के तौर पर मार्क किए गए किसी भी एट्रिब्यूट से रेफ़र किया जा सकता है.

बिल्ड के विकल्पों के किसी सेट के लिए, इन वैरिएबल और उनकी वैल्यू की सूची देखने के लिए, यह कमांड चलाएं:

bazel info --show_make_env [build options]

इसके बाद, आउटपुट की सबसे ऊपर वाली लाइनों को देखें. इनमें बड़े अक्षरों का इस्तेमाल किया गया होता है.

पहले से तय वैरिएबल का उदाहरण देखें.

टूलचेन के विकल्प वाले वैरिएबल

पाथ वैरिएबल

  • BINDIR: टारगेट आर्किटेक्चर के लिए जनरेट किए गए बाइनरी ट्री का बेस.

    ध्यान दें कि क्रॉस-कंपाइलिंग की सुविधा देने के लिए, होस्ट आर्किटेक्चर पर बिल्ड के दौरान चलने वाले प्रोग्राम के लिए, अलग ट्री का इस्तेमाल किया जा सकता है.

    अगर आपको genrule में किसी टूल को चलाना है, तो उसका पाथ पाने का सुझाव दिया जाता है. इसके लिए, $(execpath toolname) का इस्तेमाल करें. यहां toolname को genrule's tools एट्रिब्यूट में शामिल किया जाना चाहिए.

  • GENDIR: टारगेट आर्किटेक्चर के लिए जनरेट किए गए कोड ट्री का बेस.

मशीन आर्किटेक्चर वैरिएबल

  • TARGET_CPU: टारगेट आर्किटेक्चर का सीपीयू. जैसे, k8.

पहले से तय genrule वैरिएबल

ये वैरिएबल, खास तौर पर genrule's cmd एट्रिब्यूट के लिए उपलब्ध होते हैं. आम तौर पर, इस एट्रिब्यूट को काम करने के लिए इनकी ज़रूरत होती है.

पहले से तय genrule वैरिएबल का उदाहरण देखें.

  • OUTS: genrule की outs सूची. अगर आपके पास सिर्फ़ एक आउटपुट फ़ाइल है, तो $@ का इस्तेमाल किया जा सकता है.
  • SRCS: genrule की srcs सूची. ज़्यादा सटीक तौर पर कहें, तो srcs सूची में मौजूद लेबल से जुड़ी फ़ाइलों के पाथ के नाम. अगर आपके पास सिर्फ़ एक सोर्स फ़ाइल है, तो $< का इस्तेमाल किया जा सकता है.
  • <: SRCS, अगर यह एक फ़ाइल है. वरना, बिल्ड में गड़बड़ी होती है.
  • @: OUTS, अगर यह एक फ़ाइल है. वरना, बिल्ड में गड़बड़ी होती है.
  • RULEDIR: टारगेट की आउटपुट डायरेक्ट्री. यानी, genfiles या bin ट्री में टारगेट वाले पैकेज के नाम से जुड़ी डायरेक्ट्री. //my/pkg:my_genrule के लिए, यह हमेशा my/pkg पर खत्म होता है. भले ही, //my/pkg:my_genrule के आउटपुट सबडायरेक्ट्री में हों.

  • @D: आउटपुट डायरेक्ट्री. अगर आउट्स में एक एंट्री है, तो यह उस डायरेक्ट्री में एक्सपैंड होती है जिसमें वह फ़ाइल मौजूद है. अगर इसमें एक से ज़्यादा एंट्री हैं, तो यह पैकेज की रूट डायरेक्ट्री में genfiles ट्री में एक्सपैंड होती है. भले ही, सभी आउटपुट फ़ाइलें एक ही सबडायरेक्ट्री में हों!

    ध्यान दें: @D के बजाय RULEDIR का इस्तेमाल करें, क्योंकि RULEDIR के सिमैंटिक आसान होते हैं और आउटपुट फ़ाइलों की संख्या के बावजूद, यह एक ही तरह से काम करता है.

    अगर genrule को अस्थायी इंटरमीडिएट फ़ाइलें जनरेट करनी हैं (शाय101}द किसी अन्य टूल, जैसे कि कंपाइलर का इस्तेमाल करने की वजह से), तो उसे @D में लिखने की कोशिश करनी चाहिए. हालांकि, /tmp में भी लिखा जा सकता है. साथ ही, काम पूरा होने से पहले उन्हें हटा देना चाहिए.

    खास तौर पर, इनपुट वाली डायरेक्ट्री में लिखने से बचें. ऐसा हो सकता है कि वे रीड-ओनली फ़ाइल सिस्टम पर मौजूद हों. ऐसा न होने पर भी, सोर्स ट्री खराब हो जाएगा.

पहले से तय सोर्स/आउटपुट पाथ वैरिएबल

पहले से तय वैरिएबल execpath, execpaths, rootpath, rootpaths, location, और locations लेबल पैरामीटर लेते हैं.जैसे, $(execpath //foo:bar). साथ ही, उस लेबल से दिखाए गए फ़ाइल पाथ को बदल देते हैं.

सोर्स फ़ाइलों के लिए, यह आपके वर्कस्पेस रूट के मुकाबले रिलेटिव पाथ होता है. नियमों के आउटपुट के तौर पर इस्तेमाल की जाने वाली फ़ाइलों के लिए, यह फ़ाइल का आउटपुट पाथ होता है. इसके बारे में, नीचे आउटपुट फ़ाइलें की जानकारी में बताया गया है.

पहले से तय पाथ वैरिएबल का उदाहरण देखें.

  • execpath: execroot के नीचे मौजूद पाथ को दिखाता है, जहां Bazel बिल्ड ऐक्शन चलाता है.

    ऊपर दिए गए उदाहरण में, Bazel आपके वर्कस्पेस रूट में bazel-myproject सिमलंक से लिंक की गई डायरेक्ट्री में, सभी बिल्ड ऐक्शन चलाता है. सोर्स फ़ाइल empty.source, bazel-myproject/testapp/empty.source पाथ पर लिंक की गई है. इसलिए, इसका exec पाथ (जो रूट के नीचे का सबपाथ है) testapp/empty.source है. बिल्ड ऐक्शन, फ़ाइल को ढूंढने के लिए इस पाथ का इस्तेमाल कर सकते हैं.

    आउटपुट फ़ाइलों को भी इसी तरह स्टेज किया जाता है. हालांकि, इनके पहले सबपाथ bazel-out/cpu-compilation_mode/bin जोड़ा जाता है. वहीं, टूल के आउटपुट के लिए, bazel-out/cpu-opt-exec-hash/bin जोड़ा जाता है. ऊपर दिए गए उदाहरण में, //testapp:app एक टूल है, क्योंकि यह show_app_output's tools एट्रिब्यूट में दिखता है. इसलिए, इसकी आउटपुट फ़ाइल app को bazel-myproject/bazel-out/cpu-opt-exec-hash/bin/testapp/app में लिखा जाता है. इस तरह, exec पाथ bazel-out/cpu-opt-exec-hash/bin/testapp/app होता है. इस अतिरिक्त प्रीफ़िक्स की मदद से, एक ही बिल्ड में एक ही टारगेट को, उदाहरण के लिए, दो अलग-अलग सीपीयू के लिए बनाया जा सकता है. इससे, नतीजे एक-दूसरे को ओवरराइट नहीं करते.

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

  • rootpath: उस पाथ को दिखाता है जिसका इस्तेमाल, बिल्ड की गई बाइनरी, रनटाइम में डिपेंडेंसी को ढूंढने के लिए कर सकती है. यह पाथ, मुख्य डेटाबेस से जुड़ी रनफ़ाइल डायरेक्ट्री की सबडायरेक्ट्री के मुकाबले होता है. ध्यान दें: यह सिर्फ़ तब काम करता है, जब --enable_runfiles चालू हो. Windows पर, यह डिफ़ॉल्ट रूप से चालू नहीं होता. क्रॉस-प्लैटफ़ॉर्म सहायता के लिए, इसके बजाय rlocationpath का इस्तेमाल करें.

    यह execpath की तरह ही है, लेकिन इसमें ऊपर बताए गए कॉन्फ़िगरेशन प्रीफ़िक्स शामिल नहीं होते. ऊपर दिए गए उदाहरण में, इसका मतलब है कि empty.source और app दोनों में वर्कस्पेस के मुकाबले रिलेटिव पाथ का इस्तेमाल किया जाता है: testapp/empty.source और testapp/app.

    किसी बाहरी डेटाबेस rootpath में मौजूद फ़ाइल का repo ../repo/ से शुरू होगा. इसके बाद, डेटाबेस के मुकाबले रिलेटिव पाथ आएगा.

    इसके लिए भी "सिर्फ़ एक आउटपुट" की ज़रूरत होती है. यह ज़रूरत, execpath के लिए भी होती है.

  • rlocationpath: वह पाथ जिसे बिल्ड की गई बाइनरी, रनटाइम में डिपेंडेंसी को ढूंढने के लिए, रनफ़ाइल लाइब्रेरी के Rlocation फ़ंक्शन को पास कर सकती है. यह पाथ, रनफ़ाइल डायरेक्ट्री (अगर उपलब्ध हो) या रनफ़ाइल मैनिफ़ेस्ट का इस्तेमाल करके मिलता है.

    यह rootpath की तरह ही है, क्योंकि इसमें कॉन्फ़िगरेशन प्रीफ़िक्स शामिल नहीं होते. हालांकि, इसमें यह अंतर है कि यह हमेशा डेटाबेस के नाम से शुरू होता है. ऊपर दिए गए उदाहरण में, इसका मतलब है कि empty.source और app के लिए, ये पाथ मिलते हैं: myproject/testapp/empty.source और myproject/testapp/app.

    किसी बाहरी डेटाबेस rlocationpath में मौजूद फ़ाइल का repo repo/ से शुरू होगा. इसके बाद, डेटाबेस के मुकाबले रिलेटिव पाथ आएगा.

    रनटाइम में डिपेंडेंसी ढूंढने के लिए, इस पाथ को बाइनरी में पास करना और रनफ़ाइल लाइब्रेरी का इस्तेमाल करके इसे फ़ाइल सिस्टम पाथ में बदलना, सबसे अच्छा तरीका है. rootpath के मुकाबले, इसका फ़ायदा यह है कि यह सभी प्लैटफ़ॉर्म पर काम करता है. साथ ही, यह तब भी काम करता है, जब रनफ़ाइल डायरेक्ट्री उपलब्ध न हो.

    इसके लिए भी "सिर्फ़ एक आउटपुट" की ज़रूरत होती है. यह ज़रूरत, execpath के लिए भी होती है.

  • location: यह execpath या rootpath का समानार्थी है. यह इस बात पर निर्भर करता है कि कौनसे एट्रिब्यूट को एक्सपैंड किया जा रहा है. यह Starlark से पहले के समय का व्यवहार है. इसका इस्तेमाल करने का सुझाव नहीं दिया जाता. हालांकि, अगर आपको वाकई में पता है कि यह किसी खास नियम के लिए क्या करता है, तो इसका इस्तेमाल किया जा सकता है. ज़्यादा जानकारी के लिए, #2475 देखें.

execpaths, rootpaths, rlocationpaths, और locations, क्रमशः execpath, rootpath, rlocationpaths, औरlocation, के प्लरल वैरिएशन हैं. ये ऐसे लेबल के साथ काम करते हैं जो एक से ज़्यादा आउटपुट जनरेट करते हैं. ऐसे में, हर आउटपुट को स्पेस से अलग करके दिखाया जाता है. शून्य आउटपुट वाले नियमों और गलत फ़ॉर्मैट वाले लेबल की वजह से, बिल्ड में गड़बड़ियां होती हैं.

रेफ़र किए गए सभी लेबल, इस्तेमाल करने वाले टारगेट के srcs, आउटपुट फ़ाइलों या deps में दिखने चाहिए. वरना, बिल्ड में गड़बड़ी होती है. C++ टारगेट, `data` में मौजूद लेबल को भी रेफ़र कर सकते हैं.data

लेबल, कैननिकल फ़ॉर्म में होने ज़रूरी नहीं हैं. foo, :foo और //somepkg:foo, सभी मान्य हैं.

कस्टम वैरिएबल

कस्टम "Make" वैरिएबल को, "Make वैरिएबल" के तौर पर मार्क किए गए किसी भी एट्रिब्यूट से रेफ़र किया जा सकता है. हालांकि, सिर्फ़ उन टारगेट पर जो इन वैरिएबल को तय करने वाले अन्य टारगेट पर निर्भर होते हैं.

सबसे सही तरीका यह है कि सभी वैरिएबल कस्टम होने चाहिए. हालांकि, अगर Bazel के कोर में उन्हें शामिल करने की कोई ठोस वजह हो, तो ऐसा किया जा सकता है. इससे Bazel को, संभावित तौर पर महंगी डिपेंडेंसी लोड करने से बचाया जा सकता है. ऐसा इसलिए, क्योंकि वैरिएबल का इस्तेमाल करने वाले टारगेट को शायद उनकी ज़रूरत न हो.

C++ टूलचेन वैरिएबल

ये वैरिएबल, C++ टूलचेन के नियमों में तय किए जाते हैं. साथ ही, ये उन सभी नियमों के लिए उपलब्ध होते हैं जिनमें toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"] सेट किया गया है. कुछ नियमों, जैसे कि java_binary, में, C++ टूलचेन को उनके नियम की परिभाषा में शामिल किया जाता है. ये वैरिएबल अपने-आप इनहेरिट हो जाते हैं.

C++ के बिल्ट-इन नियम, "कंपाइलर को इस पर चलाएं" से कहीं ज़्यादा बेहतर हैं. एक साथ कई प्लैटफ़ॉर्म पर, *SAN, ThinLTO, मॉड्यूल के साथ/बिना मॉड्यूल, और सावधानी से ऑप्टिमाइज़ की गई बाइनरी के साथ-साथ, तेज़ी से चलने वाले टेस्ट के लिए, बिल्ट-इन नियम यह पक्का करने के लिए काफ़ी मेहनत करते हैं कि संभावित तौर पर अंदरूनी तौर पर जनरेट किए गए कई ऐक्शन में से हर एक पर, सही इनपुट, आउटपुट, और कमांड-लाइन फ़्लैग सेट किए जाएं.

ये वैरिएबल, फ़ॉलबैक मैकेनिज़्म हैं. इनका इस्तेमाल, भाषा के विशेषज्ञ बहुत कम मामलों में करते हैं. अगर आपको इनका इस्तेमाल करना है, तो कृपया पहले Bazel के डेवलपर से संपर्क करें.

  • ABI: C++ ABI का वर्शन.
  • AR: crosstool से "ar" कमांड.
  • C_COMPILER: C/C++ कंपाइलर आइडेंटिफ़ायर. जैसे, llvm.
  • CC: C और C++ कंपाइलर कमांड.

    हमारा सुझाव है कि CC के साथ हमेशा CC_FLAGS का इस्तेमाल करें. ऐसा न करने पर, आपको अपने जोखिम पर काम करना होगा.

  • CC_FLAGS: C/C++ कंपाइलर के लिए, फ़्लैग का एक छोटा सेट. इसका इस्तेमाल genrule कर सकते हैं. खास तौर पर, इसमें सही आर्किटेक्चर चुनने के लिए फ़्लैग शामिल होते हैं. हालांकि, यह तब काम करता है, जब CC कई आर्किटेक्चर के साथ काम करता हो.
  • NM: crosstool से "nm" कमांड.
  • OBJCOPY: objcopy कमांड. यह C/C++ कंपाइलर के जैसे ही सुइट से आता है.
  • STRIP: strip कमांड. यह C/C++ कंपाइलर के जैसे ही सुइट से आता है.

Java टूलचेन वैरिएबल

ये वैरिएबल, Java टूलचेन के नियमों में तय किए जाते हैं. साथ ही, ये उन सभी नियमों के लिए उपलब्ध होते हैं जिनमें toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"] सेट किया गया है. होस्ट टूलचेन के लिए, "@bazel_tools//tools/jdk:current_host_java_runtime" सेट किया जाता है.

JDK में मौजूद ज़्यादातर टूल का इस्तेमाल सीधे तौर पर नहीं किया जाना चाहिए. Java के बिल्ट-इन Java नियम, Java कंपाइलेशन और पैकेजिंग के लिए, अपस्ट्रीम टूल के मुकाबले ज़्यादा बेहतर तरीकों का इस्तेमाल करते हैं. जैसे, इंटरफ़ेस जार, हेडर इंटरफ़ेस जार, और बहुत ज़्यादा ऑप्टिमाइज़ की गई जार पैकेजिंग और मर्जिंग के लिए लागू किए गए तरीके.

ये वैरिएबल, फ़ॉलबैक मैकेनिज़्म हैं. इनका इस्तेमाल, भाषा के विशेषज्ञ बहुत कम मामलों में करते हैं. अगर आपको इनका इस्तेमाल करना है, तो कृपया पहले Bazel के डेवलपर से संपर्क करें.

  • JAVA: "java" कमांड. यह Java वर्चुअल मशीन है. इसका इस्तेमाल न करें. इसके बजाय, जहां भी मुमकिन हो, java_binary नियम का इस्तेमाल करें. यह रिलेटिव पाथ हो सकता है. अगर आपको डायरेक्ट्री बदलनी है java को लागू करने से पहले, तो डायरेक्ट्री बदलने से पहले, आपको वर्किंग डायरेक्ट्री को कैप्चर करना होगा.
  • JAVABASE: वह बेस डायरेक्ट्री जिसमें Java यूटिलिटी मौजूद होती हैं. यह रिलेटिव पाथ हो सकता है. इसमें "bin" सबडायरेक्ट्री होगी.

Starlark में तय किए गए वैरिएबल

नियम और टूलचेन के लेखक, TemplateVariableInfo प्रोवाइडर को वापस करके, पूरी तरह से कस्टम वैरिएबल तय कर सकते हैं. ` toolchains` एट्रिब्यूट के ज़रिए इन पर निर्भर रहने वाले सभी नियम, इनकी वैल्यू पढ़ सकते हैं:

Starlark में तय किए गए वैरिएबल का उदाहरण देखें.