C++ टूलचेन कॉन्फ़िगरेशन

समस्या की शिकायत करें सोर्स देखें Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

खास जानकारी

सही विकल्पों के साथ कंपाइलर को शुरू करने के लिए, Bazel को कंपाइलर के इंटरनल के बारे में कुछ जानकारी होनी चाहिए. जैसे, शामिल की गई डायरेक्ट्री और अहम फ़्लैग. दूसरे शब्दों में कहें, तो Bazel को कंपाइलर के आसान मॉडल की ज़रूरत होती है, ताकि वह उसके काम करने के तरीके को समझ सके.

Bazel को यह जानकारी चाहिए:

  • कंपाइलर, thinLTO, मॉड्यूल, डाइनैमिक लिंकिंग या पीआईसी (पोजीशन इंडिपेंडेंट कोड) के साथ काम करता है या नहीं.
  • gcc, ld, ar, objcopy वगैरह जैसे ज़रूरी टूल के पाथ.
  • पहले से मौजूद सिस्टम में डायरेक्ट्री शामिल होती हैं. Bazel को इनकी ज़रूरत होती है, ताकि वह पुष्टि कर सके कि सोर्स फ़ाइल में शामिल किए गए सभी हेडर, BUILD फ़ाइल में सही तरीके से घोषित किए गए हैं.
  • डिफ़ॉल्ट sysroot.
  • कंपाइलेशन, लिंकिंग, और संग्रह करने के लिए किन फ़्लैग का इस्तेमाल करना है.
  • कंपाइलेशन के साथ काम करने वाले मोड (opt, dbg, fastbuild) के लिए, किन फ़्लैग का इस्तेमाल करना है.
  • ऐसे वैरिएबल बनाएं जिनकी ज़रूरत कंपाइलर को खास तौर पर होती है.

अगर कंपाइलर कई आर्किटेक्चर के साथ काम करता है, तो Bazel को उन्हें अलग-अलग कॉन्फ़िगर करना होगा.

CcToolchainConfigInfo एक ऐसा प्रोवाइडर है जो Bazel के C++ नियमों के व्यवहार को कॉन्फ़िगर करने के लिए ज़रूरी लेवल की बारीकी से जानकारी देता है. डिफ़ॉल्ट रूप से, Bazel आपके बिल्ड के लिए CcToolchainConfigInfo को अपने-आप कॉन्फ़िगर करता है. हालांकि, इसे मैन्युअल तरीके से कॉन्फ़िगर किया जा सकता है. इसके लिए, आपको एक Starlark नियम की ज़रूरत होगी. यह नियम CcToolchainConfigInfo उपलब्ध कराता है. साथ ही, आपको cc_toolchain के toolchain_config एट्रिब्यूट को अपने नियम पर पॉइंट करना होगा. CcToolchainConfigInfo बनाने के लिए, cc_common.create_cc_toolchain_config_info() पर कॉल करें. आपको इस प्रोसेस में जिन स्ट्रक्चर की ज़रूरत होगी उनके लिए Starlark कंस्ट्रक्टर, @rules_cc//cc:cc_toolchain_config_lib.bzl में मिल सकते हैं.

जब कोई C++ टारगेट, विश्लेषण फ़ेज़ में पहुंचता है, तो Bazel, BUILD फ़ाइल के आधार पर सही cc_toolchain टारगेट चुनता है. इसके बाद, cc_toolchain.toolchain_config एट्रिब्यूट में तय किए गए टारगेट से CcToolchainConfigInfo प्रोवाइडर हासिल करता है. cc_toolchain टारगेट, CcToolchainProvider के ज़रिए यह जानकारी C++ टारगेट को भेजता है.

उदाहरण के लिए, कंपाइल या लिंक करने की कार्रवाई, cc_binary या cc_library जैसे किसी नियम से शुरू होती है. इसके लिए, यह जानकारी ज़रूरी होती है:

  • इस्तेमाल किया जाने वाला कंपाइलर या लिंकर
  • कंपाइलर/लिंकर के लिए कमांड-लाइन फ़्लैग
  • --copt/--linkopt विकल्पों के ज़रिए पास किए गए कॉन्फ़िगरेशन फ़्लैग
  • एनवायरमेंट वैरिएबल
  • सैंडबॉक्स में ज़रूरी आर्टफ़ैक्ट, जिसमें कार्रवाई की जाती है

ऊपर दी गई सभी जानकारी, सैंडबॉक्स में ज़रूरी आर्टफ़ैक्ट को छोड़कर, उस Starlark टारगेट में दी गई है जिस पर cc_toolchain पॉइंट करता है.

सैंडबॉक्स में शिप किए जाने वाले आर्टफ़ैक्ट, cc_toolchain टारगेट में घोषित किए जाते हैं. उदाहरण के लिए, cc_toolchain.linker_files एट्रिब्यूट की मदद से, सैंडबॉक्स में शिप करने के लिए लिंकर बाइनरी और टूलचेन लाइब्रेरी तय की जा सकती हैं.

टूलचेन चुनना

