कॉन्फ़िगरेशन

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

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

इसकी मदद से ये काम किए जा सकते हैं:

  • --define की ज़रूरत को छोड़कर, अपने प्रोजेक्ट के लिए कस्टम फ़्लैग तय करें
  • अलग-अलग कॉन्फ़िगरेशन को कॉन्फ़िगर करने के लिए, ट्रांज़िशन लिखें. यह कॉन्फ़िगरेशन, उनके माता-पिता से अलग कॉन्फ़िगरेशन में होना चाहिए (जैसे कि --compilation_mode=opt या --cpu=arm)
  • बेक करने के डिफ़ॉल्ट तरीके (जैसे कि तय SDK टूल की मदद से अपने-आप //my:android_app बनने की सुविधा)

और बहुत कुछ, .bzl फ़ाइलों से पूरी तरह से (कोई Bazel रिलीज़ की ज़रूरत नहीं). उदाहरण के लिए bazelbuild/examples रेपो देखें.

उपयोगकर्ता की तय की गई बिल्ड सेटिंग

बिल्ड की सेटिंग कॉन्फ़िगरेशन की जानकारी का एक हिस्सा है. कॉन्फ़िगरेशन को की/वैल्यू मैप के तौर पर देखें. --cpu=ppc और --copt="-DFoo" को सेट करने पर, {cpu: ppc, copt: "-DFoo"} जैसा दिखने वाला कॉन्फ़िगरेशन मिलता है. हर एंट्री एक बिल्ड सेटिंग होती है.

cpu और copt जैसे परंपरागत फ़्लैग, नेटिव सेटिंग हैं — उनकी कुंजियां तय की जाती हैं और उनकी वैल्यू, नेटिव बेज़ल जावा कोड में सेट की जाती है. Bazel वाले उपयोगकर्ता, सिर्फ़ कमांड लाइन और नेटिव तौर पर मैनेज किए जाने वाले अन्य एपीआई की मदद से, उन्हें पढ़ सकते हैं और लिख सकते हैं. नेटिव फ़्लैग और उन्हें दिखाए जाने वाले एपीआई के लिए बैज़ल रिलीज़ करना ज़रूरी है. उपयोगकर्ता की तय की गई बिल्ड सेटिंग को .bzl फ़ाइलों में तय किया जाता है. इसलिए, बदलावों को रजिस्टर करने के लिए, बेज़ल रिलीज़ की ज़रूरत नहीं होती. इन्हें कमांड लाइन के ज़रिए भी सेट किया जा सकता है (अगर उन्हें flags के तौर पर नाम दिया गया है, तो नीचे और देखें), लेकिन उन्हें उपयोगकर्ता के तय किए हुए ट्रांज़िशन के ज़रिए भी सेट किया जा सकता है.

बिल्ड की सेटिंग तय करना

खत्म होने का उदाहरण

build_setting rule() पैरामीटर

बिल्ड की सेटिंग, किसी दूसरे नियम की तरह ही होती हैं. इन्हें Starlark rule() फ़ंक्शन के build_setting एट्रिब्यूट का इस्तेमाल करके अलग किया जाता है.

# example/buildsettings/build_settings.bzl
string_flag = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)

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

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

ctx.build_setting_value का इस्तेमाल करना

सभी नियमों की तरह, बिल्ड सेटिंग के नियमों में लागू करने का फ़ंक्शन दिया जाता है. बिल्ड की सेटिंग के बुनियादी Starlark-टाइप की वैल्यू को ctx.build_setting_value तरीके से ऐक्सेस किया जा सकता है. यह तरीका सिर्फ़ बिल्ड सेटिंग के नियम वाले ctx ऑब्जेक्ट के लिए उपलब्ध है. इन तरीकों से, बिल्ड सेटिंग की वैल्यू सीधे तौर पर फ़ॉरवर्ड की जा सकती है या उस पर अलग से काम किया जा सकता है. जैसे, टाइप चेकिंग या ज़्यादा मुश्किल स्ट्रक्चर बनाना. यहां बताया गया है कि आप enum-टाइप वाली बिल्ड सेटिंग को कैसे लागू करेंगे:

# example/buildsettings/build_settings.bzl
TemperatureProvider = provider(fields = ['type'])

temperatures = ["HOT", "LUKEWARM", "ICED"]

