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

"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" वैरिएबल के नाम, अक्षरों के अलावा अन्य सिंबल भी हो सकते हैं. जैसे, @. इन्हें सिर्फ़ डॉलर के निशान का इस्तेमाल करके भी रेफ़र किया जा सकता है. इसके लिए, पैरंटheses का इस्तेमाल करने की ज़रूरत नहीं होती. उदाहरण के लिए:

my_attr = "prefix $@ suffix"

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

Predefined variables

Predefined "Make" variables can be referenced by any attribute marked as "Subject to 'Make variable' substitution" on any target.

To see the list of these variables and their values for a given set of build options, run

bazel info --show_make_env [build options]

and look at the top output lines with capital letters.

See an example of predefined variables.

Toolchain option variables

Path variables

  • BINDIR: The base of the generated binary tree for the target architecture.

    Note that a different tree may be used for programs that run during the build on the host architecture, to support cross-compiling.

    If you want to run a tool from within a genrule, the recommended way to get its path is $(execpath toolname), where toolname must be listed in the genrule's tools attribute.

  • GENDIR: The base of the generated code tree for the target architecture.

Machine architecture variables

  • TARGET_CPU: The target architecture's CPU, e.g. k8.

Predefined genrule variables

The following are specially available to genrule's cmd attribute and are generally important for making that attribute work.

See an example of predefined genrule variables.

  • OUTS: The genrule's outs list. If you have only one output file, you can also use $@.
  • SRCS: The genrule's srcs list (or more precisely: the path names of the files corresponding to labels in the srcs list). If you have only one source file, you can also use $<.
  • <: SRCS, if it is a single file. Else triggers a build error.
  • @: OUTS, if it is a single file. Else triggers a build error.
  • RULEDIR: The output directory of the target, that is, the directory corresponding to the name of the package containing the target under the genfiles or bin tree. For //my/pkg:my_genrule this always ends in my/pkg, even if //my/pkg:my_genrule's outputs are in subdirectories.

  • @D: The output directory. If outs has one entry, this expands to the directory containing that file. If it has multiple entries, this expands to the package's root directory in the genfiles tree, even if all output files are in the same subdirectory!

    Note: Use RULEDIR over @D because RULEDIR has simpler semantics and behaves the same way regardless of the number of output files.

    If the genrule needs to generate temporary intermediate files (perhaps as a result of using some other tool like a compiler), it should attempt to write them to @D (although /tmp will also be writable) and remove them before finishing.

    Especially avoid writing to directories containing inputs. They may be on read-only filesystems. Even if not, doing so would trash the source tree.

Note: If the filenames corresponding to the input labels or the output filenames contain spaces, ', or other special characters (or your genrule is part of a Starlark macro which downstream users may invoke on such files), then $(SRCS) and $(OUTS) are not suitable for interpolation into a command line, as they do not have the semantics that "${@}" would in Bash.

One workaround is to convert to a Bash array, with

mapfile SRCS <<< "$$(sed -e 's/ /\\n/g' <<'genrule_srcs_expansion'
$(SRC)
genrule_srcs_expansion
)
लिखें. इसके बाद, $(SRCS) की जगह, आने वाली कमांड लाइनों में "$$\{SRCS[@]}" का इस्तेमाल करें. इसके बजाय, Starlark नियम लिखना एक बेहतर विकल्प है.

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

पहले से तय वैरिएबल 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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • CC_FLAGS: C/C++ कंपाइलर के लिए, फ़्लैग का एक छोटा सेट. इसका इस्तेमाल genrules कर सकते हैं. खास तौर पर, इसमें सही आर्किटेक्चर चुनने के लिए फ़्लैग शामिल होते हैं. यह तब काम करता है, जब CC एक से ज़्यादा आर्किटेक्चर के साथ काम करता है.
  • DUMPBIN: Microsoft Visual Studio से Microsoft COFF बाइनरी फ़ाइल डंपर (dumpbin.exe) .
  • NM: क्रॉसटूल से "nm" कमांड.
  • OBJCOPY: objcopy कमांड, C/C++ कंपाइलर के जैसे ही सुइट से.
  • STRIP: strip कमांड, C/C++ कंपाइलर के जैसे ही सुइट से.

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

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

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

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

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

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

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

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