टूलचेन चुनने का लॉजिक इस तरह काम करता है:

  1. उपयोगकर्ता, BUILD फ़ाइल में cc_toolchain_suite टारगेट तय करता है. इसके बाद, --crosstool_top विकल्प का इस्तेमाल करके, Bazel को टारगेट के बारे में बताता है.

  2. cc_toolchain_suite टारगेट, कई टूलचेन का रेफ़रंस देता है. --cpu और --compiler फ़्लैग की वैल्यू से यह तय होता है कि इनमें से कौनसा टूलचेन चुना जाएगा. यह फ़्लैग की वैल्यू के आधार पर या --cpu | --compiler वैल्यू के आधार पर तय होता है.--cpu चुने जाने की प्रोसेस इस तरह होती है:

    • अगर --compiler विकल्प दिया गया है, तो Bazel, --cpu | --compiler वाले cc_toolchain_suite.toolchains एट्रिब्यूट से मिलती-जुलती एंट्री चुनता है. अगर Bazel को कोई मिलती-जुलती एंट्री नहीं मिलती है, तो वह गड़बड़ी का मैसेज दिखाता है.

    • अगर --compiler विकल्प नहीं दिया गया है, तो Bazel, cc_toolchain_suite.toolchains एट्रिब्यूट से मिलती-जुलती एंट्री चुनता है. इसमें सिर्फ़ --cpu होता है.

    • अगर कोई फ़्लैग नहीं दिया जाता है, तो Bazel होस्ट सिस्टम की जांच करता है और अपनी जांच के आधार पर --cpu वैल्यू चुनता है. जांच करने वाले कोड के बारे में जानें.

टूलचेन चुनने के बाद, Starlark नियम में मौजूद उससे जुड़े feature और action_config ऑब्जेक्ट, बिल्ड के कॉन्फ़िगरेशन को कंट्रोल करते हैं. इसका मतलब है कि ये ऑब्जेक्ट, बाद में बताए गए आइटम को कंट्रोल करते हैं. इन मैसेज की मदद से, Bazel बाइनरी में बदलाव किए बिना, Bazel में C++ की सभी सुविधाओं को लागू किया जा सकता है. C++ के नियमों में कई यूनीक कार्रवाइयां की जा सकती हैं. इनके बारे में Bazel के सोर्स कोड में पूरी जानकारी दी गई है.

सुविधाएं

कोई सुविधा एक ऐसी इकाई होती है जिसके लिए कमांड-लाइन फ़्लैग, कार्रवाइयां, एक्ज़ीक्यूशन एनवायरमेंट पर पाबंदियां या निर्भरता में बदलाव की ज़रूरत होती है. कोई सुविधा, BUILD फ़ाइलों को फ़्लैग के कॉन्फ़िगरेशन चुनने की अनुमति देने जैसी आसान सुविधा हो सकती है. जैसे, treat_warnings_as_errors या C++ नियमों के साथ इंटरैक्ट करना और कंपाइलेशन में नई कंपाइल कार्रवाइयां और इनपुट शामिल करना. जैसे, header_modules या thin_lto.

आदर्श रूप से, CcToolchainConfigInfo में सुविधाओं की सूची होती है. इसमें हर सुविधा में एक या उससे ज़्यादा फ़्लैग ग्रुप होते हैं. हर फ़्लैग ग्रुप, फ़्लैग की एक ऐसी सूची तय करता है जो Bazel की खास कार्रवाइयों पर लागू होती है.

किसी सुविधा को नाम से तय किया जाता है. इससे, Bazel के रिलीज़ वर्शन से Starlark नियम के कॉन्फ़िगरेशन को पूरी तरह से अलग किया जा सकता है. दूसरे शब्दों में कहें, तो Bazel के रिलीज़ होने से CcToolchainConfigInfo कॉन्फ़िगरेशन के व्यवहार पर कोई असर नहीं पड़ता. ऐसा तब तक होता है, जब तक उन कॉन्फ़िगरेशन के लिए नई सुविधाओं का इस्तेमाल करना ज़रूरी न हो.

किसी सुविधा को इनमें से किसी एक तरीके से चालू किया जाता है:

  • सुविधा के enabled फ़ील्ड को true पर सेट किया गया है.
  • Bazel या नियम के मालिक ने इसे साफ़ तौर पर चालू किया हो.
  • उपयोगकर्ता इसे --feature Bazel विकल्प या features नियम एट्रिब्यूट के ज़रिए चालू करता है.

सुविधाएँ एक-दूसरे पर निर्भर हो सकती हैं. साथ ही, ये कमांड लाइन फ़्लैग, BUILDफ़ाइल की सेटिंग, और अन्य वैरिएबल पर भी निर्भर हो सकती हैं.

सुविधाओं के बीच संबंध

आम तौर पर, डिपेंडेंसी को सीधे तौर पर Bazel से मैनेज किया जाता है. यह सिर्फ़ ज़रूरी शर्तों को लागू करता है और बिल्ड में तय की गई सुविधाओं की वजह से होने वाले टकरावों को मैनेज करता है. टूलचेन स्पेसिफ़िकेशन की मदद से, Starlark नियम में सीधे तौर पर इस्तेमाल करने के लिए ज़्यादा बेहतर कंस्ट्रेंट तय किए जा सकते हैं. ये कंस्ट्रेंट, सुविधा के साथ काम करने और उसे बढ़ाने से जुड़े होते हैं. इनके उदाहरण हैं:

Constraint ब्यौरा
requires = [
   feature_set (features = [
       'feature-name-1',
       'feature-name-2'
   ]),
]
सुविधा के लेवल पर. यह सुविधा सिर्फ़ तब काम करती है, जब बताई गई ज़रूरी सुविधाएं चालू हों. उदाहरण के लिए, जब कोई सुविधा सिर्फ़ कुछ बिल्ड मोड (opt, dbg या fastbuild) में काम करती है. अगर `requires` में एक से ज़्यादा `feature_set`शामिल हैं, तो सुविधा तब काम करती है, जब कोई भी `feature_set`पूरा हो जाता है (जब बताई गई सभी सुविधाएं चालू हों).
implies = ['feature']