def _impl(ctx):
    raw_temperature = ctx.build_setting_value
    if raw_temperature not in temperatures:
        fail(str(ctx.label) + " build setting allowed to take values {"
             + ", ".join(temperatures) + "} but was set to unallowed value "
             + raw_temperature)
    return TemperatureProvider(type = raw_temperature)

temperature = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)

एक से ज़्यादा सेट स्ट्रिंग फ़्लैग के बारे में बताना

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

# example/buildsettings/build_settings.bzl
allow_multiple_flag = rule(
    implementation = _impl,
    build_setting = config.string(flag = True, allow_multiple = True)
)
# example/BUILD
load("//example/buildsettings:build_settings.bzl", "allow_multiple_flag")
allow_multiple_flag(
    name = "roasts",
    build_setting_default = "medium"
)

फ़्लैग की हर सेटिंग को एक वैल्यू माना जाता है:

$ bazel build //my/target --//example:roasts=blonde \
    --//example:roasts=medium,dark

ऊपर {"//example:roasts": ["blonde", "medium,dark"]} को पार्स किया गया है और ctx.build_setting_value सूची ["blonde", "medium,dark"] दिखाता है.

बिल्ड सेटिंग चालू करनी हैं

build_setting पैरामीटर से जुड़े नियमों में ज़रूरी build_setting_default एट्रिब्यूट शामिल है. यह एट्रिब्यूट ठीक उसी तरह का होता है जैसा build_setting पैरामीटर में बताया गया है.

# example/buildsettings/build_settings.bzl
FlavorProvider = provider(fields = ['type'])

def _impl(ctx):
    return FlavorProvider(type = ctx.build_setting_value)

flavor = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)
# example/BUILD
load("//example/buildsettings:build_settings.bzl", "flavor")
flavor(
    name = "favorite_flavor",
    build_setting_default = "APPLE"
)

पहले से तय की गई सेटिंग

खत्म होने का उदाहरण

Skylib की लाइब्रेरी में, पहले से तय की गई सेटिंग का सेट मौजूद होता है. इसे बिना किसी कस्टम Starlark के लिखते ही इंस्टैंशिएट किया जा सकता है.

उदाहरण के लिए, स्ट्रिंग वैल्यू के सीमित सेट को स्वीकार करने वाली सेटिंग तय करने के लिए:

# example/BUILD
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
string_flag(
    name = "myflag",
    values = ["a", "b", "c"],
    build_setting_default = "a",
)

पूरी सूची के लिए, बिल्डिंग सेटिंग के सामान्य नियम देखें.

बिल्ड सेटिंग का इस्तेमाल किया जा रहा है

बिल्ड सेटिंग के आधार पर

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

# example/rules.bzl
load("//example/buildsettings:build_settings.bzl", "FlavorProvider")
def _rule_impl(ctx):
    if ctx.attr.flavor[FlavorProvider].type == "ORANGE":
        ...

drink_rule = rule(
    implementation = _rule_impl,
    attrs = {
        "flavor": attr.label()
    }
)
# example/BUILD
load("//example:rules.bzl", "drink_rule")
load("//example/buildsettings:build_settings.bzl", "flavor")
flavor(
    name = "favorite_flavor",
    build_setting_default = "APPLE"
)
drink_rule(
    name = "my_drink",
    flavor = ":favorite_flavor",
)

भाषाएं ऐसी कॉन्फ़िगरेशन वाली कॉन्फ़िगरेशन बना सकती हैं जो उस भाषा के सभी नियमों पर निर्भर करती हों. हालांकि fragments का नेटिव कॉन्सेप्ट अब Starlark कॉन्फ़िगरेशन की दुनिया में, हार्डकोड किए गए ऑब्जेक्ट के तौर पर मौजूद नहीं है. हालांकि, इस कॉन्सेप्ट के अनुवाद के लिए, एक सामान्य इंप्लिसिट एट्रिब्यूट के सेट का इस्तेमाल किया जा सकता है. उदाहरण के लिए:

# kotlin/rules.bzl
_KOTLIN_CONFIG = {
    "_compiler": attr.label(default = "//kotlin/config:compiler-flag"),
    "_mode": attr.label(default = "//kotlin/config:mode-flag"),
    ...
}

...

kotlin_library = rule(
    implementation = _rule_impl,
    attrs = dicts.add({
        "library-attr": attr.string()
    }, _KOTLIN_CONFIG)
)

