BazelCon 2022, 16 नवंबर से 17 नवंबर तक न्यूयॉर्क में और ऑनलाइन उपलब्ध है.
आज ही रजिस्टर करें!

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

संग्रह की मदद से व्यवस्थित रहें अपनी प्राथमिकताओं के आधार पर, कॉन्टेंट को सेव करें और कैटगरी में बांटें.

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

ऐसा करने से:

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

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

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

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

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

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

आखिर में आखिर तक का उदाहरण

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

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

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

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

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

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

सभी नियमों की तरह, बिल्ड सेटिंग के नियम लागू करने के फ़ंक्शन भी होते हैं. बिल्ड सेटिंग की बुनियादी Starstark-टाइप वैल्यू को, 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/buildsettings/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/buildsettings/BUILD
load("//example/buildsettings:build_settings.bzl", "flavor")
flavor(
    name = "favorite_flavor",
    build_setting_default = "APPLE"
)

पहले से तय सेटिंग

आखिर में आखिर तक का उदाहरण

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

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

# 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

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

उपनाम का इस्तेमाल करने के लिए, बिल्ड सेटिंग टारगेट पाथ की जगह उसे लिखें. उपयोगकर्ता के #39; .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"
  )

ट्रांज़िशन जोड़कर, आप अपने ग्राफ़ का साइज़ बहुत आसानी से बढ़ा सकते हैं. यह उन पैकेज पर अनुमति वाली सूची सेट करता है जिनमें आप इस नियम के टारगेट बना सकते हैं. ऊपर दिए गए कोडब्लॉक में डिफ़ॉल्ट मान सब कुछ सूची में रखता है. हालांकि, अगर आप यह तय करना चाहते हैं कि आपके नियम का इस्तेमाल कौन कर रहा है, तो आप इस एट्रिब्यूट को अनुमति वाली सूची में शामिल कर सकते हैं. अगर आप अपने बिल्ड की परफ़ॉर्मेंस पर होने वाले ट्रांज़िशन के असर के बारे में जानना चाहते हैं या सलाह या सहायता चाहते हैं, तो bazer-चर्चा@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 होते हैं. settings एक शब्दकोश है जो inputs पैरामीटर में बताई गई सभी सेटिंग का String:Object{1}है.transition().

attr, उस नियम की विशेषताओं और मानों का शब्दकोश है जिससे ट्रांज़िशन अटैच किया गया है. जब आउटगोइंग एज ट्रांज़िशन के तौर पर अटैच किया जाता है, तब इन एट्रिब्यूट की वैल्यू को चुनने के बाद से कॉन्फ़िगर किया जाता है. जब आने वाले किनारे का ट्रांज़िशन किया जाता है, तो attr में कोई भी ऐसा एट्रिब्यूट शामिल नहीं किया जाता जिससे उसकी वैल्यू के समाधान के लिए, सिलेक्टर का इस्तेमाल किया जा सके. अगर --foo पर आने वाला एज ट्रांज़िशन, एट्रिब्यूट bar को पढ़ता है और फिर एट्रिब्यूट bar को सेट करने के लिए, --foo पर भी चुनता है, तो ट्रांज़िशन में 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"]
)

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

आखिर में आखिर तक का उदाहरण

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

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

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

आने वाले एज ट्रांज़िशन को चालू करने के लिए, rule() और #33;s 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 ट्रांज़िशन होने चाहिए.

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

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

# 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+ हो सकता है.

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

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

आखिर में आखिर तक का उदाहरण

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

# 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"]

काम न करने वाले नेटिव विकल्प

बेज़ेल --define के साथ "//command_line_option:define" पर ट्रांज़िशन करने की सुविधा नहीं देते. इसके बजाय, कस्टम बिल्ड सेटिंग का इस्तेमाल करें. आम तौर पर, --define के नए इस्तेमाल के लिए, बिल्ड सेटिंग को ध्यान में रखा जाता है.

बेज़ेल --config पर ट्रांज़िशन के लिए काम नहीं करते. ऐसा इसलिए है, क्योंकि --config एक &कोटेशन एक्सटेंशन है जो अन्य फ़्लैग तक बड़ा होता है.

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

समाधान के तौर पर, आप उन फ़्लैग को साफ़ तौर पर आइटम कर सकते हैं जो आपके ट्रांज़िशन के कॉन्फ़िगरेशन का हिस्सा हैं. इसमें --config और #39

एक से ज़्यादा बिल्ड सेटिंग बदलने की सुविधा

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

# 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:ऐप्लिकेशन, जो दो टारगेट पर निर्भर करता है, //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= &kot;\(b_0b_1...b_n\)&कोटेशन; सभी \(b_i\) में \(\{0,1\}\).

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

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

इसके बारे में और पढ़ें

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