सुविधा के लेवल पर. इस सुविधा का मतलब है कि इसमें बताई गई सुविधाएँ शामिल हैं. किसी सुविधा को चालू करने पर, उससे जुड़ी सभी सुविधाएं भी अपने-आप चालू हो जाती हैं. इसका मतलब है कि यह सुविधा, बार-बार काम करती है.

यह सुविधाओं के सेट से, फ़ंक्शन के सामान्य सबसेट को फ़ैक्टर करने की सुविधा भी देता है. जैसे, सैनिटाइज़र के सामान्य हिस्से. इस्तेमाल की गई सुविधाओं को बंद नहीं किया जा सकता.

provides = ['feature']

सुविधा के लेवल पर. इससे पता चलता है कि यह सुविधा, एक-दूसरे से अलग कई वैकल्पिक सुविधाओं में से एक है. उदाहरण के लिए, सभी सैनिटाइज़र provides = ["sanitizer"] की जानकारी दे सकते हैं.

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

with_features = [
  with_feature_set(
    features = ['feature-1'],
    not_features = ['feature-2'],
  ),
]
सेट-लेवल पर फ़्लैग किया गया. किसी सुविधा के लिए, एक से ज़्यादा फ़्लैग सेट तय किए जा सकते हैं. with_features को तय करने पर, फ़्लैग सेट सिर्फ़ तब बिल्ड कमांड तक बढ़ेगा, जब कम से कम एक with_feature_set ऐसा हो जिसके लिए तय किए गए features सेट की सभी सुविधाएं चालू हों और not_features सेट में तय की गई सभी सुविधाएं बंद हों. अगर with_features तय नहीं किया गया है, तो सेट किया गया फ़्लैग, बताई गई हर कार्रवाई के लिए बिना किसी शर्त के लागू होगा.

कार्रवाइयां

कार्रवाइयों की मदद से, उन स्थितियों में बदलाव किया जा सकता है जिनमें कोई कार्रवाई की जाती है. हालांकि, इससे यह तय नहीं होता कि कार्रवाई कैसे की जाएगी. action_config से उस टूल बाइनरी के बारे में पता चलता है जिसे कोई कार्रवाई शुरू करती है. वहीं, feature से उस कॉन्फ़िगरेशन (फ़्लैग) के बारे में पता चलता है जिससे यह तय होता है कि कार्रवाई शुरू होने पर वह टूल कैसे काम करेगा.

सुविधाएं, Bazel ऐक्शन को यह सिग्नल देने के लिए कार्रवाइयों का रेफ़रंस देती हैं कि वे किन Bazel ऐक्शन पर असर डालती हैं. ऐसा इसलिए, क्योंकि कार्रवाइयां Bazel ऐक्शन ग्राफ़ में बदलाव कर सकती हैं. CcToolchainConfigInfo प्रोवाइडर में ऐसी कार्रवाइयां शामिल होती हैं जिनके साथ फ़्लैग और टूल जुड़े होते हैं. जैसे, c++-compile. हर कार्रवाई को फ़्लैग असाइन किए जाते हैं. इसके लिए, उन्हें किसी सुविधा से जोड़ा जाता है.

हर ऐक्शन का नाम, Bazel की ओर से की गई किसी एक तरह की कार्रवाई को दिखाता है. जैसे, कंपाइल करना या लिंक करना. हालांकि, कार्रवाइयों और Bazel ऐक्शन टाइप के बीच कई-से-एक का संबंध होता है. Bazel ऐक्शन टाइप, एक Java क्लास को कहते हैं, जो किसी कार्रवाई (जैसे कि CppCompileAction) को लागू करती है. खास तौर पर, नीचे दी गई टेबल में "असेंबलर ऐक्शन" और "कंपाइलर ऐक्शन" CppCompileAction हैं, जबकि लिंक ऐक्शन CppLinkAction हैं.

असेंबलर की कार्रवाइयां

कार्रवाई ब्यौरा
preprocess-assemble प्रीप्रोसेसिंग के साथ असेंबल करें. आम तौर पर, .S फ़ाइलों के लिए.
assemble प्रीप्रोसेसिंग के बिना असेंबल करें. आम तौर पर, .s फ़ाइलों के लिए.

कंपाइलर की कार्रवाइयां

कार्रवाई ब्यौरा
cc-flags-make-variable यह कुकी, CC_FLAGS को genrules पर भेजती है.
c-compile C. के तौर पर कंपाइल करें.
c++-compile C++ के तौर पर कंपाइल करें.
c++-header-parsing हेडर फ़ाइल पर कंपाइलर के पार्सर को चलाएं, ताकि यह पक्का किया जा सके कि हेडर में सभी ज़रूरी जानकारी मौजूद है. ऐसा न करने पर, कंपाइलेशन से जुड़ी गड़बड़ियां होंगी. यह सिर्फ़ उन टूलचेन पर लागू होता है जो मॉड्यूल के साथ काम करते हैं.
कार्रवाई ब्यौरा
c++-link-dynamic-library शेयर की गई लाइब्रेरी को लिंक करें, जिसमें उसकी सभी डिपेंडेंसी शामिल हों.
c++-link-nodeps-dynamic-library सिर्फ़ cc_library सोर्स वाली शेयर की गई लाइब्रेरी को लिंक करें.
c++-link-executable पहले से तैयार लाइब्रेरी को लिंक करें.