kotlin_binary = rule(
    implementation = _binary_impl,
    attrs = dicts.add({
        "binary-attr": attr.label()
    }, _KOTLIN_CONFIG)

कमांड लाइन की बिल्ड सेटिंग का इस्तेमाल करना

ज़्यादातर नेटिव फ़्लैग के मामले में, कमांड लाइन का इस्तेमाल करके बिल्ड की सेटिंग फ़्लैग के तौर पर मार्क की गई सेट करें. बिल्ड सेटिंग का नाम name=value सिंटैक्स का इस्तेमाल करके उसका पूरा टारगेट पाथ होता है:

$ bazel build //my/target --//example:string_flag=some-value # allowed
$ bazel build //my/target --//example:string_flag some-value # not allowed

खास बूलियन सिंटैक्स इस्तेमाल किया जा सकता है:

$ bazel build //my/target --//example:boolean_flag
$ bazel build //my/target --no//example:boolean_flag

बिल्ड सेटिंग के उपनामों का इस्तेमाल करना

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

अपने .bazelrc में --flag_alias=ALIAS_NAME=TARGET_PATH जोड़कर, कोई उपनाम सेट करें . उदाहरण के लिए, किसी उपनाम को coffee पर सेट करने के लिए:

# .bazelrc
build --flag_alias=coffee=//experimental/user/starlark_configurations/basic_build_setting:coffee-temp

सबसे सही तरीका: किसी उपनाम को एक से ज़्यादा बार सेट करने से सबसे हाल के नतीजे को प्राथमिकता मिलती है. यूनीक पार्सिंग के नतीजों से बचने के लिए, यूनीक उपनाम नामों का इस्तेमाल करें.

उपनाम का इस्तेमाल करने के लिए, उसे बिल्ड सेटिंग टारगेट पाथ की जगह टाइप करें. ऊपर दिए गए उदाहरण में, उपयोगकर्ता की .bazelrc के लिए coffee सेट किया गया है:

$ bazel build //my/target --coffee=ICED

के बजाय

$ bazel build //my/target --//experimental/user/starlark_configurations/basic_build_setting:coffee-temp=ICED

सबसे सही तरीका: हालांकि, कमांड लाइन पर उपनाम सेट करना मुमकिन है. हालांकि, उन्हें .bazelrc पर छोड़ने से, कमांड लाइन क्लटर कम होता है.

लेबल-आधारित बिल्ड सेटिंग

खत्म होने का उदाहरण

बिल्ड की अन्य सेटिंग के उलट, लेबल की टाइप की गई सेटिंग को build_setting नियम पैरामीटर का इस्तेमाल करके तय नहीं किया जा सकता. इसके बजाय, बज़ेल में पहले से ही दो नियम लागू होते हैं: label_flag और label_setting. इन नियमों से उन कंपनियों को टारगेट किया जाता है जिन्हें असल में टारगेट सेट करना है. label_flag और label_setting को ट्रांज़िशन के ज़रिए पढ़ा और लिखा जा सकता है. साथ ही, label_flag को उपयोगकर्ता build_setting के दूसरे नियमों की तरह सेट कर सकता है. अंतर सिर्फ़ इतना है कि उन्हें कस्टम रूप से तय नहीं किया जा सकता.

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

# example/rules.bzl
MyProvider = provider(fields = ["my_field"])

def _dep_impl(ctx):
    return MyProvider(my_field = "yeehaw")

dep_rule = rule(
    implementation = _dep_impl
)

def _parent_impl(ctx):
    if ctx.attr.my_field_provider[MyProvider].my_field == "cowabunga":
        ...

parent_rule = rule(
    implementation = _parent_impl,
    attrs = { "my_field_provider": attr.label() }
)

# example/BUILD
load("//example:rules.bzl", "dep_rule", "parent_rule")

dep_rule(name = "dep")

parent_rule(name = "parent", my_field_provider = ":my_field_provider")

label_flag(
    name = "my_field_provider",
    build_setting_default = ":dep"
)

सेटिंग बनाएं और Select()

खत्म होने का उदाहरण

उपयोगकर्ता select() का इस्तेमाल करके, बिल्ड सेटिंग के लिए एट्रिब्यूट कॉन्फ़िगर कर सकते हैं. बिल्ड की सेटिंग के टारगेट, config_setting के flag_values एट्रिब्यूट में पास किए जा सकते हैं. कॉन्फ़िगरेशन से मेल खाने वाली वैल्यू को String के तौर पर पास किया जाता है. इसके बाद, मिलान के लिए, बिल्ड सेटिंग के टाइप को पार्स किया जाता है.

config_setting(
    name = "my_config",
    flag_values = {
        "//example:favorite_flavor": "MANGO"
    }
)

उपयोगकर्ता के तय किए गए ट्रांज़िशन

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

इन्हें सेट करने वाले नियमों में एक खास एट्रिब्यूट शामिल होना चाहिए:

  "_allowlist_function_transition": attr.label(
      default = "@bazel_tools//tools/allowlists/function_transition_allowlist"
  )

ट्रांज़िशन जोड़कर, अपने बिल्ड ग्राफ़ के साइज़ को आसानी से बेहतर किया जा सकता है. इससे उन पैकेज पर, अनुमति वाली सूची जुड़ जाती है जिन्हें आप इस नियम के टारगेट बना सकते हैं. ऊपर दिए गए कोडब्लॉक में डिफ़ॉल्ट वैल्यू सब कुछ अनुमति दे देती है. हालांकि, अगर आप यह तय करना चाहते हैं कि आपके नियम का इस्तेमाल कौन कर रहा है, तो आप उस एट्रिब्यूट को अपनी पसंद के मुताबिक बनाई गई अनुमति की सूची में सेट कर सकते हैं. अगर आपको कोई सलाह या मदद चाहिए, तो bazel-visit@googlegroups.com पर संपर्क करें. इससे आपको यह समझने में मदद मिलेगी कि ट्रांज़िशन से, बिल्ड की परफ़ॉर्मेंस पर क्या असर पड़ सकता है.

परिभाषित करना

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

औपचारिक रूप से, ट्रांज़िशन एक इनपुट कॉन्फ़िगरेशन से एक या ज़्यादा आउटपुट कॉन्फ़िगरेशन तक का फ़ंक्शन होता है. ज़्यादातर ट्रांज़िशन 1:1 होते हैं, जैसे कि "--cpu=ppc के साथ इनपुट कॉन्फ़िगरेशन को बदलना. 1:2+ ट्रांज़िशन भी हो सकते हैं, लेकिन खास पाबंदियों के साथ.

Starlark में, ट्रांज़िशन काफ़ी हद तक नियमों की तरह होता है. transition() फ़ंक्शन और इसे लागू करने का फ़ंक्शन भी तय किया जाता है.

# example/transitions/transitions.bzl
def _impl(settings, attr):
    _ignore = (settings, attr)
    return {"//example:favorite_flavor" : "MINT"}

hot_chocolate_transition = transition(
    implementation = _impl,
    inputs = [],
    outputs = ["//example:favorite_flavor"]
)

transition() फ़ंक्शन, लागू करने वाले फ़ंक्शन में, बिल्ड सेटिंग के सेट को पढ़ने(inputs) में, और बिल्ड सेटिंग को सेट करने के लिए (outputs) सेट करता है. लागू करने वाले फ़ंक्शन में दो पैरामीटर, settings और attr होते हैं. inputs पैरामीटर में, transition() के लिए तय की गई सभी सेटिंग का एक शब्दकोश {String:Object} है.settings

attr, नियम और एट्रिब्यूट की वैल्यू का शब्दकोश है, जिसमें ट्रांज़िशन अटैच किया गया है. आउटगोइंग एज ट्रांज़िशन के तौर पर अटैच होने पर, इन एट्रिब्यूट की वैल्यू कॉन्फ़िगर करने के बाद चुनी गई()() रिज़ॉल्यूशन होती है. आने वाले किनारे के ट्रांज़िशन के तौर पर अटैच होने पर, attr में ऐसे एट्रिब्यूट शामिल नहीं होते जो वैल्यू चुनने के लिए सिलेक्टर का इस्तेमाल करते हैं. --foo पर आने वाला एज ट्रांज़िशन, bar एट्रिब्यूट को पढ़ता है और --foo को भी चुनता है, ताकि एट्रिब्यूट bar को सेट किया जा सके. इससे, आने वाले एज ट्रांज़िशन को bar की गलत वैल्यू को समझने का मौका मिलता है.

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

1:2+ ट्रांज़िशन तय करना

खत्म होने का उदाहरण

आउटगोइंग एज ट्रांज़िशन की मदद से, किसी एक इनपुट कॉन्फ़िगरेशन को दो या उससे ज़्यादा आउटपुट कॉन्फ़िगरेशन में मैप किया जा सकता है. यह उन नियमों को परिभाषित करने के लिए उपयोगी है जो मल्टी-आर्किटेक्चर कोड को बंडल करते हैं.

1:2+ ट्रांज़िशन के बारे में, ट्रांज़िशन लागू करने वाले फ़ंक्शन में डिक्शनरी की सूची दिखती है.

# example/transitions/transitions.bzl
def _impl(settings, attr):
    _ignore = (settings, attr)
    return [
        {"//example:favorite_flavor" : "LATTE"},
        {"//example:favorite_flavor" : "MOCHA"},
    ]

coffee_transition = transition(
    implementation = _impl,
    inputs = [],
    outputs = ["//example:favorite_flavor"]
)

वे कस्टम कुंजियां भी सेट कर सकती हैं जिनका इस्तेमाल नियम लागू करने वाला फ़ंक्शन, अलग-अलग डिपेंडेंसी पढ़ने के लिए कर सकता है:

# example/transitions/transitions.bzl
def _impl(settings, attr):
    _ignore = (settings, attr)
    return {
        "Apple deps": {"//command_line_option:cpu": "ppc"},
        "Linux deps": {"//command_line_option:cpu": "x86"},
    }

multi_arch_transition = transition(
    implementation = _impl,
    inputs = [],
    outputs = ["//command_line_option:cpu"]
)

ट्रांज़िशन अटैच किया जा रहा है

खत्म होने का उदाहरण

ट्रांज़िशन दो जगहों पर अटैच किए जा सकते हैं: इनकमिंग किनारे और बाहरी किनारे. इसका मतलब है कि नियम अपने ही कॉन्फ़िगरेशन (आने वाला ट्रांज़िशन) और अपने डिपेंडेंसी कॉन्फ़िगरेशन (आउटगोइंग ट्रांज़िशन) में बदलाव कर सकते हैं.

ध्यान दें: फ़िलहाल, Starlark ट्रांज़िशन को नेटिव नियमों से जोड़ने का कोई तरीका नहीं है. अगर आपको यह करने की ज़रूरत है, तो इस समस्या को सुलझाने के बारे में मदद पाने के लिए bazel-visit@googlegroups.com से संपर्क करें.

आने वाले किनारों पर ट्रांज़िशन

इनकमिंग ऑब्जेक्ट के ट्रांज़िशन के लिए, rule() के cfg पैरामीटर में transition ऑब्जेक्ट को transition() जोड़कर अटैच किया जाता है:

# example/rules.bzl
load("example/transitions:transitions.bzl", "hot_chocolate_transition")
drink_rule = rule(
    implementation = _impl,
    cfg = hot_chocolate_transition,
    ...

इनकमिंग एज ट्रांज़िशन को 1:1 ट्रांज़िशन होना चाहिए.

आउटगोइंग एज ट्रांज़िशन

आउटगोइंग एज ट्रांज़िशन को किसी एट्रिब्यूट के cfg पैरामीटर में transition (transition() से बनाया गया) अटैच करके चालू किया जाता है:

# example/rules.bzl
load("example/transitions:transitions.bzl", "coffee_transition")
drink_rule = rule(
    implementation = _impl,
    attrs = { "dep": attr.label(cfg = coffee_transition)}
    ...

आउटगोइंग एज ट्रांज़िशन 1:1 या 1:2+ हो सकते हैं.

इन कुंजियों को पढ़ने के लिए, ट्रांज़िशन से एट्रिब्यूट को ऐक्सेस करना देखें.

नेटिव विकल्पों पर ट्रांज़िशन

खत्म होने का उदाहरण

Starलार्क ट्रांज़िशन, नेटिव बिल्ड कॉन्फ़िगरेशन के विकल्पों को पढ़ने और लिखने का एलान भी कर सकता है. इसके लिए, विकल्प के नाम से एक खास प्रीफ़िक्स का इस्तेमाल किया जाता है.

# example/transitions/transitions.bzl
def _impl(settings, attr):
    _ignore = (settings, attr)
    return {"//command_line_option:cpu": "k8"}

cpu_transition = transition(
    implementation = _impl,
    inputs = [],
    outputs = ["//command_line_option:cpu"]

असमर्थित स्थानीय विकल्प

Bazel से --define पर "//command_line_option:define" का इस्तेमाल नहीं किया जा सकता. इसके बजाय, पसंद के मुताबिक बिल्ड की सेटिंग का इस्तेमाल करें. आम तौर पर, बिल्ड सेटिंग में --define का इस्तेमाल नहीं किया जाता है.

Bazel से --config पर ट्रांज़िशन की सुविधा नहीं है. ऐसा इसलिए, क्योंकि --config बड़ा होने वाला "फ़्लैग" होता है, जो दूसरे फ़्लैग के साथ काम करता है.

अहम तौर पर, --config में ऐसे फ़्लैग शामिल हो सकते हैं जिनसे बिल्ड कॉन्फ़िगरेशन पर असर नहीं पड़ता, जैसे कि --spawn_strategy . बेज़ल, डिज़ाइन की वजह से ऐसे फ़्लैग को अलग-अलग टारगेट से नहीं जोड़ सकता. इसका मतलब है कि इन बदलावों को लागू करने का कोई सही तरीका नहीं है.

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

एक से ज़्यादा बिल्ड सेटिंग जोड़ने की अनुमति दें

बिल्ड की सेटिंग सेट करते समय एक से ज़्यादा वैल्यू की अनुमति होती है, लेकिन सेटिंग की वैल्यू एक सूची के साथ सेट होनी चाहिए.

# example/buildsettings/build_settings.bzl
string_flag = rule(
    implementation = _impl,
    build_setting = config.string(flag = True, allow_multiple = True)
)
# example/BUILD
load("//example/buildsettings:build_settings.bzl", "string_flag")
string_flag(name = "roasts", build_setting_default = "medium")
# example/transitions/rules.bzl
def _transition_impl(settings, attr):
    # Using a value of just "dark" here will throw an error
    return {"//example:roasts" : ["dark"]},

coffee_transition = transition(
    implementation = _transition_impl,
    inputs = [],
    outputs = ["//example:roasts"]
)

नो-ऑप ट्रांज़िशन

अगर कोई ट्रांज़िशन {}, [] या None दिखाता है, तो यह सभी सेटिंग को उनकी ओरिजनल वैल्यू में बनाए रखने के लिए शॉर्टकट है. यह हर आउटपुट को साफ़ तौर पर सेट करने से ज़्यादा आसान है.

# example/transitions/transitions.bzl
def _impl(settings, attr):
    _ignore = (attr)
    if settings["//example:already_chosen"] is True:
      return {}
    return {
      "//example:favorite_flavor": "dark chocolate",
      "//example:include_marshmallows": "yes",
      "//example:desired_temperature": "38C",
    }

hot_chocolate_transition = transition(
    implementation = _impl,
    inputs = ["//example:already_chosen"],
    outputs = [
        "//example:favorite_flavor",
        "//example:include_marshmallows",
        "//example:desired_temperature",
    ]
)

ट्रांज़िशन से एट्रिब्यूट ऐक्सेस करना

खत्म होने का उदाहरण

किसी आउटगोइंग एज में ट्रांज़िशन अटैच करते समय (इस बात पर ध्यान दिए बिना कि ट्रांज़िशन 1:1 या 1:2+ ट्रांज़िशन है), ctx.attr को हर हाल में सूची में शामिल किया जाता है. इस सूची में शामिल एलिमेंट का क्रम तय नहीं किया गया है.

# example/transitions/rules.bzl
def _transition_impl(settings, attr):
    return {"//example:favorite_flavor" : "LATTE"},

coffee_transition = transition(
    implementation = _transition_impl,
    inputs = [],
    outputs = ["//example:favorite_flavor"]
)

def _rule_impl(ctx):
    # Note: List access even though "dep" is not declared as list
    transitioned_dep = ctx.attr.dep[0]

    # Note: Access doesn't change, other_deps was already a list
    for other_dep in ctx.attr.other_deps:
      # ...


coffee_rule = rule(
    implementation = _rule_impl,
    attrs = {
        "dep": attr.label(cfg = coffee_transition)
        "other_deps": attr.label_list(cfg = coffee_transition)
    })

अगर ट्रांज़िशन के लिए 1:2+ दिया गया है और उसमें कस्टम बटन सेट किए गए हैं, तो हर कुंजी के लिए अलग-अलग डिप पढ़ने के लिए ctx.split_attr का इस्तेमाल किया जा सकता है:

# example/transitions/rules.bzl
def _impl(settings, attr):
    _ignore = (settings, attr)
    return {
        "Apple deps": {"//command_line_option:cpu": "ppc"},
        "Linux deps": {"//command_line_option:cpu": "x86"},
    }

multi_arch_transition = transition(
    implementation = _impl,
    inputs = [],
    outputs = ["//command_line_option:cpu"]
)

def _rule_impl(ctx):
    apple_dep = ctx.split_attr.dep["Apple deps"]
    linux_dep = ctx.split_attr.dep["Linux deps"]
    # ctx.attr has a list of all deps for all keys. Order is not guaranteed.
    all_deps = ctx.attr.dep

multi_arch_rule = rule(
    implementation = _rule_impl,
    attrs = {
        "dep": attr.label(cfg = multi_arch_transition)
    })

यहां पूरा उदाहरण देखें.

प्लैटफ़ॉर्म और टूलचेन के साथ इंटिग्रेशन

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

मेमोरी और परफ़ॉर्मेंस के बारे में जानकारी

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

ऐप्लिकेशन की खराब परफ़ॉर्मेंस: केस स्टडी

बढ़ाने लायक ग्राफ़

पहला डायग्राम. बढ़ाने लायक ग्राफ़, जो टॉप लेवल टारगेट और इसकी डिपेंडेंसी दिखाता है.

यह ग्राफ़ एक टॉप लेवल टारगेट //pkg:app दिखाता है. यह दो टारगेट पर निर्भर करता है, //pkg:1_0 और //pkg:1_1. ये दोनों टारगेट दो टारगेट पर निर्भर करते हैं //pkg:2_0 और //pkg:2_1. दोनों टारगेट दो टारगेट पर निर्भर करते हैं, //pkg:3_0 और //pkg:3_1. यह //pkg:n_0 और //pkg:n_1 तक जारी रहता है. ये दोनों एक ही टारगेट //pkg:dep पर निर्भर करते हैं.

//pkg:app बनाने के लिए \(2n+2\) टारगेट ज़रूरी है:

  • //pkg:app
  • //pkg:dep
  • \(i\) \([1..n]\)में //pkg:i_0 और //pkg:i_1

मान लें कि आपको फ़्लैग लागू करना है --//foo:owner=<STRING> और //pkg:i_b लागू होता है

depConfig = myConfig + depConfig.owner="$(myConfig.owner)$(b)"

दूसरे शब्दों में, //pkg:i_b अपनी सभी गड़बड़ियों के लिए, b को --owner की पुरानी वैल्यू में जोड़ देता है.

इससे नीचे दिए गए कॉन्फ़िगर किए गए टारगेट मिलते हैं:

//pkg:app                              //foo:owner=""
//pkg:1_0                              //foo:owner=""
//pkg:1_1                              //foo:owner=""
//pkg:2_0 (via //pkg:1_0)              //foo:owner="0"
//pkg:2_0 (via //pkg:1_1)              //foo:owner="1"
//pkg:2_1 (via //pkg:1_0)              //foo:owner="0"
//pkg:2_1 (via //pkg:1_1)              //foo:owner="1"
//pkg:3_0 (via //pkg:1_0 → //pkg:2_0)  //foo:owner="00"
//pkg:3_0 (via //pkg:1_0 → //pkg:2_1)  //foo:owner="01"
//pkg:3_0 (via //pkg:1_1 → //pkg:2_0)  //foo:owner="10"
//pkg:3_0 (via //pkg:1_1 → //pkg:2_1)  //foo:owner="11"
...

//pkg:depकॉन्फ़िगर किए गए \(2^n\) कॉन्फ़िगर किए गए टारगेट बनाता है: config.owner= "\(b_0b_1...b_n\)" \(b_i\) सभी के लिए \(\{0,1\}\)में

इससे बिल्ड ग्राफ़, टारगेट ग्राफ़ की तुलना में तेज़ी से बड़ा हो जाता है, जिससे मेमोरी और परफ़ॉर्मेंस के नतीजे काम के होते हैं.

TODO: इन समस्याओं को मेज़र करने और उन्हें ठीक करने के लिए रणनीतियां जोड़ें.

आगे पढ़ना

बिल्ड कॉन्फ़िगरेशन में बदलाव करने के बारे में ज़्यादा जानकारी के लिए, यह देखें: