तारीख सेव करें: BazelCon 2023, 24 से 25 अक्टूबर तक Google म्यूनिख में होगा! ज़्यादा जानें

टूलचेन

किसी समस्या की शिकायत करें स्रोत देखें

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

वजह

आइए सबसे पहले उन समस्या हल करने वाले टूल पर बात करें जिन्हें हल करने के लिए डिज़ाइन किया गया है. मान लें कि आप "बार" प्रोग्रामिंग भाषा का समर्थन करने के लिए नियम लिख रहे हैं. आपका 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 उपयोगकर्ता से थोड़ा पूछने की ज़रूरत है. अगर पूरे फ़ाइल फ़ोल्डर में इस स्टाइल का लगातार इस्तेमाल नहीं किया गया है, तो एक ही प्लैटफ़ॉर्म पर कई ऐसे काम होते हैं जो एक ही जगह पर ठीक से काम करते हैं. हालांकि, एक से ज़्यादा प्लैटफ़ॉर्म पर इस्तेमाल करने पर ये स्टाइल काम नहीं करते. यह मौजूदा नियमों या टारगेट में बदलाव किए बिना, नए प्लैटफ़ॉर्म और कंपाइलर के लिए सहायता जोड़ने से जुड़ी समस्या को भी हल नहीं करता.

टूलचेन फ़्रेमवर्क, निर्देश का एक अतिरिक्त स्तर जोड़कर इस समस्या का समाधान करता है. ज़रूरी तौर पर यह बताया गया हो कि टारगेट (टूलचेन टाइप) के किसी फ़ैमिली ग्रुप के कुछ सदस्य के पास, आपके नियम का ऐब्सट्रैक्ट डिपेंडेंसी है. इसके अलावा, बेज़ल लागू होने वाले प्लैटफ़ॉर्म की सीमाओं के आधार पर, इसे अपने-आप एक खास टारगेट (टूलचेन) पर हल कर देता है. नियम के लेखक और टारगेट लेखक को उपलब्ध प्लैटफ़ॉर्म और टूल चेन के पूरे सेट की जानकारी नहीं होनी चाहिए.

लिखने के नियम, जो टूल चेन का इस्तेमाल करते हैं

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

# 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 कंपनी से किया. ToolchainInfo ऑब्जेक्ट के फ़ील्ड, मूल टूल के नियम से सेट होते हैं. अगले सेक्शन में, इस नियम को इस तरह से दिखाया गया है कि BarcInfo ऑब्जेक्ट को रैप करने वाला barcinfo फ़ील्ड मौजूद हो.

टारगेट के लिए टूलचेन का समाधान करने के लिए, बेज़ल की प्रोसेस नीचे दी गई है. असल में, समाधान किया गया टूलचेन टारगेट असल में, bar_binary टारगेट पर निर्भर करता है, न कि कैंडिडेट टूलचेन के लिए.

ज़रूरी और वैकल्पिक टूलचेन

डिफ़ॉल्ट रूप से, जब कोई नियम सिर्फ़ लेबल के ज़रिए टूलचेन प्रकार की निर्भरता दिखाता है (जैसा कि ऊपर दिखाया गया है), तो टूलचेन प्रकार को ज़रूरी माना जाता है. अगर बैज़ेल किसी ज़रूरी टूलचेन टाइप के लिए, मिलता-जुलता टूलचेन नहीं मिल पाता है (नीचे टूलचेन रिज़ॉल्यूशन देखें) तो यह एक गड़बड़ी है और विश्लेषण रुक जाता है.

इसके बजाय, नीचे दिए गए तरीके से वैकल्पिक टूलचेन प्रकार का एलान करना संभव है:

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 []

टूलचेन को परिभाषित करना

किसी टूलचेन प्रकार के लिए कुछ टूलचेन तय करने के लिए, आपको तीन चीज़ों की ज़रूरत होगी:

  1. टूल या टूल सुइट किस तरह का है, यह दिखाने वाला भाषा से जुड़ा नियम. कन्वेंशन के मुताबिक, इस नियम के नाम के आगे "_toolchain" लगा है.

    1. ध्यान दें: \_toolchain नियम बनाने की कोई कार्रवाई नहीं की जा सकती. बल्कि, यह अन्य नियमों से आर्टफ़ैक्ट इकट्ठा करता है और उन्हें उस नियम पर भेजता है जो टूलचेन का इस्तेमाल करता है. यह नियम बिल्ड की सभी कार्रवाइयों के लिए ज़िम्मेदार है.
  2. इस तरह के नियम के कई टारगेट, अलग-अलग प्लैटफ़ॉर्म के लिए टूल या टूल सुइट के वर्शन दिखाते हैं.

  3. इस तरह के हर टारगेट के लिए, सामान्य 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 परिभाषाएं बनाई जाती हैं. ये परिभाषाएं, खास भाषा के टारगेट को टूलचेन टाइप से जोड़ती हैं. इससे कंटेंपररी से जुड़ी जानकारी मिलती है, जिससे बेज़ल को किसी प्लैटफ़ॉर्म के लिए सही टूल की जानकारी मिलती है.

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 एट्रिब्यूट) दोनों को उन नियमों में शामिल करने की अनुमति देता है जिनकी ज़रूरत उन्हें होती है. सिस्टम लाइब्रेरी फ़ाइनल आर्टफ़ैक्ट से लिंक होती हैं, इसलिए इन्हें उसी प्लैटफ़ॉर्म के लिए बनाया जाना चाहिए, जबकि कंपाइलर बिल्ड के दौरान शुरू किया गया टूल होता है और उसे एक्ज़ीक्यूशन प्लैटफ़ॉर्म पर चलाने की अनुमति होती है.

टूलचेन की मदद से रजिस्टर करना और बनाना

यहां सभी बिल्डिंग ब्लॉक असेंबल किए जाते हैं. इसके बाद, आपको बस बेज़ल के रिज़ॉल्यूशन की प्रोसेस के लिए टूलचेन उपलब्ध कराने होंगे. इसके लिए, 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",
)

अब जब आप किसी टूलचेन प्रकार पर निर्भर कोई लक्ष्य बनाते हैं, तो लक्ष्य और निष्पादन प्लेटफ़ॉर्म के आधार पर एक उपयुक्त टूलचेन चुना जाएगा.

# 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

बेज़ल को पता चलेगा कि //my_pkg:my_bar_binary एक ऐसे प्लैटफ़ॉर्म के साथ बनाया जा रहा है जिसमें @platforms//os:linux है. इसलिए, यह //bar_tools:barc_linux_toolchain के //bar_tools:toolchain_type रेफ़रंस को रिज़ॉल्व करता है. इससे इमारत //bar_tools:barc_linux बन जाएगी, लेकिन //bar_tools:barc_windows नहीं.

टूलचेन रिज़ॉल्यूशन

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

एक्ज़ीक्यूशन के लिए उपलब्ध प्लैटफ़ॉर्म और टूल चेन, WORKSPACE फ़ाइल से इकट्ठा किए जाते हैं. इसके लिए, register_execution_platforms औरregister_toolchains का इस्तेमाल किया जाता है. एक्ज़ीक्यूशन के लिए अतिरिक्त प्लैटफ़ॉर्म और टूल चेन भी --extra_execution_platforms और--extra_toolchains के ज़रिए कमांड लाइन पर दी जा सकती हैं. होस्ट प्लैटफ़ॉर्म अपने-आप, एक्ज़ीक्यूशन के उपलब्ध प्लैटफ़ॉर्म के तौर पर शामिल हो जाता है. उपलब्ध प्लैटफ़ॉर्म और टूलचेन को डेटरमिनिज़्म की क्रम में दी गई सूचियों के रूप में ट्रैक किया जाता है. साथ ही, इसमें सूची में पहले के आइटम को भी प्राथमिकता दी जाती है.

समस्या हल करने के तरीके यहां दिए गए हैं.

  1. किसी target_compatible_with या exec_compatible_with क्लॉज़ का मिलान किसी प्लैटफ़ॉर्म से मिलता-जुलता है, अगर सूची में मौजूद हर constraint_value के लिए, प्लैटफ़ॉर्म को वह constraint_value भी दिया गया हो (पूरी तरह से या डिफ़ॉल्ट के तौर पर).

    अगर प्लैटफ़ॉर्म में constraint_setting के constraint_value की जानकारी दी गई है, जो क्लॉज़ में नहीं दी गई है, तो मिलान करने पर कोई असर नहीं पड़ेगा.

  2. अगर बनाया जा रहा टारगेट, exec_compatible_with एट्रिब्यूट बताता है (या इसके नियम की परिभाषा में, exec_compatible_with आर्ग्युमेंट बताया गया है), तो एक्ज़ीक्यूशन से जुड़ी शर्तों से मेल न खाने वाले किसी एक एग्ज़िट को हटाने के लिए, उपलब्ध एक्ज़ीक्यूशन प्लैटफ़ॉर्म की सूची फ़िल्टर की जाती है.

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

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

चुने गए एक्ज़ीक्यूशन प्लैटफ़ॉर्म का इस्तेमाल टारगेट जनरेट की जाने वाली सभी कार्रवाइयां चलाने के लिए किया जाता है.

ऐसे मामलों में जहां एक ही टारगेट को एक ही बिल्ड में कई कॉन्फ़िगरेशन (जैसे कि अलग-अलग सीपीयू के लिए) में बनाया जा सकता हो, वहीं रिज़ॉल्यूशन प्रोसेस, टारगेट के हर वर्शन पर अलग-अलग लागू की जाती है.

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

डीबग करने वाले टूलचेन

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

अगर आपको देखना है कि कौनसी 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