एआर ऐक्शन

AR कार्रवाइयां, ऑब्जेक्ट फ़ाइलों को संग्रह लाइब्रेरी (.a फ़ाइलें) में ar के ज़रिए इकट्ठा करती हैं. साथ ही, कुछ सिमैंटिक को नाम में एन्कोड करती हैं.

कार्रवाई ब्यौरा
c++-link-static-library स्टैटिक लाइब्रेरी (संग्रह) बनाएं.

एलटीओ से जुड़ी कार्रवाइयां

कार्रवाई ब्यौरा
lto-backend ThinLTO की मदद से, बिटकोड को नेटिव ऑब्जेक्ट में कंपाइल किया जाता है.
lto-index ThinLTO ऐक्शन, ग्लोबल इंडेक्स जनरेट कर रहा है.

action_config का इस्तेमाल करना

action_config एक Starlark स्ट्रक्चर है. यह Bazel ऐक्शन के बारे में बताता है. इसके लिए, यह ऐक्शन के दौरान टूल (बाइनरी) को शुरू करने और सुविधाओं के हिसाब से फ़्लैग के सेट को तय करता है. ये फ़्लैग, कार्रवाई को पूरा करने के लिए कुछ शर्तें लागू करते हैं.

action_config() कंस्ट्रक्टर में ये पैरामीटर होते हैं:

एट्रिब्यूट ब्यौरा
action_name यह कार्रवाई, Bazel की जिस कार्रवाई से जुड़ी है. Bazel इस एट्रिब्यूट का इस्तेमाल, हर कार्रवाई के लिए टूल और एक्ज़ीक्यूशन की ज़रूरी शर्तों का पता लगाने के लिए करता है.
tools लागू करने के लिए एक्ज़ीक्यूटेबल. कार्रवाई के लिए इस्तेमाल किया जाने वाला टूल, सूची में मौजूद पहला टूल होगा. इसमें सुविधाओं का ऐसा सेट होगा जो सुविधा के कॉन्फ़िगरेशन से मेल खाता हो. डिफ़ॉल्ट वैल्यू देना ज़रूरी है.
flag_sets फ़्लैग की सूची, जो कार्रवाइयों के ग्रुप पर लागू होती है. यह किसी सुविधा के लिए तय की गई सीमा के बराबर है.
env_sets यह एनवायरमेंट की उन पाबंदियों की सूची है जो कार्रवाइयों के ग्रुप पर लागू होती हैं. किसी सुविधा के लिए इस्तेमाल किए जाने वाले तरीके जैसा ही है.

सुविधाओं के संबंध के बारे में पहले बताया गया है. इसके मुताबिक, किसी action_config के लिए अन्य सुविधाएं और action_config ज़रूरी हो सकते हैं. यह सुविधा की तरह काम करता है.

आखिरी दो एट्रिब्यूट, सुविधाओं के हिसाब से काम के नहीं हैं. इन्हें इसलिए शामिल किया गया है, क्योंकि Bazel की कुछ कार्रवाइयों के लिए कुछ फ़्लैग या एनवायरमेंट वैरिएबल की ज़रूरत होती है. साथ ही, हमारा मकसद गैर-ज़रूरी action_config+feature पेयर से बचना है. आम तौर पर, एक ही फ़ीचर को कई action_config में शेयर करना बेहतर होता है.

एक ही टूलचेन में, एक ही action_name के लिए एक से ज़्यादा action_config तय नहीं किए जा सकते. इससे टूल पाथ में अस्पष्टता नहीं होती. साथ ही, action_config के पीछे के मकसद को लागू किया जाता है. इसका मतलब है कि टूलचेन में किसी कार्रवाई की प्रॉपर्टी के बारे में एक ही जगह पर साफ़ तौर पर बताया गया है.

टूल कंस्ट्रक्टर का इस्तेमाल करना

action_config पैरामीटर की मदद से, action_config टूल का सेट तय किया जा सकता है.tools tool() कंस्ट्रक्टर, इन पैरामीटर का इस्तेमाल करता है:

फ़ील्ड ब्यौरा
path सवाल में दिए गए टूल का पाथ (मौजूदा जगह के हिसाब से).
with_features सुविधाओं के सेट की सूची. इस टूल को लागू करने के लिए, इनमें से कम से कम एक सुविधा का इस्तेमाल करना ज़रूरी है.

किसी दिए गए action_config के लिए, सिर्फ़ एक tool, Bazel ऐक्शन पर टूल पाथ और एक्ज़ीक्यूशन से जुड़ी ज़रूरी शर्तें लागू करता है. किसी टूल को चुनने के लिए, action_config पर मौजूद tools एट्रिब्यूट को तब तक दोहराया जाता है, जब तक कि with_feature सेट वाला कोई ऐसा टूल न मिल जाए जो सुविधा के कॉन्फ़िगरेशन से मेल खाता हो. ज़्यादा जानकारी के लिए, इस पेज पर पहले सुविधाओं के बीच संबंध देखें. आपको टूल की सूचियों को ऐसे डिफ़ॉल्ट टूल के साथ खत्म करना चाहिए जो सुविधा के खाली कॉन्फ़िगरेशन से मेल खाता हो.

