इस पेज पर, टूलचेन फ़्रेमवर्क के बारे में बताया गया है. इसकी मदद से, नियम लिखने वाले लोग, टूल के प्लैटफ़ॉर्म के हिसाब से चुने जाने की प्रोसेस से, अपने नियम की लॉजिक को अलग कर सकते हैं. हमारा सुझाव है कि आगे बढ़ने से पहले, नियमों और प्लैटफ़ॉर्म के बारे में जानकारी देने वाले पेज पढ़ लें. इस पेज पर, टूलचेन की ज़रूरत क्यों होती है, उन्हें कैसे तय किया जाता है और उनका इस्तेमाल कैसे किया जाता है, और प्लैटफ़ॉर्म की पाबंदियों के आधार पर Bazel, सही टूलचेन कैसे चुनता है, इस बारे में बताया गया है.
वजह
सबसे पहले, उस समस्या के बारे में जानते हैं जिसे हल करने के लिए टूलचेन बनाए गए हैं. मान लें कि "बार" प्रोग्रामिंग भाषा के लिए नियम लिखे जा रहे हैं. आपका bar_binary नियम, barc कंपाइलर का इस्तेमाल करके *.bar फ़ाइलें कंपाइल करेगा. यह टूल, आपके वर्कस्पेस में किसी दूसरे टारगेट के तौर पर बनाया जाता है. bar_binary टारगेट लिखने वाले उपयोगकर्ताओं को कंपाइलर पर डिपेंडेंसी तय नहीं करनी चाहिए. इसलिए, इसे नियम की डेफ़िनिशन में एक निजी एट्रिब्यूट के तौर पर जोड़कर, इसे इंप्लिसिट डिपेंडेंसी बनाएं.
bar_binary = rule(
implementation = _bar_binary_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
...
"_compiler": attr.label(
default = "//bar_tools:barc_linux", # the compiler running on linux
providers = [BarcInfo],
),
},
)
//bar_tools:barc_linux अब हर bar_binary टारगेट की डिपेंडेंसी है. इसलिए, इसे किसी भी bar_binary टारगेट से पहले बनाया जाएगा. इसे नियम के लागू करने वाले फ़ंक्शन से, किसी अन्य एट्रिब्यूट की तरह ही ऐक्सेस किया जा सकता है:
BarcInfo = provider(
doc = "Information about how to invoke the barc compiler.",
# In the real world, compiler_path and system_lib might hold File objects,
# but for simplicity they are strings for this example. arch_flags is a list
# of strings.
fields = ["compiler_path", "system_lib", "arch_flags"],
)
def _bar_binary_impl(ctx):
...
info = ctx.attr._compiler[BarcInfo]
command = "%s -l %s %s" % (
info.compiler_path,
info.system_lib,
" ".join(info.arch_flags),
)
...
यहां समस्या यह है कि कंपाइलर का लेबल, bar_binary में हार्डकोड किया गया है. हालांकि, अलग-अलग टारगेट के लिए अलग-अलग कंपाइलर की ज़रूरत पड़ सकती है. यह इस बात पर निर्भर करता है कि उन्हें किस प्लैटफ़ॉर्म के लिए बनाया जा रहा है और किस प्लैटफ़ॉर्म पर बनाया जा रहा है. इन्हें क्रमशः टारगेट प्लैटफ़ॉर्म और एक्ज़ीक्यूशन प्लैटफ़ॉर्म कहा जाता है. इसके अलावा, नियम लिखने वाले व्यक्ति को उपलब्ध सभी टूल और प्लैटफ़ॉर्म के बारे में जानकारी नहीं होती. इसलिए, नियम की डेफ़िनिशन में उन्हें हार्डकोड करना मुमकिन नहीं है.
एक कम असरदार तरीका यह होगा कि _compiler एट्रिब्यूट को निजी न बनाकर, उपयोगकर्ताओं पर ज़िम्मेदारी डाल दी जाए. इसके बाद, अलग-अलग टारगेट को किसी एक प्लैटफ़ॉर्म के लिए हार्डकोड किया जा सकता है.
bar_binary(
name = "myprog_on_linux",
srcs = ["mysrc.bar"],
compiler = "//bar_tools:barc_linux",
)
bar_binary(
name = "myprog_on_windows",
srcs = ["mysrc.bar"],
compiler = "//bar_tools:barc_windows",
)
select का इस्तेमाल करके, प्लैटफ़ॉर्म के आधार पर compiler
चुनकर, इस तरीके को बेहतर बनाया जा सकता है:
config_setting(
name = "on_linux",
constraint_values = [
"@platforms//os:linux",
],
)
config_setting(
name = "on_windows",
constraint_values = [
"@platforms//os:windows",
],
)
bar_binary(
name = "myprog",
srcs = ["mysrc.bar"],
compiler = select({
":on_linux": "//bar_tools:barc_linux",
":on_windows": "//bar_tools:barc_windows",
}),
)
हालांकि, यह मुश्किल है और हर bar_binary उपयोगकर्ता से ऐसा करने के लिए कहना सही नहीं है.
अगर इस स्टाइल का इस्तेमाल, पूरे वर्कस्पेस में एक जैसा नहीं किया जाता है, तो ऐसे बिल्ड तैयार होते हैं जो किसी एक प्लैटफ़ॉर्म पर तो ठीक से काम करते हैं, लेकिन मल्टी-प्लैटफ़ॉर्म वाले सिनेरियो में काम नहीं करते. साथ ही, इससे मौजूदा नियमों या टारगेट में बदलाव किए बिना, नए प्लैटफ़ॉर्म और कंपाइलर के लिए सहायता जोड़ने की समस्या भी हल नहीं होती.
टूलचेन फ़्रेमवर्क, इनडायरेक्शन का एक और लेवल जोड़कर इस समस्या को हल करता है. असल में, आपको यह एलान करना होता है कि आपके नियम में, टारगेट के किसी ग्रुप (टूलचेन टाइप) के किसी सदस्य पर ऐब्स्ट्रैक्ट डिपेंडेंसी है. इसके बाद, Bazel, लागू होने वाली प्लैटफ़ॉर्म की पाबंदियों के आधार पर, इसे किसी खास टारगेट (टूलचेन) में अपने-आप बदल देता है. नियम लिखने वाले व्यक्ति और टारगेट लिखने वाले व्यक्ति, दोनों को उपलब्ध प्लैटफ़ॉर्म और टूलचेन के पूरे सेट के बारे में जानकारी नहीं होनी चाहिए.
टूलचेन का इस्तेमाल करने वाले नियम लिखना
टूलचेन फ़्रेमवर्क के तहत, नियमों को सीधे टूल पर डिपेंड करने के बजाय, टूलचेन टाइप पर डिपेंड किया जाता है. टूलचेन टाइप एक सामान्य टारगेट होता है. यह टूल के ऐसे क्लास को दिखाता है जो अलग-अलग प्लैटफ़ॉर्म के लिए एक ही भूमिका निभाते हैं. उदाहरण के लिए, बार कंपाइलर को दिखाने वाला टाइप तय किया जा सकता है:
# By convention, toolchain_type targets are named "toolchain_type" and
# distinguished by their package path. So the full path for this would be
# //bar_tools:toolchain_type.
toolchain_type(name = "toolchain_type")
पिछले सेक्शन में दिए गए नियम की डेफ़िनिशन में बदलाव किया गया है. अब यह कंपाइलर को एट्रिब्यूट के तौर पर लेने के बजाय, यह एलान करता है कि यह //bar_tools:toolchain_type टूलचेन का इस्तेमाल करता है.
bar_binary = rule(
implementation = _bar_binary_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
...
# No `_compiler` attribute anymore.
},
toolchains = ["//bar_tools:toolchain_type"],
)
लागू करने वाला फ़ंक्शन अब इस डिपेंडेंसी को ctx.attr के बजाय ctx.toolchains में ऐक्सेस करता है. इसके लिए, टूलचेन टाइप को कुंजी के तौर पर इस्तेमाल किया जाता है.
def _bar_binary_impl(ctx):
...
info = ctx.toolchains["//bar_tools:toolchain_type"].barcinfo
# The rest is unchanged.
command = "%s -l %s %s" % (
info.compiler_path,
info.system_lib,
" ".join(info.arch_flags),
)
...
ctx.toolchains["//bar_tools:toolchain_type"] उस टारगेट का
ToolchainInfo प्रोवाइडर
दिखाता है जिसके लिए Bazel ने टूलचेन डिपेंडेंसी को हल किया है. ToolchainInfo ऑब्जेक्ट के फ़ील्ड, उसके लिए बने नियम से सेट किए जाते हैं. अगले सेक्शन में, इस नियम को इस तरह तय किया गया है कि इसमें barcinfo फ़ील्ड हो. यह BarcInfo ऑब्जेक्ट को रैप करता है.
टारगेट के लिए टूलचेन को हल करने की Bazel की प्रोसेस के बारे में यहां बताया गया है
यहां. हल किए गए टूलचेन टारगेट को ही bar_binary टारगेट की डिपेंडेंसी बनाया जाता है. संभावित टूलचेन के पूरे स्पेस को नहीं.
ज़रूरी और वैकल्पिक टूलचेन
डिफ़ॉल्ट रूप से, जब कोई नियम, सामान्य लेबल का इस्तेमाल करके टूलचेन टाइप डिपेंडेंसी दिखाता है (जैसा कि ऊपर दिखाया गया है), तो टूलचेन टाइप को ज़रूरी माना जाता है. अगर Bazel , ज़रूरी टूलचेन टाइप के लिए मैचिंग टूलचेन नहीं ढूंढ पाता है, तो यह एक गड़बड़ी है और विश्लेषण रुक जाता है. टूलचेन को हल करने की प्रोसेस के बारे में नीचे बताया गया है (टूलचेन को हल करने की प्रोसेस देखें).
इसके बजाय, वैकल्पिक टूलचेन टाइप डिपेंडेंसी का एलान किया जा सकता है. इसके लिए, यह तरीका अपनाएं:
bar_binary = rule(
...
toolchains = [
config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False),
],
)
जब किसी वैकल्पिक टूलचेन टाइप को हल नहीं किया जा सकता, तो विश्लेषण जारी रहता है. साथ ही, का नतीजा ctx.toolchains["//bar_tools:toolchain_type"] None होता है.
The config_common.toolchain_type
फ़ंक्शन, डिफ़ॉल्ट रूप से ज़रूरी होता है.
इन फ़ॉर्म का इस्तेमाल किया जा सकता है:
- ज़रूरी टूलचेन टाइप:
toolchains = ["//bar_tools:toolchain_type"]toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type")]toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = True)]
- वैकल्पिक टूलचेन टाइप:
toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False)]
bar_binary = rule(
...
toolchains = [
"//foo_tools:toolchain_type",
config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False),
],
)
एक ही नियम में, अलग-अलग फ़ॉर्म को मिक्स और मैच भी किया जा सकता है. हालांकि, अगर एक ही टूलचेन टाइप को कई बार सूची में शामिल किया जाता है, तो सबसे सख्त वर्शन लागू होगा. इसमें, ज़रूरी को वैकल्पिक से ज़्यादा सख्त माना जाता है.
टूलचेन का इस्तेमाल करने वाले आसपेक्ट लिखना
आसपेक्ट के पास, नियमों के जैसा ही टूलचेन एपीआई का ऐक्सेस होता है. इसमें, ज़रूरी टूलचेन टाइप तय किए जा सकते हैं, कॉन्टेक्स्ट के ज़रिए टूलचेन को ऐक्सेस किया जा सकता है, और टूलचेन का इस्तेमाल करके नई कार्रवाइयां जनरेट की जा सकती हैं.
bar_aspect = aspect(
implementation = _bar_aspect_impl,
attrs = {},
toolchains = ['//bar_tools:toolchain_type'],
)
def _bar_aspect_impl(target, ctx):
toolchain = ctx.toolchains['//bar_tools:toolchain_type']
# Use the toolchain provider like in a rule.
return []
टूलचेन तय करना
किसी दिए गए टूलचेन टाइप के लिए कुछ टूलचेन तय करने के लिए, आपको इन तीन चीज़ों की ज़रूरत होती है:
भाषा के हिसाब से कोई नियम. यह नियम, टूल या टूल सुइट के टाइप को दिखाता है. आम तौर पर, इस नियम के नाम के आखिर में "_toolchain" जोड़ा जाता है.
- ध्यान दें:
\_toolchainनियम, कोई भी बिल्ड ऐक्शन नहीं बना सकता. इसके बजाय, यह अन्य नियमों से आर्टफ़ैक्ट इकट्ठा करता है और उन्हें उस नियम को फ़ॉरवर्ड करता है जो टूलचेन का इस्तेमाल करता है. सभी बिल्ड ऐक्शन बनाने की ज़िम्मेदारी उस नियम की होती है.
- ध्यान दें:
इस नियम टाइप के कई टारगेट. ये टारगेट, अलग-अलग प्लैटफ़ॉर्म के लिए टूल या टूल सुइट के वर्शन दिखाते हैं.
ऐसे हर टारगेट के लिए, सामान्य
toolchainनियम का कोई टारगेट. इससे टूलचेन फ़्रेमवर्क के इस्तेमाल किए जाने वाले मेटाडेटा की जानकारी मिलती है. यहtoolchainटारगेट, इस टूलचेन से जुड़ेtoolchain_typeको भी दिखाता है. इसका मतलब है कि किसी_toolchainनियम को किसी भीtoolchain_typeसे जोड़ा जा सकता है. साथ ही, सिर्फ़toolchainइंस्टेंस में, इस_toolchainनियम का इस्तेमाल करने वाले नियम कोtoolchain_typeसे जोड़ा जाता है.
हमारे उदाहरण के लिए, यहां bar_toolchain नियम की डेफ़िनिशन दी गई है. हमारे उदाहरण में सिर्फ़ एक कंपाइलर है. हालांकि, इसके तहत लिंकर जैसे अन्य टूल भी ग्रुप किए जा सकते हैं.
def _bar_toolchain_impl(ctx):
toolchain_info = platform_common.ToolchainInfo(
barcinfo = BarcInfo(
compiler_path = ctx.attr.compiler_path,
system_lib = ctx.attr.system_lib,
arch_flags = ctx.attr.arch_flags,
),
)
return [toolchain_info]
bar_toolchain = rule(
implementation = _bar_toolchain_impl,
attrs = {
"compiler_path": attr.string(),
"system_lib": attr.string(),
"arch_flags": attr.string_list(),
},
)
नियम से ToolchainInfo प्रोवाइडर दिखना चाहिए. यह वह ऑब्जेक्ट होता है जिसे इस्तेमाल करने वाला नियम, ctx.toolchains और टूलचेन टाइप के लेबल का इस्तेमाल करके वापस पाता है. ToolchainInfo, struct की तरह, फ़ील्ड-वैल्यू के जोड़े को सेव कर सकता है. ToolchainInfo में कौनसे फ़ील्ड जोड़े जाते हैं, इसकी जानकारी टूलचेन टाइप में साफ़ तौर पर दी जानी चाहिए. इस उदाहरण में, ऊपर तय किए गए स्कीमा का फिर से इस्तेमाल करने के लिए, वैल्यू को BarcInfo ऑब्जेक्ट में रैप करके दिखाया जाता है. यह स्टाइल, पुष्टि करने और कोड का फिर से इस्तेमाल करने के लिए काम की हो सकती है.
अब खास barc कंपाइलर के लिए टारगेट तय किए जा सकते हैं.
bar_toolchain(
name = "barc_linux",
arch_flags = [
"--arch=Linux",
"--debug_everything",
],
compiler_path = "/path/to/barc/on/linux",
system_lib = "/usr/lib/libbarc.so",
)
bar_toolchain(
name = "barc_windows",
arch_flags = [
"--arch=Windows",
# Different flags, no debug support on windows.
],
compiler_path = "C:\\path\\on\\windows\\barc.exe",
system_lib = "C:\\path\\on\\windows\\barclib.dll",
)
आखिर में, दो bar_toolchain टारगेट के लिए toolchain डेफ़िनिशन बनाएं.
इन डेफ़िनिशन से, भाषा के हिसाब से टारगेट को टूलचेन टाइप से लिंक किया जाता है. साथ ही, पाबंदी की जानकारी दी जाती है. इससे Bazel को यह पता चलता है कि किसी दिए गए प्लैटफ़ॉर्म के लिए टूलचेन कब सही है.
toolchain(
name = "barc_linux_toolchain",
exec_compatible_with = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
target_compatible_with = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
toolchain = ":barc_linux",
toolchain_type = ":toolchain_type",
)
toolchain(
name = "barc_windows_toolchain",
exec_compatible_with = [
"@platforms//os:windows",
"@platforms//cpu:x86_64",
],
target_compatible_with = [
"@platforms//os:windows",
"@platforms//cpu:x86_64",
],
toolchain = ":barc_windows",
toolchain_type = ":toolchain_type",
)
ऊपर दिए गए उदाहरण में, रिलेटिव पाथ सिंटैक्स का इस्तेमाल करने से पता चलता है कि ये सभी डेफ़िनिशन एक ही पैकेज में हैं. हालांकि, टूलचेन टाइप, भाषा के हिसाब से टूलचेन टारगेट, और toolchain डेफ़िनिशन टारगेट, सभी अलग-अलग पैकेज में हो सकते हैं.
असल दुनिया के उदाहरण के लिए, go_toolchain
देखें.
टूलचेन और कॉन्फ़िगरेशन
नियम लिखने वाले लोगों के लिए एक अहम सवाल यह है कि जब bar_toolchain टारगेट का
विश्लेषण किया जाता है, तो यह कौनसा कॉन्फ़िगरेशन देखता है. साथ ही, डिपेंडेंसी के लिए किन ट्रांज़िशन का
इस्तेमाल किया जाना चाहिए? ऊपर दिए गए उदाहरण में स्ट्रिंग एट्रिब्यूट का इस्तेमाल किया गया है. हालांकि, Bazel रिपॉज़िटरी में मौजूद अन्य टारगेट पर डिपेंड करने वाले ज़्यादा जटिल टूलचेन के लिए क्या होगा?
bar_toolchain का ज़्यादा जटिल वर्शन देखते हैं:
def _bar_toolchain_impl(ctx):
# The implementation is mostly the same as above, so skipping.
pass
bar_toolchain = rule(
implementation = _bar_toolchain_impl,
attrs = {
"compiler": attr.label(
executable = True,
mandatory = True,
cfg = "exec",
),
"system_lib": attr.label(
mandatory = True,
cfg = "target",
),
"arch_flags": attr.string_list(),
},
)
attr.label का इस्तेमाल, स्टैंडर्ड नियम के लिए किए जाने वाले इस्तेमाल जैसा ही है.
हालांकि, cfg पैरामीटर का मतलब थोड़ा अलग है.
टूलचेन को हल करने की प्रोसेस के ज़रिए, किसी टारगेट (जिसे "पैरंट" कहा जाता है) से टूलचेन तक की डिपेंडेंसी, "टूलचेन ट्रांज़िशन" नाम के खास कॉन्फ़िगरेशन ट्रांज़िशन का इस्तेमाल करती है. टूलचेन ट्रांज़िशन, कॉन्फ़िगरेशन को एक जैसा रखता है. हालांकि, यह टूलचेन और पैरंट के लिए, एक्ज़ीक्यूशन प्लैटफ़ॉर्म को एक जैसा रखता है. ऐसा न होने पर, टूलचेन को हल करने की प्रोसेस के ज़रिए, टूलचेन के लिए कोई भी एक्ज़ीक्यूशन प्लैटफ़ॉर्म चुना जा सकता है. साथ ही, यह ज़रूरी नहीं है कि यह प्लैटफ़ॉर्म, पैरंट के लिए इस्तेमाल किए जाने वाले प्लैटफ़ॉर्म जैसा ही हो. इससे, टूलचेन की exec डिपेंडेंसी को पैरंट के बिल्ड ऐक्शन के लिए भी एक्ज़ीक्यूट किया जा सकता है. टूलचेन की ऐसी कोई भी डिपेंडेंसी जो cfg =
"target" का इस्तेमाल करती है (या जो cfg तय नहीं करती, क्योंकि "target" डिफ़ॉल्ट है), उसे
पैरंट के जैसे ही टारगेट प्लैटफ़ॉर्म के लिए बनाया जाता है. इससे, टूलचेन के नियम, बिल्ड के उन नियमों में लाइब्रेरी (system_lib एट्रिब्यूट) और टूल (compiler एट्रिब्यूट) दोनों को शामिल कर सकते हैं जिनकी उन्हें ज़रूरत होती है. सिस्टम लाइब्रेरी को फ़ाइनल आर्टफ़ैक्ट में लिंक किया जाता है. इसलिए, उन्हें एक ही प्लैटफ़ॉर्म के लिए बनाया जाना चाहिए. वहीं, कंपाइलर एक ऐसा टूल है जिसे बिल्ड के दौरान इस्तेमाल किया जाता है. इसलिए, यह एक्ज़ीक्यूशन प्लैटफ़ॉर्म पर चल सकता है.
टूलचेन को रजिस्टर करना और उनकी मदद से बिल्ड करना
अब सभी बिल्डिंग ब्लॉक इकट्ठा हो गए हैं. अब आपको सिर्फ़ Bazel की टूलचेन को हल करने की प्रोसेस के लिए, टूलचेन उपलब्ध कराने हैं. इसके लिए, टूलचेन को रजिस्टर करें. इसके लिए, MODULE.bazel फ़ाइल में register_toolchains() का इस्तेमाल करें या --extra_toolchains फ़्लैग का इस्तेमाल करके, कमांड लाइन पर टूलचेन के लेबल पास करें.
register_toolchains(
"//bar_tools:barc_linux_toolchain",
"//bar_tools:barc_windows_toolchain",
# Target patterns are also permitted, so you could have also written:
# "//bar_tools:all",
# or even
# "//bar_tools/...",
)
टूलचेन रजिस्टर करने के लिए, टारगेट पैटर्न का इस्तेमाल करने पर, अलग-अलग टूलचेन को रजिस्टर करने का क्रम इन नियमों से तय होता है:
- किसी पैकेज के सबपैकेज में तय किए गए टूलचेन, पैकेज में तय किए गए टूलचेन से पहले रजिस्टर किए जाते हैं.
- किसी पैकेज में, टूलचेन को उनके नामों के लेक्सिकोग्राफ़िकल क्रम में रजिस्टर किया जाता है.
अब जब किसी ऐसे टारगेट को बिल्ड किया जाता है जो टूलचेन टाइप पर डिपेंड करता है, तो टारगेट और एक्ज़ीक्यूशन प्लैटफ़ॉर्म के आधार पर सही टूलचेन चुना जाएगा.
# my_pkg/BUILD
platform(
name = "my_target_platform",
constraint_values = [
"@platforms//os:linux",
],
)
bar_binary(
name = "my_bar_binary",
...
)
bazel build //my_pkg:my_bar_binary --platforms=//my_pkg:my_target_platform
Bazel को पता चलेगा कि //my_pkg:my_bar_binary को ऐसे प्लैटफ़ॉर्म के साथ बिल्ड किया जा रहा है जिसमें @platforms//os:linux है. इसलिए, //bar_tools:toolchain_type रेफ़रंस को //bar_tools:barc_linux_toolchain में बदल दिया जाएगा.
इससे //bar_tools:barc_linux बिल्ड होगा, लेकिन //bar_tools:barc_windows नहीं.
टूलचेन को हल करने की प्रोसेस
टूलचेन का इस्तेमाल करने वाले हर टारगेट के लिए, Bazel की टूलचेन को हल करने की प्रोसेस, टारगेट की ठोस टूलचेन डिपेंडेंसी तय करती है. इस प्रोसेस में, ज़रूरी टूलचेन टाइप का सेट, टारगेट प्लैटफ़ॉर्म, उपलब्ध एक्ज़ीक्यूशन प्लैटफ़ॉर्म की सूची, और उपलब्ध टूलचेन की सूची को इनपुट के तौर पर लिया जाता है. इसके आउटपुट में, हर टूलचेन टाइप के लिए चुना गया टूलचेन और मौजूदा टारगेट के लिए चुना गया एक्ज़ीक्यूशन प्लैटफ़ॉर्म शामिल होता है.
`MODULE.bazel` फ़ाइलों में register_execution_platforms
और
register_toolchains कॉल के ज़रिए, बाहरी डिपेंडेंसी ग्राफ़ से उपलब्ध एक्ज़ीक्यूशन प्लैटफ़ॉर्म और टूलचेन इकट्ठा किए जाते हैं. कमांड लाइन पर [`MODULE.bazelfiles.
Additional execution platforms and toolchains may also be specified on the
command line via
[--extra_execution_platforms](/versions/7.5.0/reference/command-line-reference#flag--extra_execution_platforms)
and
[--extra_toolchains`](/versions/7.5.0/reference/command-line-reference#flag--extra_toolchains) के ज़रिए, अतिरिक्त एक्ज़ीक्यूशन प्लैटफ़ॉर्म और टूलचेन भी तय किए जा सकते हैं.
होस्ट प्लैटफ़ॉर्म को, उपलब्ध एक्ज़ीक्यूशन प्लैटफ़ॉर्म के तौर पर अपने-आप शामिल कर लिया जाता है.
उपलब्ध प्लैटफ़ॉर्म और टूलचेन को, तय क्रम वाली सूचियों के तौर पर ट्रैक किया जाता है. इसमें सूची में मौजूद पहले आइटम को प्राथमिकता दी जाती है.
प्राथमिकता के क्रम में, उपलब्ध टूलचेन का सेट, --extra_toolchains और register_toolchains से बनाया जाता है:
--extra_toolchainsका इस्तेमाल करके रजिस्टर किए गए टूलचेन, सबसे पहले जोड़े जाते हैं. (इनमें, आखिरी टूलचेन को सबसे ज़्यादा प्राथमिकता मिलती है.)- ट्रांज़िटिव बाहरी डिपेंडेंसी ग्राफ़ में,
register_toolchainsका इस्तेमाल करके रजिस्टर किए गए टूलचेन, इस क्रम में जोड़े जाते हैं: (इनमें, पहले बताए गए टूलचेन को सबसे ज़्यादा प्राथमिकता मिलती है.)- रूट मॉड्यूल से रजिस्टर किए गए टूलचेन (जैसे, वर्कस्पेस रूट पर मौजूद
MODULE.bazel); - उपयोगकर्ता की
WORKSPACEफ़ाइल में रजिस्टर किए गए टूलचेन. इनमें, वहां से शुरू किए गए मैक्रो भी शामिल हैं. - नॉन-रूट मॉड्यूल से रजिस्टर किए गए टूलचेन (जैसे, रूट मॉड्यूल से तय की गई डिपेंडेंसी, उनकी डिपेंडेंसी वगैरह);
- "WORKSPACE सफ़िक्स" में रजिस्टर किए गए टूलचेन. इसका इस्तेमाल सिर्फ़ Bazel इंस्टॉलेशन के साथ बंडल किए गए कुछ नेटिव नियमों से किया जाता है.
- रूट मॉड्यूल से रजिस्टर किए गए टूलचेन (जैसे, वर्कस्पेस रूट पर मौजूद
ध्यान दें: स्यूडो-टारगेट, जैसे कि :all, :*, और
/... को Bazel के पैकेज
लोड करने के मैकेनिज़्म के हिसाब से क्रम में लगाया जाता है. यह मैकेनिज़्म, लेक्सिकोग्राफ़िक क्रम का इस्तेमाल करता है.
टूलचेन को हल करने की प्रोसेस के चरण यहां दिए गए हैं.
target_compatible_withयाexec_compatible_withक्लॉज़, किसी प्लैटफ़ॉर्म से मैच करता है, अगर उसकी सूची में मौजूद हरconstraint_value, प्लैटफ़ॉर्म में भी मौजूद हो (साफ़ तौर पर या डिफ़ॉल्ट के तौर पर).constraint_valueअगर प्लैटफ़ॉर्म में
constraint_settingसेconstraint_valueमौजूद हैं, जिन्हें क्लॉज़ में रेफ़र नहीं किया गया है, तो इनसे मैचिंग पर कोई असर नहीं पड़ता.अगर बिल्ड किया जा रहा टारगेट,
exec_compatible_withएट्रिब्यूट तय करता है (या उसके नियम की डेफ़िनिशन,exec_compatible_withआर्ग्युमेंटतय करती है), तो उपलब्ध एक्ज़ीक्यूशन प्लैटफ़ॉर्म की सूची को फ़िल्टर किया जाता है. इसमें से, एक्ज़ीक्यूशन की पाबंदियों से मैच न करने वाले प्लैटफ़ॉर्म हटा दिए जाते हैं.हर उपलब्ध एक्ज़ीक्यूशन प्लैटफ़ॉर्म के लिए, हर टूलचेन टाइप को पहले उपलब्ध टूलचेन से जोड़ा जाता है. यह टूलचेन, इस एक्ज़ीक्यूशन प्लैटफ़ॉर्म और टारगेट प्लैटफ़ॉर्म के साथ काम करता हो.
ऐसे किसी भी एक्ज़ीक्यूशन प्लैटफ़ॉर्म को हटा दिया जाता है जिसके लिए, उसके किसी टूलचेन टाइप के लिए, काम करने वाला ज़रूरी टूलचेन नहीं मिला. बाकी प्लैटफ़ॉर्म में से, पहला प्लैटफ़ॉर्म, मौजूदा टारगेट का एक्ज़ीक्यूशन प्लैटफ़ॉर्म बन जाता है. साथ ही, उससे जुड़े टूलचेन (अगर कोई हो) टारगेट की डिपेंडेंसी बन जाते हैं.
चुने गए एक्ज़ीक्यूशन प्लैटफ़ॉर्म का इस्तेमाल, टारगेट से जनरेट होने वाली सभी कार्रवाइयों को चलाने के लिए किया जाता है.
ऐसे मामलों में जहां एक ही टारगेट को एक ही बिल्ड में, कई कॉन्फ़िगरेशन (जैसे, अलग-अलग सीपीयू के लिए) में बिल्ड किया जा सकता है, वहां टारगेट के हर वर्शन पर, टूलचेन को हल करने की प्रोसेस अलग-अलग लागू की जाती है.
अगर नियम, एक्ज़ीक्यूशन ग्रुप का इस्तेमाल करता है, तो हर एक्ज़ीक्यूशन ग्रुप, टूलचेन को हल करने की प्रोसेस अलग से करता है. साथ ही, हर ग्रुप का अपना एक्ज़ीक्यूशन प्लैटफ़ॉर्म और टूलचेन होता है.
टूलचेन को डीबग करना
अगर किसी मौजूदा नियम में टूलचेन की सुविधा जोड़ी जा रही है, तो --toolchain_resolution_debug=regex फ़्लैग का इस्तेमाल करें. टूलचेन को हल करने की प्रोसेस के दौरान, यह फ़्लैग, regex वैरिएबल से मैच करने वाले टूलचेन टाइप या टारगेट के नामों के लिए ज़्यादा जानकारी वाला आउटपुट देता है. सभी जानकारी का आउटपुट पाने के लिए, .* का इस्तेमाल किया जा सकता है. Bazel, टूलचेन के उन नामों का आउटपुट देगा जिनकी वह टूलचेन को हल करने की प्रोसेस के दौरान जांच करता है और जिन्हें छोड़ देता है.
अगर आपको यह देखना है कि cquery की कौनसी डिपेंडेंसी, टूलचेन
को हल करने की प्रोसेस से मिली हैं, तो cquery's --transitions फ़्लैग का इस्तेमाल करें:
# Find all direct dependencies of //cc:my_cc_lib. This includes explicitly
# declared dependencies, implicit dependencies, and toolchain dependencies.
$ bazel cquery 'deps(//cc:my_cc_lib, 1)'
//cc:my_cc_lib (96d6638)
@bazel_tools//tools/cpp:toolchain (96d6638)
@bazel_tools//tools/def_parser:def_parser (HOST)
//cc:my_cc_dep (96d6638)
@local_config_platform//:host (96d6638)
@bazel_tools//tools/cpp:toolchain_type (96d6638)
//:default_host_platform (96d6638)
@local_config_cc//:cc-compiler-k8 (HOST)
//cc:my_cc_lib.cc (null)
@bazel_tools//tools/cpp:grep-includes (HOST)
# Which of these are from toolchain resolution?
$ bazel cquery 'deps(//cc:my_cc_lib, 1)' --transitions=lite | grep "toolchain dependency"
[toolchain dependency]#@local_config_cc//:cc-compiler-k8#HostTransition -> b6df211