इस पेज पर Starlark कॉन्फ़िगरेशन के फ़ायदों और बुनियादी इस्तेमाल के बारे में बताया गया है, अपने प्रोजेक्ट को अपनी ज़रूरत के हिसाब से बनाने के लिए, Basel का एपीआई. इसमें यह बताया गया है कि बिल्ड सेटिंग और उदाहरण प्रदान करता है.
इसकी मदद से, ये काम किए जा सकते हैं:
- अपने प्रोजेक्ट के लिए कस्टम फ़्लैग को परिभाषित करें, ताकि
--define
- लिखें
डीपलिंक को कॉन्फ़िगर करने के लिए, ट्रांज़िशन
उनके माता-पिता की तुलना में अलग कॉन्फ़िगरेशन
(जैसे कि
--compilation_mode=opt
या--cpu=arm
) - नियमों को डिफ़ॉल्ट तौर पर बेहतर बनाएं (जैसे कि अपने-आप बनने वाली
//my:android_app
इस्तेमाल करने का तरीका जानें)
और भी बहुत कुछ, पूरी तरह से .bzl फ़ाइलों से लिया जाता है (Bzel रिलीज़ की ज़रूरत नहीं होती). ज़्यादा जानकारी के लिए,
इसके लिए bazelbuild/examples
रेपो
उदाहरण के तौर पर दिए गए हैं.
उपयोगकर्ता की ओर से तय की गई बिल्ड सेटिंग
बिल्ड सेटिंग
कॉन्फ़िगरेशन
जानकारी. कॉन्फ़िगरेशन को की/वैल्यू मैप के तौर पर देखें. --cpu=ppc
सेट किया जा रहा है
और --copt="-DFoo"
एक कॉन्फ़िगरेशन जनरेट करता है, जो ऐसा दिखता है
{cpu: ppc, copt: "-DFoo"}
. हर एंट्री एक बिल्ड सेटिंग है.
cpu
और copt
जैसे पारंपरिक फ़्लैग, नेटिव सेटिंग हैं —
उनकी कुंजियां तय होती हैं और उनकी वैल्यू, नेटिव baज़ेन JavaScript कोड में सेट होती हैं.
Basel के उपयोगकर्ता उन्हें सिर्फ़ कमांड लाइन के ज़रिए पढ़ और लिख सकते हैं
और अन्य एपीआई, जिन्हें मैन्युअल तौर पर मैनेज किया जाता है. नेटिव फ़्लैग और एपीआई में बदलाव करना
जो उन्हें एक्सपोज़ हो जाते हैं, उनके लिए बेज़ल रिलीज़ की ज़रूरत होती है. उपयोगकर्ता के हिसाब से बनाया गया बिल्ड
सेटिंग .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 लाइब्रेरी में पहले से तय सेटिंग का एक सेट होता है, जिसे बिना किसी का इस्तेमाल करना था.
उदाहरण के लिए, ऐसी सेटिंग तय करने के लिए जो स्ट्रिंग वैल्यू के सीमित सेट को स्वीकार करती हो:
# 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
बिल्ड सेटिंग के उपनामों का इस्तेमाल किया जा रहा है
आप अपनी बिल्ड सेटिंग के टारगेट पाथ के लिए उपनाम सेट कर सकते हैं, ताकि उसे आसानी से पढ़ा जा सके डालें. उपनाम, नेटिव फ़्लैग की तरह ही काम करते हैं और इनका इस्तेमाल भी करते हैं का इस्तेमाल किया जा सकता है.
--flag_alias=ALIAS_NAME=TARGET_PATH
जोड़कर उपनाम सेट करें
आपके .bazelrc
में . उदाहरण के लिए, किसी उपनाम को coffee
पर सेट करने के लिए:
# .bazelrc
build --flag_alias=coffee=//experimental/user/starlark_configurations/basic_build_setting:coffee-temp
सबसे सही तरीका: उपनाम को कई बार सेट करने पर, सबसे हाल ही में किसी एक को प्राथमिकता दें. पार्स करने के अनचाहे नतीजों से बचने के लिए, उपनाम के यूनीक नामों का इस्तेमाल करें.
उपनाम का इस्तेमाल करने के लिए, इसे बिल्ड सेटिंग टारगेट पाथ की जगह टाइप करें.
ऊपर दिए गए coffee
के उदाहरण से, उपयोगकर्ता के .bazelrc
में सेट किया गया:
$ 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()
. बिल्ड सेटिंग के टारगेट को, इसकी flag_values
एट्रिब्यूट में पास किया जा सकता है
config_setting
. कॉन्फ़िगरेशन से मेल खाने वाली वैल्यू,
इसके बाद, 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"
)
ट्रांज़िशन जोड़कर, आप बड़ी आसानी से बिल्ड ग्राफ़ मिल सकता है. यह उन पैकेज के लिए अनुमति वाली सूची सेट करता है जिनमें ये काम किए जा सकते हैं इस नियम के टारगेट बनाएं. ऊपर दिए गए कोडब्लॉक में डिफ़ॉल्ट वैल्यू अनुमति वाली सूची में सब कुछ शामिल है. लेकिन यदि आप इसे सीमित करना चाहते हैं कि आपके नियम का उपयोग कौन कर सकता है, आपके पास इस एट्रिब्यूट को इस तरह सेट करने का विकल्प होता है कि उपयोगकर्ताओं को, पसंद के मुताबिक बनाई गई आपकी अनुमति वाले चैनलों पर ले जाया जा सके. अगर आपको सलाह या सहायता चाहिए, तो baज़ेन-discuss@googlegroups.com पर संपर्क करें यह समझना कि ट्रांज़िशन आपके बिल्ड की परफ़ॉर्मेंस पर कैसे असर डाल सकते हैं.
परिभाषा तय करना
ट्रांज़िशन से, नियमों के बीच कॉन्फ़िगरेशन में होने वाले बदलावों का पता चलता है. उदाहरण के लिए, अनुरोध जैसे, "मेरी डिपेंडेंसी को किसी दूसरे सीपीयू के लिए कंपाइल करें" एक ट्रांज़िशन है.
औपचारिक रूप से, ट्रांज़िशन एक फ़ंक्शन है, जो किसी इनपुट कॉन्फ़िगरेशन से एक या एक से ज़्यादा पर होता है
आउटपुट कॉन्फ़िगरेशन. ज़्यादातर ट्रांज़िशन 1:1 होते हैं, जैसे कि "इनपुट बदलें
कॉन्फ़िगरेशन को --cpu=ppc
" के साथ कॉन्फ़िगर किया गया है. 1:2+ ट्रांज़िशन भी मौजूद हो सकते हैं, लेकिन
खास पाबंदियों के साथ.
स्टारलार्क में, ट्रांज़िशन को काफ़ी हद तक नियमों की तरह परिभाषित किया जाता है.
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
, एलान की गई सभी सेटिंग का डिक्शनरी {String
:Object
} है
transition()
के लिए inputs
पैरामीटर में.
attr
नियम की विशेषताओं और मानों का एक शब्दकोश है, जिसे
ट्रांज़िशन अटैच किया गया है. जब
आउटगोइंग किनारे का ट्रांज़िशन, इनके मान
एट्रिब्यूट, सभी पोस्ट-select() रिज़ॉल्यूशन को कॉन्फ़िगर किए गए हैं. इस रूप में अटैच किए जाने पर
इनकमिंग एज ट्रांज़िशन में, 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-discuss@googlegroups.com और समस्या को हल करने में मदद पाएं.
इनकमिंग एज ट्रांज़िशन
transition
ऑब्जेक्ट अटैच करके, इनकमिंग एज ट्रांज़िशन चालू किए जाते हैं
(transition()
ने बनाया) rule()
के cfg
पैरामीटर से:
# example/rules.bzl
load("example/transitions:transitions.bzl", "hot_chocolate_transition")
drink_rule = rule(
implementation = _impl,
cfg = hot_chocolate_transition,
...
इनकमिंग एज ट्रांज़िशन 1:1 ट्रांज़िशन होने चाहिए.
आउटगोइंग एज ट्रांज़िशन
transition
ऑब्जेक्ट अटैच करके, आउटगोइंग एज ट्रांज़िशन चालू किए जाते हैं
(transition()
ने बनाया) को एट्रिब्यूट के 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+ हो सकते हैं.
ट्रांज़िशन वाले एट्रिब्यूट ऐक्सेस करना देखें का इस्तेमाल करने के लिए तैयार हैं.
नेटिव विकल्पों के हिसाब से ट्रांज़िशन
स्टारलार्क ट्रांज़िशन, नेटिव बिल्ड पर रीड और राइट्स का एलान भी कर सकते हैं कॉन्फ़िगरेशन विकल्पों का इस्तेमाल करें.
# 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"]
असमर्थित निजी विकल्प
Basel, --define
पर इस ऐप्लिकेशन के साथ ट्रांज़िशन की सुविधा नहीं देती
"//command_line_option:define"
. इसके बजाय, किसी कस्टम
build सेटिंग पर सेट करें. आम तौर पर,
--define
को बिल्ड सेटिंग इस्तेमाल करने की सलाह नहीं दी जाती है.
Basel, --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
- \([1..n]\) \(i\) में
//pkg:i_0
और//pkg:i_1
मान लें कि आपने किसी फ़्लैग का इस्तेमाल लागू किया है
--//foo:owner=<STRING>
और //pkg:i_b
लागू होती हैं
depConfig = myConfig + depConfig.owner="$(myConfig.owner)$(b)"
दूसरे शब्दों में, //pkg:i_b
सभी के लिए --owner
की पुरानी वैल्यू में b
को जोड़ देता है
इसके डिपार्टमेंट भी हैं.
इससे, ये कॉन्फ़िगर किए गए टारगेट जनरेट होते हैं:
//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\}\).
इससे बिल्ड ग्राफ़, टारगेट ग्राफ़ की तुलना में बहुत ज़्यादा बड़ा हो जाता है. साथ ही, इससे जुड़ी मेमोरी और परफ़ॉर्मेंस पर असर पड़ सकता है.
काम की सूची: इन समस्याओं के आकलन और उन्हें कम करने के लिए रणनीतियां जोड़ें.
इसके बारे में और पढ़ें
बिल्ड कॉन्फ़िगरेशन में बदलाव करने के बारे में ज़्यादा जानकारी के लिए, यहां देखें:
- Starlark बिल्ड का कॉन्फ़िगरेशन
- बेज़ल कॉन्फ़िगर करने की क्षमता का रोडमैप
- शुरू से अंत तक के उदाहरणों का पूरा सेट