इस्तेमाल से जुड़ा उदाहरण

अलग-अलग प्लैटफ़ॉर्म के सिमैंटिक के साथ Bazel ऐक्शन लागू करने के लिए, सुविधाओं और ऐक्शन का एक साथ इस्तेमाल किया जा सकता है. उदाहरण के लिए, macOS पर डीबग सिंबल जनरेट करने के लिए, कंपाइल ऐक्शन में सिंबल जनरेट करने होते हैं. इसके बाद, लिंक ऐक्शन के दौरान किसी खास टूल को कॉल करके कंप्रेस किया गया dsym संग्रह बनाना होता है. इसके बाद, उस संग्रह को डीकंप्रेस करके ऐप्लिकेशन बंडल और Xcode के इस्तेमाल के लिए .plist फ़ाइलें बनानी होती हैं.

Bazel की मदद से, इस प्रोसेस को इस तरह लागू किया जा सकता है. इसमें unbundle-debuginfo, Bazel ऐक्शन है:

load("@rules_cc//cc:defs.bzl", "ACTION_NAMES")

action_configs = [
    action_config (
        action_name = ACTION_NAMES.cpp_link_executable,
        tools = [
            tool(
                with_features = [
                    with_feature(features=["generate-debug-symbols"]),
                ],
                path = "toolchain/mac/ld-with-dsym-packaging",
            ),
            tool (path = "toolchain/mac/ld"),
        ],
    ),
]

features = [
    feature(
        name = "generate-debug-symbols",
        flag_sets = [
            flag_set (
                actions = [
                    ACTION_NAMES.c_compile,
                    ACTION_NAMES.cpp_compile
                ],
                flag_groups = [
                    flag_group(
                        flags = ["-g"],
                    ),
                ],
            )
        ],
        implies = ["unbundle-debuginfo"],
   ),
]

इसी सुविधा को Linux के लिए पूरी तरह से अलग तरीके से लागू किया जा सकता है. Linux, fission का इस्तेमाल करता है. वहीं, Windows के लिए इसे अलग तरीके से लागू किया जा सकता है, जो .pdb फ़ाइलें बनाता है. उदाहरण के लिए, fission पर आधारित डीबग सिंबल जनरेट करने का तरीका ऐसा दिख सकता है:

load("@rules_cc//cc:defs.bzl", "ACTION_NAMES")

action_configs = [
    action_config (
        name = ACTION_NAMES.cpp_compile,
        tools = [
            tool(
                path = "toolchain/bin/gcc",
            ),
        ],
    ),
]

features = [
    feature (
        name = "generate-debug-symbols",
        requires = [with_feature_set(features = ["dbg"])],
        flag_sets = [
            flag_set(
                actions = [ACTION_NAMES.cpp_compile],
                flag_groups = [
                    flag_group(
                        flags = ["-gsplit-dwarf"],
                    ),
                ],
            ),
            flag_set(
                actions = [ACTION_NAMES.cpp_link_executable],
                flag_groups = [
                    flag_group(
                        flags = ["-Wl", "--gdb-index"],
                    ),
                ],
            ),
      ],
    ),
]

ग्रुप फ़्लैग करना

CcToolchainConfigInfo की मदद से, फ़्लैग को ऐसे ग्रुप में बंडल किया जा सकता है जो किसी खास मकसद को पूरा करते हैं. फ़्लैग वैल्यू में पहले से तय किए गए वैरिएबल का इस्तेमाल करके, फ़्लैग तय किया जा सकता है. कंपाइलर, बिल्ड कमांड में फ़्लैग जोड़ते समय इसे बड़ा करता है. उदाहरण के लिए:

flag_group (
    flags = ["%{output_execpath}"],
)

इस मामले में, फ़्लैग के कॉन्टेंट को कार्रवाई के आउटपुट फ़ाइल पाथ से बदल दिया जाएगा.

फ़्लैग ग्रुप को, सूची में दिखने के क्रम के हिसाब से बिल्ड कमांड में शामिल किया जाता है. यह क्रम ऊपर से नीचे और बाएं से दाएं होता है.

अगर किसी फ़्लैग को बिल्ड कमांड में जोड़ते समय, अलग-अलग वैल्यू के साथ दोहराना होता है, तो फ़्लैग ग्रुप, list टाइप के वैरिएबल को दोहरा सकता है. उदाहरण के लिए, list टाइप का वैरिएबल include_path:

flag_group (
    iterate_over = "include_paths",
    flags = ["-I%{include_paths}"],
)

include_paths सूची में मौजूद हर पाथ एलिमेंट के लिए, -I<path> में बदल जाता है. फ़्लैग ग्रुप के एलान के मुख्य हिस्से में मौजूद सभी फ़्लैग (या flag_group) को एक यूनिट के तौर पर बड़ा किया जाता है. उदाहरण के लिए:

flag_group (
    iterate_over = "include_paths",
    flags = ["-I", "%{include_paths}"],
)

include_paths सूची में मौजूद हर पाथ एलिमेंट के लिए, -I <path> में बदल जाता है.

कोई वैरिएबल कई बार दोहराया जा सकता है. उदाहरण के लिए:

flag_group (
    iterate_over = "include_paths",
    flags = ["-iprefix=%{include_paths}", "-isystem=%{include_paths}"],
)

बढ़कर इतनी हो जाती है:

-iprefix=<inc0> -isystem=<inc0> -iprefix=<inc1> -isystem=<inc1>

