एक्ज़ीक्यूशन ग्रुप

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

बैकग्राउंड

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

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

एक्ज़ीक्यूशन ग्रुप तय करना

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

# foo.bzl
my_rule = rule(
    _impl,
    exec_groups = {
        link: exec_group(
            exec_compatible_with = [ "@platforms//os:linux" ]
            toolchains = ["//foo:toolchain_type"],
        ),
        test: exec_group(
            toolchains = ["//foo_tools:toolchain_type"],
        ),
    },
    attrs = {
        "_compiler": attr.label(cfg = config.exec("link"))
    },
)

ऊपर दिए गए कोड स्निपेट में, आपको दिख सकता है कि टूल डिपेंडेंसी, cfg एट्रिब्यूट पैरामीटर और config मॉड्यूल का इस्तेमाल करके, किसी exec ग्रुप के लिए ट्रांज़िशन भी तय कर सकती हैं. मॉड्यूल, exec फ़ंक्शन दिखाता है. यह एक स्ट्रिंग पैरामीटर लेता है, जो उस exec ग्रुप का नाम होता है जिसके लिए डिपेंडेंसी बनाई जानी चाहिए.

नेटिव नियमों की तरह, Starlark टेस्ट के नियमों में, test एक्ज़ीक्यूशन ग्रुप डिफ़ॉल्ट रूप से मौजूद होता है.

एक्ज़ीक्यूशन ग्रुप इनहेरिटेंस

नए एक्ज़ीक्यूशन ग्रुप, अपने कंस्ट्रेंट और टूलचेन तय करने के अलावा, यह भी तय कर सकते हैं कि वे नियम के डिफ़ॉल्ट एक्ज़ीक्यूशन ग्रुप से इनहेरिट करना चाहते हैं. इसके लिए, copy_from_rule = True पैरामीटर पास किया जा सकता है. copy_from_rule को 'सही' पर सेट करना और exec_compatible_with या toolchains को पास करना, एक गड़बड़ी है.

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

# foo.bzl
my_rule = rule(
    _impl,
    exec_groups = {
        copied: exec_group(
            copy_from_rule = True,
            # This will inherit exec_compatible_with and toolchains.
            # Setting them here directly would be an error, however.
        ),
    },
    toolchains = ["//foo_tools:toolchain_type"],
    exec_compatible_with = ["@platforms//os:linux"],
)

# BUILD

my_rule(
    name = "demo",
    exec_compatible_with = [":local_constraint"],
)

कॉन्फ़िगर किए गए टारगेट demo के लिए, copied एक्ज़ीक्यूशन ग्रुप में ये सभी शामिल होंगे: - //fool_tools:toolchain_type - @platforms//os:linux - :local_constraint

एक्ज़ीक्यूशन ग्रुप ऐक्सेस करना

नियम लागू करने के दौरान, यह तय किया जा सकता है कि कार्रवाइयां, किसी एक्ज़ीक्यूशन ग्रुप के एक्ज़ीक्यूशन प्लैटफ़ॉर्म पर चलनी चाहिए. इसके लिए, कार्रवाई जनरेट करने वाले तरीकों के exec_group पैरामीटर का इस्तेमाल किया जा सकता है. खास तौर पर, ctx.actions.run और ctx.actions.run_shell.

# foo.bzl
def _impl(ctx):
  ctx.actions.run(
     inputs = [ctx.attr._some_tool, ctx.srcs[0]]
     exec_group = "compile",
     # ...
  )

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

# foo.bzl
def _impl(ctx):
  foo_info = ctx.exec_groups["link"].toolchains["//foo:toolchain_type"].fooinfo
  ctx.actions.run(
     inputs = [foo_info, ctx.srcs[0]]
     exec_group = "link",
     # ...
  )

एक्ज़ीक्यूशन प्रॉपर्टी सेट करने के लिए, एक्ज़ीक्यूशन ग्रुप का इस्तेमाल करना

एक्ज़ीक्यूशन ग्रुप, exec_properties एट्रिब्यूट के साथ इंटिग्रेट किए जाते हैं. यह एट्रिब्यूट हर नियम में मौजूद होता है. इसकी मदद से, टारगेट राइटर प्रॉपर्टी की स्ट्रिंग डिक्शनरी तय कर सकता है. इसके बाद, इसे एक्ज़ीक्यूशन मशीनरी को पास किया जाता है. उदाहरण के लिए, अगर आपको टारगेट के लिए कोई प्रॉपर्टी सेट करनी है, जैसे कि मेमोरी, और कुछ कार्रवाइयों को ज़्यादा मेमोरी उपलब्ध करानी है, तो आपको एक्ज़ीक्यूशन-ग्रुप-ऑगमेंटेड कुंजी के साथ exec_properties एंट्री लिखनी होगी. जैसे:

# BUILD
my_rule(
    name = 'my_target',
    exec_properties = {
        'mem': '12g',
        'link.mem': '16g'
    }
    
)

exec_group = "link" वाली सभी कार्रवाइयों को, exec प्रॉपर्टीज़ डिक्शनरी {"mem": "16g"} के तौर पर दिखेगी. जैसा कि यहां दिख रहा है, एक्ज़ीक्यूशन-ग्रुप-लेवल की सेटिंग, टारगेट-लेवल की सेटिंग को बदल देती हैं.

नेटिव नियमों के लिए एक्ज़ीक्यूशन ग्रुप

नेटिव नियमों से तय की गई कार्रवाइयों के लिए, ये एक्ज़ीक्यूशन ग्रुप उपलब्ध हैं:

  • test: टेस्ट रनर की कार्रवाइयां.
  • cpp_link: C++ लिंकिंग की कार्रवाइयां.

exec प्रॉपर्टी सेट करने के लिए, exec ग्रुप बनाना

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

# foo.bzl

# Creating an exec group with `copy_from_rule=True` is the same as explicitly
# setting the exec group's toolchains and constraints to the same values as the
# rule's respective parameters.
my_rule = rule(
    _impl,
    exec_compatible_with = ["@platforms//os:linux"],
    toolchains = ["//foo:toolchain_type"],
    exec_groups = {
        # The following two groups have the same toolchains and constraints:
        foo: exec_group(copy_from_rule = True),
        "bar": exec_group(
            exec_compatible_with = ["@platforms//os:linux"],
            toolchains = ["//foo:toolchain_type"],
        ),
    },
)

#

एक्ज़ीक्यूशन ग्रुप और प्लैटफ़ॉर्म एक्ज़ीक्यूशन प्रॉपर्टी

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

उदाहरण के लिए, मान लें कि C++ टेस्ट चलाने के लिए, किसी संसाधन की ज़रूरत होती है. हालांकि, कंपाइल करने और लिंक करने के लिए इसकी ज़रूरत नहीं होती. इसे इस तरह मॉडल किया जा सकता है:

constraint_setting(name = "resource")
constraint_value(name = "has_resource", constraint_setting = ":resource")

platform(
    name = "platform_with_resource",
    constraint_values = [":has_resource"],
    exec_properties = {
        "test.resource": "...",
    },
)

cc_test(
    name = "my_test",
    srcs = ["my_test.cc"],
    exec_compatible_with = [":has_resource"],
)

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