इस पेज पर टूलचेन फ़्रेमवर्क के बारे में बताया गया है. यह नियम बनाने वाले लोगों के लिए, अपने नियम के लॉजिक को प्लैटफ़ॉर्म के हिसाब से चुने गए टूल से अलग करने का एक तरीका है. हमारा सुझाव है कि जारी रखने से पहले, नियमों और प्लैटफ़ॉर्म के पेजों को पढ़ें. इस पेज पर बताया गया है कि टूलचेन की ज़रूरत क्यों होती है, उन्हें कैसे तय और इस्तेमाल किया जाता है, और प्लैटफ़ॉर्म की सीमाओं के आधार पर Bazel, सही टूलचेन कैसे चुनता है.
वजह
सबसे पहले, यह देखें कि टूलचेन किस समस्या को हल करने के लिए डिज़ाइन किए गए हैं. मान लें कि आपने "bar" प्रोग्रामिंग भाषा के साथ काम करने के लिए नियम लिखे हैं. आपका 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",
)
प्लैटफ़ॉर्म के हिसाब से compiler
को चुनने के लिए, select
का इस्तेमाल करके इस समाधान को बेहतर बनाया जा सकता है:
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
उपयोगकर्ता से पूछना मुश्किल और थोड़ा ज़्यादा है.
अगर इस स्टाइल का इस्तेमाल पूरे फ़ाइल फ़ोल्डर में लगातार नहीं किया जाता है, तो इससे ऐसे बिल्ड बन जाते हैं जो एक प्लैटफ़ॉर्म पर ठीक से काम करते हैं. हालांकि, इन्हें एक से ज़्यादा प्लैटफ़ॉर्म पर लागू नहीं किया जा सकता. इससे, मौजूदा नियमों या टारगेट में बदलाव किए बिना, नए प्लैटफ़ॉर्म और कंपाइलर के लिए सहायता जोड़ने की समस्या भी हल नहीं होती.
टूलचेन फ़्रेमवर्क, इनडायरेक्शन के एक और लेवल को जोड़कर इस समस्या को हल करता है. असल में, आपने यह एलान किया है कि आपका नियम, टारगेट ग्रुप (टूलचेन टाइप) के कुछ सदस्यों पर निर्भर करता है. साथ ही, Baज़र, लागू होने वाले प्लैटफ़ॉर्म की शर्तों के आधार पर, इसे अपने-आप एक खास टारगेट (टूलचेन) तक सीमित करता है. नियम के लेखक और टारगेट लेखक को उपलब्ध प्लैटफ़ॉर्म और टूलचेन के पूरे सेट की जानकारी होना ज़रूरी नहीं है.
टूलचेन का इस्तेमाल करने वाले नियम लिखना
टूलचेन फ़्रेमवर्क के तहत, नियम सीधे टूल पर निर्भर होने के बजाय टूलचेन टाइप पर निर्भर करते हैं. टूलचेन टाइप, एक सामान्य टारगेट होता है. यह ऐसे टूल की कैटगरी को दिखाता है जो अलग-अलग प्लैटफ़ॉर्म के लिए एक ही भूमिका में होते हैं. उदाहरण के लिए, बार कंपाइलर को दिखाने वाला टाइप तय किया जा सकता है:
# 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
होता है.
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
और टूलचेन टाइप के लेबल का इस्तेमाल करके, फिर से पाता है. struct
की तरह, ToolchainInfo
में आर्बिट्रेरी फ़ील्ड-वैल्यू पेयर को होल्ड किया जा सकता है. 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
की जानकारी नहीं देती हैं, क्योंकि "टारगेट" डिफ़ॉल्ट है) उन्हें पैरंट के टारगेट प्लैटफ़ॉर्म के लिए बनाया जाता है. इससे टूलचेन के नियमों को, उन बिल्ड नियमों में लाइब्रेरी (ऊपर दिया गया system_lib
एट्रिब्यूट) और टूल (compiler
एट्रिब्यूट) दोनों का योगदान देने की अनुमति मिलती है जिनमें इनकी ज़रूरत होती है. सिस्टम लाइब्रेरी आखिरी आर्टफ़ैक्ट से जुड़ी होती हैं, इसलिए एक ही प्लैटफ़ॉर्म के लिए बनाई जानी चाहिए, जबकि कंपाइलर एक टूल है जिसे बिल्ड के दौरान इस्तेमाल किया जाता है. साथ ही, यह एक ऐसा टूल होता है जो एक्ज़ीक्यूशन प्लैटफ़ॉर्म पर चल सकता है.
टूलचेन के साथ रजिस्टर करना और बनाना
इस समय, सभी बिल्डिंग ब्लॉक एक साथ इकट्ठा हो जाते हैं. इसके बाद, आपको सिर्फ़ Bazel के रिज़ॉल्यूशन प्रोसेस के लिए टूलचेन उपलब्ध कराने होंगे. इसके लिए, टूलचेन को रजिस्टर किया जाता है. इसे register_toolchains()
का इस्तेमाल करके, WORKSPACE
फ़ाइल में रजिस्टर किया जाता है या कमांड लाइन पर टूलचेन के लेबल पास करने के लिए, --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
नहीं.
टूलचेन रिज़ॉल्यूशन
टूलचेन का इस्तेमाल करने वाले हर टारगेट के लिए, Basel की टूलचेन रिज़ॉल्यूशन प्रोसेस टारगेट की कंक्रीट टूलचेन डिपेंडेंसी तय करती है. इस प्रोसेस में, ज़रूरी टूलचेन टाइप का सेट, टारगेट प्लैटफ़ॉर्म, उपलब्ध प्रोग्राम चलाने वाले प्लैटफ़ॉर्म की सूची, और उपलब्ध टूलचेन की सूची को इनपुट के तौर पर लिया जाता है. इसके आउटपुट में, हर टूलचेन टाइप के लिए चुना गया टूलचेन और मौजूदा टारगेट के लिए चुना गया, प्रोग्राम चलाने वाला प्लैटफ़ॉर्म शामिल होता है.
लागू करने के लिए उपलब्ध प्लैटफ़ॉर्म और टूलचेन WORKSPACE
फ़ाइल से register_execution_platforms
और register_toolchains
के ज़रिए इकट्ठा किए जाते हैं.
--extra_execution_platforms
और --extra_toolchains
के ज़रिए, कमांड लाइन पर अतिरिक्त प्लैटफ़ॉर्म और टूलचेन भी तय किए जा सकते हैं.
होस्ट प्लैटफ़ॉर्म, उपलब्ध एक्ज़ीक्यूशन प्लैटफ़ॉर्म के तौर पर अपने-आप शामिल हो जाता है.
उपलब्ध प्लैटफ़ॉर्म और टूलचेन को डिटरमिनिज़्म के लिए ऑर्डर की गई सूचियों के तौर पर ट्रैक किया जाता है.
साथ ही, सूची में पहले मौजूद आइटम को प्राथमिकता दी जाती है.
प्राथमिकता के क्रम में, उपलब्ध टूलचेन का सेट, --extra_toolchains
और register_toolchains
से बनाया जाता है:
--extra_toolchains
का इस्तेमाल करके रजिस्टर किए गए टूलचेन पहले जोड़े जाते हैं.- इनमें से, last टूलचेन की प्राथमिकता सबसे ज़्यादा होती है.
register_toolchains
का इस्तेमाल करके रजिस्टर किए गए टूलचेन- इनमें, पहले बताए गए टूलचेन को सबसे ज़्यादा प्राथमिकता दी जाती है.
ध्यान दें: :all
, :*
, और /...
जैसे बदली नहीं जा सकने वाले टारगेट को, Baze के पैकेज लोडिंग मैकेनिज़्म के हिसाब से क्रम में लगाया जाता है. इसमें, लेक्सिकोग्राफ़िक ऑर्डर का इस्तेमाल होता है.
इस समस्या को हल करने का तरीका यहां बताया गया है.
target_compatible_with
याexec_compatible_with
क्लॉज़ किसी प्लैटफ़ॉर्म से मैच करता है, अगर उसकी सूची में मौजूद हरconstraint_value
के लिए, प्लैटफ़ॉर्म में भी वहconstraint_value
मौजूद है (या तो साफ़ तौर पर या डिफ़ॉल्ट रूप से).अगर प्लैटफ़ॉर्म पर
constraint_setting
से मिलेconstraint_value
हैं, जिनका क्लॉज़ में रेफ़रंस नहीं दिया गया है, तो इनसे मैचिंग पर कोई असर नहीं पड़ता.अगर बनाए जा रहे टारगेट में
exec_compatible_with
एट्रिब्यूट की जानकारी दी गई है या उसके नियम की परिभाषा मेंexec_compatible_with
आर्ग्युमेंट की जानकारी दी गई है, तो उपलब्ध प्लैटफ़ॉर्म की सूची को फ़िल्टर किया जाता है, ताकि ऐसे सभी प्लैटफ़ॉर्म हटाए जा सकें जो लागू करने से जुड़ी पाबंदियों से मेल नहीं खाते.हर उपलब्ध एक्सीक्यूशन प्लैटफ़ॉर्म के लिए, हर तरह के टूलचेन को पहले उपलब्ध टूलचेन से जोड़ा जाता है. हालांकि, ऐसा तब ही किया जाता है, जब वह टूलचेन, एक्सीक्यूशन प्लैटफ़ॉर्म और टारगेट प्लैटफ़ॉर्म के साथ काम करता हो.
ऐसा कोई भी एक्ज़ीक्यूशन प्लैटफ़ॉर्म, जो अपने किसी टूलचेन टाइप के साथ काम करने वाला ज़रूरी टूलचेन नहीं ढूंढ पाता है, उसे प्रोसेस नहीं किया जाएगा. बाकी प्लैटफ़ॉर्म में से पहला प्लैटफ़ॉर्म, मौजूदा टारगेट को पूरा करने का प्लैटफ़ॉर्म बन जाता है और उससे जुड़े टूलचेन (अगर कोई हो) लक्ष्य के डिपेंडेंसी बन जाते हैं.
चुने गए एक्सीक्यूशन प्लैटफ़ॉर्म का इस्तेमाल, उन सभी कार्रवाइयों को चलाने के लिए किया जाता है जिन्हें टारगेट जनरेट करता है.
जिन मामलों में एक ही टारगेट को एक ही बिल्ड में कई कॉन्फ़िगरेशन (जैसे, अलग-अलग सीपीयू के लिए) में बनाया जा सकता है, उनमें टारगेट के हर वर्शन पर, रिज़ॉल्यूशन की प्रोसेस अलग-अलग लागू की जाती है.
अगर नियम में एक्सीक्यूशन ग्रुप का इस्तेमाल किया जाता है, तो हर एक्सीक्यूशन ग्रुप, टूलचेन रिज़ॉल्यूशन को अलग से करता है. साथ ही, हर ग्रुप का अपना एक्सीक्यूशन प्लैटफ़ॉर्म और टूलचेन होता है.
टूलचेन डीबग करना
अगर किसी मौजूदा नियम में टूलचेन की सुविधा जोड़ी जा रही है, तो --toolchain_resolution_debug=regex
फ़्लैग का इस्तेमाल करें. टूलचेन रिज़ॉल्यूशन के दौरान, फ़्लैग
ऐसे टूलचेन टाइप या टारगेट नामों के लिए ज़्यादा जानकारी देता है जो रेगुलर एक्सप्रेशन वैरिएबल से मेल खाते हैं. सारी जानकारी देने के लिए, .*
का इस्तेमाल किया जा सकता है. रिज़ॉल्यूशन प्रोसेस के दौरान, Baze टूल उन टूलचेन के नाम जनरेट करेगा
जिनकी जांच की जाती है और जिन्हें स्किप किया जाता है.
अगर आपको यह देखना है कि कौनसी cquery
डिपेंडेंसी, टूलचेन रिज़ॉल्यूशन से हैं, तो cquery
के --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