वैरिएबल, डॉट-नोटेशन का इस्तेमाल करके ऐक्सेस किए जा सकने वाले स्ट्रक्चर के मुताबिक हो सकते हैं. उदाहरण के लिए:

flag_group (
    flags = ["-l%{libraries_to_link.name}"],
)

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

flag_group (
    iterate_over = "libraries_to_link",
    flag_groups = [
        flag_group (
            iterate_over = "libraries_to_link.shared_libraries",
            flags = ["-l%{libraries_to_link.shared_libraries.name}"],
        ),
    ],
)

शर्त के हिसाब से फ़ंक्शन को बड़ा करना

expand_if_available, expand_if_not_available, expand_if_true, expand_if_false या expand_if_equal एट्रिब्यूट का इस्तेमाल करके, किसी खास वैरिएबल या उसके फ़ील्ड की मौजूदगी के आधार पर, फ़्लैग ग्रुप को शर्तों के मुताबिक बड़ा किया जा सकता है. उदाहरण के लिए:

flag_group (
    iterate_over = "libraries_to_link",
    flag_groups = [
        flag_group (
            iterate_over = "libraries_to_link.shared_libraries",
            flag_groups = [
                flag_group (
                    expand_if_available = "libraries_to_link.shared_libraries.is_whole_archive",
                    flags = ["--whole_archive"],
                ),
                flag_group (
                    flags = ["-l%{libraries_to_link.shared_libraries.name}"],
                ),
                flag_group (
                    expand_if_available = "libraries_to_link.shared_libraries.is_whole_archive",
                    flags = ["--no_whole_archive"],
                ),
            ],
        ),
    ],
)

CcToolchainConfigInfo का रेफ़रंस

इस सेक्शन में, C++ नियमों को सही तरीके से कॉन्फ़िगर करने के लिए ज़रूरी जानकारी दी गई है. जैसे, बिल्ड वैरिएबल, सुविधाएं, और अन्य जानकारी.

CcToolchainConfigInfo के बिल्ड वैरिएबल

यहां CcToolchainConfigInfo बिल्ड वैरिएबल का रेफ़रंस दिया गया है.

