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

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

बैकग्राउंड

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

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

नियम लागू करने के दौरान, यह तय किया जा सकता है कि कार्रवाइयां, किसी एक्ज़ीक्यूशन ग्रुप के एक्ज़ीक्यूशन प्लैटफ़ॉर्म पर रन की जानी चाहिए. इसके लिए, कार्रवाई जनरेट करने वाले तरीकों के 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_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, एक्ज़ीक्यूशन प्लैटफ़ॉर्म से इनहेरिट की गई प्रॉपर्टी से ज़्यादा प्राथमिकता लेती हैं.