এই পৃষ্ঠাটি স্টারলার্ক কনফিগারেশনের সুবিধা এবং মৌলিক ব্যবহার কভার করে, আপনার প্রকল্প কীভাবে তৈরি হয় তা কাস্টমাইজ করার জন্য Bazel এর API। এটি বিল্ড সেটিংস কিভাবে সংজ্ঞায়িত করতে হয় এবং উদাহরণ প্রদান করে তা অন্তর্ভুক্ত করে।
এটি এটি সম্ভব করে তোলে:
- আপনার প্রকল্পের জন্য কাস্টম পতাকা সংজ্ঞায়িত করুন,
--define
এর প্রয়োজনীয়তা অপ্রচলিত - তাদের পিতামাতার চেয়ে ভিন্ন কনফিগারেশনে deps কনফিগার করার জন্য রূপান্তর লিখুন (যেমন
--compilation_mode=opt
বা--cpu=arm
) - নিয়মে আরও ভাল ডিফল্ট বেক করুন (যেমন স্বয়ংক্রিয়ভাবে তৈরি
//my:android_app
একটি নির্দিষ্ট SDK দিয়ে)
এবং আরও অনেক কিছু, সম্পূর্ণরূপে .bzl ফাইল থেকে (কোন Bazel রিলিজের প্রয়োজন নেই)। উদাহরণের জন্য bazelbuild/examples
repo দেখুন।
ব্যবহারকারী-সংজ্ঞায়িত বিল্ড সেটিংস
একটি বিল্ড সেটিং হল কনফিগারেশন তথ্যের একক অংশ। একটি কী/মান মানচিত্র হিসাবে একটি কনফিগারেশনের কথা ভাবুন। --cpu=ppc
এবং --copt="-DFoo"
সেট করা একটি কনফিগারেশন তৈরি করে যা দেখতে {cpu: ppc, copt: "-DFoo"}
। প্রতিটি এন্ট্রি একটি বিল্ড সেটিং.
copt
cpu
ঐতিহ্যবাহী পতাকাগুলি নেটিভ সেটিংস - তাদের কীগুলি সংজ্ঞায়িত করা হয় এবং তাদের মানগুলি নেটিভ বেজেল জাভা কোডের মধ্যে সেট করা হয়। Bazel ব্যবহারকারীরা শুধুমাত্র কমান্ড লাইন এবং স্থানীয়ভাবে রক্ষণাবেক্ষণ করা অন্যান্য API এর মাধ্যমে সেগুলি পড়তে এবং লিখতে পারে। নেটিভ ফ্ল্যাগগুলি এবং এপিআইগুলি যেগুলি তাদের প্রকাশ করে তা পরিবর্তন করার জন্য একটি বেজেল রিলিজ প্রয়োজন৷ ব্যবহারকারী-সংজ্ঞায়িত বিল্ড সেটিংস .bzl
ফাইলগুলিতে সংজ্ঞায়িত করা হয়েছে (এবং এইভাবে, পরিবর্তনগুলি নিবন্ধনের জন্য একটি বেজেল রিলিজের প্রয়োজন নেই)। এগুলি কমান্ড লাইনের মাধ্যমেও সেট করা যেতে পারে (যদি তারা flags
হিসাবে মনোনীত হয়, নীচে আরও দেখুন), তবে ব্যবহারকারী-সংজ্ঞায়িত রূপান্তরের মাধ্যমেও সেট করা যেতে পারে।
বিল্ড সেটিংস সংজ্ঞায়িত করা
build_setting
rule()
প্যারামিটার
বিল্ড সেটিংস হল অন্য নিয়মের মতো নিয়ম এবং স্টারলার্ক rule()
ফাংশনের build_setting
অ্যাট্রিবিউট ব্যবহার করে আলাদা করা হয়।
# example/buildsettings/build_settings.bzl
string_flag = rule(
implementation = _impl,
build_setting = config.string(flag = True)
)
build_setting
অ্যাট্রিবিউটটি একটি ফাংশন নেয় যা বিল্ড সেটিং-এর ধরন নির্ধারণ করে। টাইপটি বুল এবং string
মতো মৌলিক bool
ধরণের একটি সেটের মধ্যে সীমাবদ্ধ। বিস্তারিত জানার জন্য config
মডিউল ডকুমেন্টেশন দেখুন। নিয়মের বাস্তবায়ন ফাংশনে আরও জটিল টাইপিং করা যেতে পারে। নীচে এই সম্পর্কে আরো.
config
মডিউলের ফাংশনগুলি একটি ঐচ্ছিক বুলিয়ান প্যারামিটার, flag
নেয়, যা ডিফল্টরূপে মিথ্যাতে সেট করা থাকে। যদি flag
সত্যে সেট করা হয়, বিল্ড সেটিংটি ব্যবহারকারীদের দ্বারা কমান্ড লাইনে এবং সেইসাথে অভ্যন্তরীণভাবে নিয়ম লেখকদের দ্বারা ডিফল্ট মান এবং পরিবর্তনের মাধ্যমে সেট করা যেতে পারে। সমস্ত সেটিংস ব্যবহারকারীদের দ্বারা সেট করা উচিত নয়। উদাহরণস্বরূপ, যদি একজন নিয়ম লেখক হিসাবে আপনার কিছু ডিবাগ মোড থাকে যা আপনি পরীক্ষার নিয়মের ভিতরে চালু করতে চান, তাহলে আপনি ব্যবহারকারীদের অন্য অ-পরীক্ষা নিয়মের মধ্যে নির্বিচারে সেই বৈশিষ্ট্যটি চালু করার ক্ষমতা দিতে চান না।
ctx.build_setting_value ব্যবহার করা
সমস্ত নিয়মের মতো, বিল্ড সেটিং নিয়মগুলির বাস্তবায়ন ফাংশন রয়েছে। বিল্ড সেটিংসের মৌলিক স্টারলার্ক-টাইপ মান 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
প্যারামিটার রয়েছে যা কমান্ড লাইনে বা bazelrcs-এ একাধিকবার পতাকা সেট করার অনুমতি দেয়। তাদের ডিফল্ট মান এখনও একটি স্ট্রিং-টাইপ বৈশিষ্ট্যের সাথে সেট করা আছে:
# 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
স্থানীয় ধারণাটি আর বিদ্যমান নেই, এই ধারণাটি অনুবাদ করার একটি উপায় হল সাধারণ অন্তর্নিহিত বৈশিষ্ট্যগুলির সেট ব্যবহার করা। উদাহরণ স্বরূপ:
# 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
API-কে প্রতিস্থাপন করবে।
# 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()
ব্যবহার করে বিল্ড সেটিংসে বৈশিষ্ট্যগুলি কনফিগার করতে পারেন। বিল্ড সেটিং লক্ষ্যগুলি 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-discuss@googlegroups.com-এর সাথে যোগাযোগ করুন৷
সংজ্ঞায়িত
ট্রানজিশন নিয়মের মধ্যে কনফিগারেশন পরিবর্তন সংজ্ঞায়িত করে। উদাহরণস্বরূপ, একটি অনুরোধ যেমন "একটি অভিভাবকের চেয়ে ভিন্ন CPU-এর জন্য আমার নির্ভরতা কম্পাইল করুন" একটি ট্রানজিশন দ্বারা পরিচালিত হয়।
আনুষ্ঠানিকভাবে, একটি রূপান্তর হল একটি ইনপুট কনফিগারেশন থেকে এক বা একাধিক আউটপুট কনফিগারেশনে একটি ফাংশন। বেশিরভাগ ট্রানজিশন হল 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
} যা inputs
প্যারামিটারে transition()
থেকে ঘোষণা করা হয়েছে।
attr
হল নিয়মের গুণাবলী এবং মানগুলির একটি অভিধান যার সাথে রূপান্তর সংযুক্ত করা হয়েছে। আউটগোয়িং এজ ট্রানজিশন হিসাবে সংযুক্ত করা হলে, এই অ্যাট্রিবিউটের মানগুলি সমস্ত পোস্ট-select() রেজোলিউশনে কনফিগার করা হয়। যখন একটি ইনকামিং এজ ট্রানজিশন হিসাবে সংযুক্ত করা হয়, তখন 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"]
)
ট্রানজিশন সংযুক্ত করা হচ্ছে
ট্রানজিশন দুটি জায়গায় সংযুক্ত করা যেতে পারে: ইনকামিং প্রান্ত এবং বহির্গামী প্রান্ত। কার্যকরীভাবে এর অর্থ হল নিয়মগুলি তাদের নিজস্ব কনফিগারেশন (আগত প্রান্তের স্থানান্তর) এবং তাদের নির্ভরতাগুলির কনফিগারেশন (আউটগোয়িং এজ ট্রানজিশন) স্থানান্তর করতে পারে।
দ্রষ্টব্য: বর্তমানে স্টারলার্ক ট্রানজিশনগুলিকে নেটিভ নিয়মে সংযুক্ত করার কোন উপায় নেই। আপনার যদি এটি করার প্রয়োজন হয়, তাহলে সমাধান খুঁজে বের করতে সহায়তার জন্য bazel-discuss@googlegroups.com-এ যোগাযোগ করুন।
ইনকামিং প্রান্ত পরিবর্তন
ইনকামিং এজ ট্রানজিশন একটি transition
অবজেক্ট সংযুক্ত করে সক্রিয় করা হয় ( transition()
) দ্বারা Rule( rule()
এর cfg
প্যারামিটারে:
# 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+ হতে পারে।
এই কীগুলি কীভাবে পড়তে হয় তার জন্য ট্রানজিশন সহ অ্যাট্রিবিউট অ্যাক্সেস করা দেখুন।
নেটিভ অপশনে ট্রানজিশন
স্টারলার্ক ট্রানজিশনগুলি বিকল্প নামের একটি বিশেষ উপসর্গের মাধ্যমে নেটিভ বিল্ড কনফিগারেশন বিকল্পগুলিতে রিড এবং রাইট ঘোষণা করতে পারে।
# 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 "//command_line_option:define"
এর সাথে --define
এ রূপান্তর সমর্থন করে না। পরিবর্তে, একটি কাস্টম বিল্ড সেটিং ব্যবহার করুন। সাধারণভাবে, --define
এর নতুন ব্যবহার বিল্ড সেটিংসের পক্ষে নিরুৎসাহিত করা হয়।
Bazel --config
এ রূপান্তর সমর্থন করে না। কারণ --config
হল একটি "সম্প্রসারণ" পতাকা যা অন্যান্য ফ্ল্যাগে প্রসারিত হয়।
অত্যন্ত গুরুত্বপূর্ণভাবে, --config
এ এমন পতাকা অন্তর্ভুক্ত থাকতে পারে যা বিল্ড কনফিগারেশনকে প্রভাবিত করে না, যেমন --spawn_strategy
। বেজেল, ডিজাইন দ্বারা, এই জাতীয় পতাকাগুলিকে পৃথক লক্ষ্যে আবদ্ধ করতে পারে না। এর মানে হল ট্রানজিশনে এগুলি প্রয়োগ করার কোন সুসংগত উপায় নেই।
একটি সমাধান হিসাবে, আপনি স্পষ্টভাবে ফ্ল্যাগগুলিকে আইটেমাইজ করতে পারেন যা আপনার ট্রানজিশনে কনফিগারেশনের অংশ। এর জন্য --config
এর সম্প্রসারণ দুটি জায়গায় বজায় রাখা প্রয়োজন, যা একটি পরিচিত UI ত্রুটি।
ট্রানজিশন একাধিক বিল্ড সেটিংসের অনুমতি দেয়
একাধিক মান অনুমোদন করে এমন বিল্ড সেটিংস সেট করার সময়, সেটিংটির মান একটি তালিকার সাথে সেট করতে হবে।
# 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
টুলচেন রেজোলিউশনের সাথে সম্পর্কিত। ভবিষ্যতে, এই ধরনের পতাকার সুস্পষ্ট রূপান্তর সম্ভবত টার্গেট প্ল্যাটফর্মে রূপান্তর দ্বারা প্রতিস্থাপিত হবে।
মেমরি এবং কর্মক্ষমতা বিবেচনা
আপনার বিল্ডে ট্রানজিশন যোগ করা, এবং সেইজন্য নতুন কনফিগারেশনগুলি খরচ করে: বড় বিল্ড গ্রাফ, কম বোধগম্য বিল্ড গ্রাফ এবং ধীর বিল্ড। আপনার বিল্ড নিয়মে রূপান্তর ব্যবহার করার সময় বিবেচনা করার সময় এই খরচগুলি বিবেচনা করা মূল্যবান। কিভাবে একটি ট্রানজিশন আপনার বিল্ড গ্রাফের সূচকীয় বৃদ্ধি তৈরি করতে পারে তার একটি উদাহরণ নিচে দেওয়া হল।
খারাপ আচরণ করা তৈরি করে: একটি কেস স্টাডি
চিত্র 1. স্কেলেবিলিটি গ্রাফ একটি শীর্ষ স্তরের লক্ষ্য এবং এর নির্ভরতা দেখাচ্ছে।
এই গ্রাফটি একটি শীর্ষ স্তরের লক্ষ্য দেখায়, //pkg:app, যা দুটি লক্ষ্যের উপর নির্ভর করে, a //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
-
//pkg:i_0
এবং//pkg:i_1
\(i\) \([1..n]\)এ
কল্পনা করুন যে আপনি প্রয়োগ করেছেন ) একটি পতাকা --//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
dep \(2^n\) কনফিগার করা লক্ষ্যগুলি তৈরি করে: config.owner=
l10n-placeholder7-এ সমস্ত \(b_i\) এর জন্য config.owner= "\(b_0b_1...b_n\)\(\{0,1\}\)।
এটি বিল্ড গ্রাফটিকে লক্ষ্য গ্রাফের চেয়ে দ্রুতগতিতে বড় করে, সংশ্লিষ্ট মেমরি এবং কর্মক্ষমতা ফলাফল সহ।
TODO: এই সমস্যাগুলির পরিমাপ এবং প্রশমনের জন্য কৌশল যোগ করুন।
আরও পড়া
বিল্ড কনফিগারেশন পরিবর্তন করার বিষয়ে আরো বিস্তারিত জানার জন্য, দেখুন:
- স্টারলার্ক বিল্ড কনফিগারেশন
- Bazel কনফিগারেবিলিটি রোডম্যাপ
- শেষ থেকে শেষ উদাহরণের সম্পূর্ণ সেট