वैरिएबल कार्रवाई ब्यौरा
source_file कंपाइल करें कंपाइल करने के लिए सोर्स फ़ाइल.
input_file स्ट्रिप स्ट्रिप करने के लिए आर्टफ़ैक्ट.
output_file कंपाइल करें, स्ट्रिप करें कंपाइलेशन का आउटपुट.
output_assembly_file कंपाइल करें असेंबली फ़ाइल भेजी गई. यह सिर्फ़ तब लागू होता है, जब compile कार्रवाई से असेंबली टेक्स्ट मिलता है. आम तौर पर, ऐसा --save_temps फ़्लैग का इस्तेमाल करते समय होता है. कॉन्टेंट, output_file के कॉन्टेंट जैसा ही है.
output_preprocess_file कंपाइल करें प्रीप्रोसेस किया गया आउटपुट. यह सिर्फ़ कंपाइल करने की उन कार्रवाइयों पर लागू होता है जो सिर्फ़ सोर्स फ़ाइलों को प्रीप्रोसेस करती हैं. आम तौर पर, ऐसा --save_temps फ़्लैग का इस्तेमाल करते समय होता है. कॉन्टेंट, output_file के कॉन्टेंट जैसा ही है.
includes कंपाइल करें फ़ाइलों का क्रम, जिसे कंपाइलर को कंपाइल किए गए सोर्स में शामिल करना होगा.
include_paths कंपाइल करें उन डायरेक्ट्री का क्रम जिनमें कंपाइलर, #include<foo.h> और #include "foo.h" का इस्तेमाल करके शामिल किए गए हेडर खोजता है.
quote_include_paths कंपाइल करें -iquote का क्रम - ऐसी डायरेक्ट्री जिनमें कंपाइलर, #include "foo.h" का इस्तेमाल करके शामिल किए गए हेडर ढूंढता है.
system_include_paths कंपाइल करें -isystem का क्रम - ऐसी डायरेक्ट्री जिनमें कंपाइलर, #include <foo.h> का इस्तेमाल करके शामिल किए गए हेडर ढूंढता है.
dependency_file कंपाइल करें यह .d डिपेंडेंसी फ़ाइल है, जिसे कंपाइलर ने जनरेट किया है.
preprocessor_defines कंपाइल करें defines का क्रम, जैसे कि --DDEBUG.
pic कंपाइल करें आउटपुट को पोज़िशन-इंडिपेंडेंट कोड के तौर पर कंपाइल करता है.
gcov_gcno_file कंपाइल करें gcov कवरेज फ़ाइल.
per_object_debug_info_file कंपाइल करें हर ऑब्जेक्ट के लिए डीबग की जानकारी (.dwp) वाली फ़ाइल.
stripopts स्ट्रिप stripopts का क्रम.
legacy_compile_flags कंपाइल करें लेगसी CROSSTOOL फ़ील्ड से मिले फ़्लैग का क्रम, जैसे कि compiler_flag, optional_compiler_flag, cxx_flag, और optional_cxx_flag.
user_compile_flags कंपाइल करें copt नियम एट्रिब्यूट या --copt, --cxxopt, और --conlyopt फ़्लैग में से किसी एक से फ़्लैग का क्रम.
unfiltered_compile_flags कंपाइल करें unfiltered_cxx_flagलेगसीCROSSTOOL फ़ील्ड या unfiltered_compile_flagsसुविधा से फ़्लैग का क्रम. इन्हें nocopts नियम एट्रिब्यूट के हिसाब से फ़िल्टर नहीं किया जाता.
sysroot sysroot.
runtime_library_search_directories लिंक लिंकर के रनटाइम सर्च पाथ में मौजूद एंट्री (आम तौर पर, इसे -rpath फ़्लैग के साथ सेट किया जाता है).
library_search_directories लिंक लिंकर सर्च पाथ में मौजूद एंट्री (आम तौर पर, -L फ़्लैग के साथ सेट की जाती हैं).
libraries_to_link लिंक लिंकर इनवोकेशन में इनपुट के तौर पर लिंक करने के लिए फ़ाइलें उपलब्ध कराने वाले फ़्लैग.
def_file_path लिंक MSVC के साथ Windows पर इस्तेमाल की गई def फ़ाइल की जगह.
linker_param_file लिंक लिंकर पैरामीटर फ़ाइल की जगह. इसे Bazel ने कमांड लाइन की लंबाई की सीमा को पूरा करने के लिए बनाया है.
output_execpath लिंक लिंकर के आउटपुट का Execpath.
generate_interface_library लिंक "yes" या "no", इस आधार पर कि इंटरफ़ेस लाइब्रेरी जनरेट की जानी चाहिए या नहीं.
interface_library_builder_path लिंक इंटरफ़ेस लाइब्रेरी बिल्डर टूल का पाथ.
interface_library_input_path लिंक इंटरफ़ेस लाइब्रेरी ifso बिल्डर टूल के लिए इनपुट.
interface_library_output_path लिंक वह पाथ जहां ifso बिल्डर टूल का इस्तेमाल करके इंटरफ़ेस लाइब्रेरी जनरेट की जाती है.
legacy_link_flags लिंक लेगसी CROSSTOOL फ़ील्ड से मिलने वाले लिंकर फ़्लैग.
user_link_flags लिंक --linkopt या linkopts एट्रिब्यूट से मिलने वाले लिंकर फ़्लैग.
linkstamp_paths लिंक यह एक बिल्ड वैरिएबल है, जो लिंकस्टैंप के पाथ देता है.
force_pic लिंक इस वैरिएबल के मौजूद होने का मतलब है कि PIC/PIE कोड जनरेट किया जाना चाहिए. Bazel विकल्प `--force_pic` पास किया गया था.
strip_debug_symbols लिंक इस वैरिएबल के मौजूद होने से पता चलता है कि डीबग सिंबल हटाए जाने चाहिए.
is_cc_test लिंक अगर मौजूदा कार्रवाई cc_test लिंक करने की कार्रवाई है, तो यह वैल्यू सही होती है. ऐसा न होने पर, यह वैल्यू गलत होती है.
is_using_fission कंपाइल, लिंक इस वैरिएबल की मौजूदगी से पता चलता है कि फ़िशन (हर ऑब्जेक्ट के लिए डीबग करने की जानकारी) चालू है. डीबग करने से जुड़ी जानकारी, .o फ़ाइलों के बजाय .dwo फ़ाइलों में होगी. साथ ही, कंपाइलर और लिंकर को इस बारे में पता होना चाहिए.
fdo_instrument_path कंपाइल, लिंक उस डायरेक्ट्री का पाथ जिसमें FDO इंस्ट्रुमेंटेशन प्रोफ़ाइल सेव की जाती है.
fdo_profile_path कंपाइल करें FDO प्रोफ़ाइल का पाथ.
fdo_prefetch_hints_path कंपाइल करें कैश मेमोरी प्रीफ़ेच प्रोफ़ाइल का पाथ.
cs_fdo_instrument_path कंपाइल, लिंक उस डायरेक्ट्री का पाथ जिसमें कॉन्टेक्स्ट के हिसाब से काम करने वाली FDO इंस्ट्रुमेंटेशन प्रोफ़ाइल सेव की जाती है.

मशहूर सुविधाएं

यहां सुविधाओं और उन्हें चालू करने की शर्तों के बारे में बताया गया है.

सुविधा दस्तावेज़ के रूप में
opt | dbg | fastbuild कंपाइलेशन मोड के आधार पर, डिफ़ॉल्ट रूप से चालू होता है.
static_linking_mode | dynamic_linking_mode लिंक करने के मोड के आधार पर, डिफ़ॉल्ट रूप से चालू होती है.
per_object_debug_info यह तब चालू होता है, जब supports_fission सुविधा के बारे में बताया गया हो और उसे चालू किया गया हो. साथ ही, --fission फ़्लैग में मौजूदा कंपाइलेशन मोड के बारे में बताया गया हो.
supports_start_end_lib अगर यह विकल्प चालू है और --start_end_lib विकल्प सेट है, तो Bazel स्टैटिक लाइब्रेरी के साथ लिंक नहीं करेगा. इसके बजाय, वह ऑब्जेक्ट के साथ सीधे लिंक करने के लिए --start-lib/--end-lib लिंकर विकल्पों का इस्तेमाल करेगा. इससे बिल्ड की प्रोसेस तेज़ हो जाती है, क्योंकि Bazel को स्टैटिक लाइब्रेरी बनाने की ज़रूरत नहीं होती.
supports_interface_shared_libraries अगर यह सुविधा चालू है और --interface_shared_objects विकल्प सेट है, तो Bazel उन टारगेट को लिंक करेगा जिनके लिए linkstatic को False (डिफ़ॉल्ट रूप से cc_test) पर सेट किया गया है. ऐसा इंटरफ़ेस शेयर की गई लाइब्रेरी के ख़िलाफ़ किया जाएगा. इससे इंक्रीमेंटल रिलिंकिंग की प्रोसेस तेज़ हो जाती है.
supports_dynamic_linker इस विकल्प के चालू होने पर, C++ के नियमों को पता चल जाएगा कि टूलचेन, शेयर की गई लाइब्रेरी बना सकता है.
static_link_cpp_runtimes यह सुविधा चालू होने पर, Bazel स्टैटिक लिंकिंग मोड में C++ रनटाइम को स्टैटिक तौर पर और डाइनैमिक लिंकिंग मोड में डाइनैमिक तौर पर लिंक करेगा. cc_toolchain.static_runtime_lib या cc_toolchain.dynamic_runtime_lib एट्रिब्यूट में बताए गए आर्टफ़ैक्ट (लिंक करने के मोड के आधार पर) को लिंक करने की कार्रवाइयों में जोड़ दिया जाएगा.
supports_pic इस विकल्प को चालू करने पर, टूलचेन को यह पता चल जाएगा कि उसे डाइनैमिक लाइब्रेरी के लिए पीआईसी ऑब्जेक्ट का इस्तेमाल करना है. जब भी पीआईसी कंपाइलेशन की ज़रूरत होती है, तब `pic` वैरिएबल मौजूद होता है. अगर यह सुविधा डिफ़ॉल्ट रूप से चालू नहीं है और `--force_pic` पास किया गया है, तो Bazel `supports_pic` का अनुरोध करेगा. साथ ही, यह पुष्टि करेगा कि सुविधा चालू है. अगर सुविधा मौजूद नहीं है या उसे चालू नहीं किया जा सका, तो `--force_pic` का इस्तेमाल नहीं किया जा सकता.
static_linking_mode | dynamic_linking_mode लिंक करने के मोड के आधार पर, डिफ़ॉल्ट रूप से चालू होती है.
no_legacy_features अगर C++ कॉन्फ़िगरेशन मौजूद है, तो Bazel को उसमें लेगसी सुविधाएं जोड़ने से रोकता है. सुविधाओं की पूरी सूची यहां दी गई है.
shorten_virtual_includes यह सुविधा चालू होने पर, वर्चुअल इंक्लूड हेडर फ़ाइलें bin/<target package path>/_virtual_includes/<target name> के बजाय bin/_virtual_includes/<hash of target path> में लिंक की जाती हैं. MSVC के साथ लंबे पाथ की समस्या से बचने के लिए, Windows पर यह विकल्प काम का है.

लेगसी सुविधाओं के लिए पैचिंग लॉजिक

Bazel, पुराने सिस्टम के साथ काम करने की सुविधा के लिए, टूलचेन की सुविधाओं में ये बदलाव करता है:

  • legacy_compile_flags सुविधा को टूलचेन में सबसे ऊपर ले जाता है
  • default_compile_flags सुविधा को टूलचेन में सबसे ऊपर ले जाता है
  • अगर टूलचेन में dependency_file मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में pic मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में per_object_debug_info मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में preprocessor_defines मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में includes मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में include_paths मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में fdo_instrument मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में fdo_optimize मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में cs_fdo_instrument मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में cs_fdo_optimize मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में fdo_prefetch_hints मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में autofdo मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में build_interface_libraries मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में dynamic_library_linker_tool मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में shared_flag मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में linkstamps मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में output_execpath_flags मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में runtime_library_search_directories मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में library_search_directories मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में archiver_flags मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में libraries_to_link मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में force_pic_flags मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में user_link_flags मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में legacy_link_flags मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में static_libgcc मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में fission_support मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में strip_debug_symbols मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में coverage मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में llvm_coverage_map_format मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • अगर टूलचेन में gcc_coverage_map_format मौजूद नहीं है, तो उसे टूलचेन में सबसे ऊपर जोड़ता है
  • यह टूलचेन के सबसे नीचे fully_static_link (अगर मौजूद नहीं है) सुविधा जोड़ता है
  • यह टूलचेन के सबसे नीचे user_compile_flags (अगर मौजूद नहीं है) सुविधा जोड़ता है
  • यह टूलचेन के सबसे नीचे sysroot (अगर मौजूद नहीं है) सुविधा जोड़ता है
  • यह टूलचेन के सबसे नीचे unfiltered_compile_flags (अगर मौजूद नहीं है) सुविधा जोड़ता है
  • यह टूलचेन के सबसे नीचे linker_param_file (अगर मौजूद नहीं है) सुविधा जोड़ता है
  • यह टूलचेन के सबसे नीचे compiler_input_flags (अगर मौजूद नहीं है) सुविधा जोड़ता है
  • यह टूलचेन के सबसे नीचे compiler_output_flags (अगर मौजूद नहीं है) सुविधा जोड़ता है

यह सुविधाओं की लंबी सूची है. Crosstool in Starlark के पूरा होने के बाद, इन्हें हटा दिया जाएगा. ज़्यादा जानकारी पाने के लिए, CppActionConfigs में लागू करने का तरीका देखें. साथ ही, प्रोडक्शन टूलचेन के लिए no_legacy_features जोड़ने पर विचार करें, ताकि टूलचेन को ज़्यादा स्टैंडअलोन बनाया जा सके.