דף זה מכסה את היתרונות ואת השימוש הבסיסי בהגדרות של Starlark, Bazel's API להתאמה אישית של בניית הפרויקט. הוא כולל איך לקבוע את הגדרות Build ומספק דוגמאות.
זה מאפשר:
- הגדרת סימונים מותאמים אישית לפרויקט, כך שלא יהיה צורך
ב
--define
- כתוב
מעברים כדי להגדיר את נקודות המבט
בתצורות השונות מאלה של ההורים
(למשל
--compilation_mode=opt
או--cpu=arm
) - החלת ברירות מחדל טובות יותר על כללים (למשל, יצירה אוטומטית של
//my:android_app
באמצעות SDK ספציפי)
ועוד, והכול מתוך קובצי bzl (אין צורך במהדורת Bazel). להצגת
bazelbuild/examples
הדוגמאות .
הגדרות build בהגדרת המשתמש
הגדרת build היא קטע יחיד של
הגדרות. אפשר לחשוב על הגדרה בתור מפת מפתח/ערך. ההגדרות --cpu=ppc
ו---copt="-DFoo"
יוצרות הגדרה שנראית
{cpu: ppc, copt: "-DFoo"}
. כל רשומה היא הגדרת build.
סימונים מסורתיים כמו cpu
ו-copt
הם הגדרות מקוריות –
המפתחות שלהם מוגדרים והערכים שלהם מוגדרים בתוך קוד JavaScript מקורי של bzel.
משתמשי Bazel יכולים לקרוא ולכתוב אותם רק דרך שורת הפקודה וממשקי API אחרים שמתחזקים באופן מקורי. כדי לשנות דגלים מקומיים ואת ממשקי ה-API שחושפים אותם, יש צורך בקוד בסיס. הגדרות ה-build
שמוגדרות על ידי המשתמשים מוגדרות ב-.bzl
קבצים (ולכן אין צורך לשחרר את הבסיס כדי לרשום שינויים). ניתן גם להגדיר אותם דרך שורת הפקודה
(אם הם מוגדרים כ-flags
, ראו מידע נוסף בהמשך), אך ניתן להגדיר אותם גם באמצעות מעברים שמוגדרים על ידי המשתמש.
קביעת הגדרות build
הפרמטר build_setting
rule()
הגדרות build הן כללים כמו כל כלל אחר, והן מובדלות באמצעות הפונקציה Starlark rule()
's build_setting
.
# example/buildsettings/build_settings.bzl
string_flag = rule(
implementation = _impl,
build_setting = config.string(flag = True)
)
המאפיין build_setting
מקבל פונקציה שקובעת את סוג הגדרת ה-build. סוג זה מוגבל לקבוצה של סוגים בסיסיים של Starlark, כגון bool
ו-string
. פרטים נוספים זמינים בconfig
מודול
התיעוד. ניתן לבצע הקלדה מורכבת יותר
בפונקציית ההטמעה של הכלל. מידע נוסף בנושא מפורט בהמשך.
הפונקציות של המודול config
'S כוללות פרמטר בוליאני אופציונלי, flag
,
שמוגדר כברירת מחדל כ-False. אם flag
מוגדר כ-true, ניתן לקבוע את הגדרת ה-build
בשורת הפקודה על ידי משתמשים וכן באופן פנימי על ידי כותבי כללים
באמצעות ערכי ברירת מחדל ומעברים.
לא כל ההגדרות צריכות להיות מוגדרות על ידי משתמשים. לדוגמה, אם ככותב של כלל
יש לך מצב ניפוי באגים ואתם רוצים להפעיל אותו במסגרת כללי הבדיקה,
אתם לא רוצים לתת למשתמשים את היכולת להפעיל את התכונה
ללא כללים נפרדים.
שימוש ב-ctx.build_setting_value
כמו בכל הכללים, גם לכללים ליצירת הגדרות יש פונקציות הטמעה.
ניתן לגשת לערך הבסיסי של סוג Starlark של הגדרות build
בשיטה ctx.build_setting_value
. השיטה הזו זמינה רק ל
ctx
אובייקטים של כללי הגדרה של build. שיטות ההטמעה האלה יכולות להעביר את הערך של הגדרות ה-build ישירות או לבצע בו פעולות נוספות כמו בדיקת סוג או יצירת מבנה מורכב יותר. כך תטמיעו הגדרת build בהקלדה של 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 מידיות
לכללים שהוגדרו עם הפרמטר 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 כוללת קבוצה של הגדרות מוגדרות מראש שניתן ליצור ללא צורך בכתיבה כדי להשתמש בתכונה Starlark בהתאמה אישית.
לדוגמה, כדי לקבוע הגדרה שמקבלת קבוצה מוגבלת של ערכי מחרוזת:
# example/BUILD
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
string_flag(
name = "myflag",
values = ["a", "b", "c"],
build_setting_default = "a",
)
רשימה מלאה זמינה במאמר כללים נפוצים להגדרת גרסת build.
שימוש בהגדרות build
בהתאם להגדרות ה-build
אם יעד מסוים רוצה לקרוא מידע על הגדרה, הוא יכול תלוי ישירות בהגדרת ה-build באמצעות תלות רגילה של מאפיינים.
# 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)
שימוש בהגדרות של build בשורת הפקודה
בדומה לרוב הסימונים המקומיים, ניתן להשתמש בשורת הפקודה כדי לקבוע הגדרות build
שמסומנות כסימונים. שם ההגדרה של ה-build הוא נתיב היעד המלא שלו באמצעות תחביר 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
שימוש בכינויים של הגדרות build
אפשר להגדיר כינוי בנתיב היעד של ההגדרה כדי שיהיה קל יותר לקרוא אותו בשורת הפקודה. כינויים משמשים בדומה לסימונים מקומיים ומשתמשים בתחביר של אפשרות המקף הכפול.
מגדירים כינוי על ידי הוספת --flag_alias=ALIAS_NAME=TARGET_PATH
ל-.bazelrc
. לדוגמה, כדי להגדיר כינוי כ-coffee
:
# .bazelrc
build --flag_alias=coffee=//experimental/user/starlark_configurations/basic_build_setting:coffee-temp
שיטה מומלצת: הגדרת מספר פעמים של כתובת אימייל חלופית תיתן לו את הכינוי המועדף. השתמשו בשמות ייחודיים של כתובות אימייל חלופיות כדי להימנע מתוצאות ניתוח לא מכוונות.
כדי להשתמש בכינוי, יש להקליד אותו במקום את נתיב היעד של הגדרת ה-build.
בדוגמה שלמעלה של coffee
שהוגדר ב.bazelrc
של המשתמש:
$ bazel build //my/target --coffee=ICED
במקום
$ bazel build //my/target --//experimental/user/starlark_configurations/basic_build_setting:coffee-temp=ICED
שיטה מומלצת: אמנם אפשר להגדיר כינויים בשורת הפקודה, אבל השארתם
ב.bazelrc
מפחיתה את העומס בשורת הפקודה.
הגדרות של build לפי תווית
בניגוד להגדרות build אחרות, לא ניתן להגדיר הגדרות שמבוססות על תוויות באמצעות הפרמטר
build_setting
של הכלל. במקום זאת, לבוז יש שני כללים מובנים:
label_flag
וlabel_setting
. כללים אלה מעבירים את הספקים של היעד שאליו מוגדרת הגדרת ה-build בפועל. 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"
)
Build settings ו-select()
המשתמשים יכולים לקבוע מאפיינים בהגדרות build באמצעות
select()
. ניתן להעביר יעדים של הגדרת build אל המאפיין flag_values
של
config_setting
. הערך שיש להתאים לתצורה מועבר כ-String
, ולאחר מכן מנתחים אותו לסוג ההגדרה של build לצורך התאמה.
config_setting(
name = "my_config",
flag_values = {
"//example:favorite_flavor": "MANGO"
}
)
מעברים שמוגדרים על ידי המשתמש
מעבר 'תצורה' ממופה את הטרנספורמציה מיעד אחד לאחר בתרשים הבנייה.
כללים שמגדירים אותם חייבים לכלול מאפיין מיוחד:
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist"
)
על ידי הוספת מעברים אתם יכולים די להרחיב את הגודל של תרשים ה-build שלכם. פעולה זו מגדירה רשימת היתרים בחבילות שבהן אפשר ליצור יעדים של הכלל הזה. ערך ברירת המחדל בבלוק הקוד מופיע ברשימת ההיתרים. אבל אם רוצים להגביל את המשתמשים בכלל, אפשר להגדיר את המאפיין הזה כך שיפנה לרשימת ההיתרים המותאמת אישית. אפשר לפנות אל bazel-דיון@googlegroups.com אם אתם רוצים לקבל עצות או סיוע כדי להבין איך מעברים יכולים להשפיע על הביצועים.
הגדרה
מעברים מגדירים שינויים בתצורה בין כללים. לדוגמה, בקשה כמו "מדביקת את התלות במעבד מרכזי (CPU) השונה מזה של ההורה והציטוט שלה; מטופלת במסגרת מעבר.
באופן רשמי, מעבר הוא פונקציה מהגדרת קלט לתצורה אחת או יותר של פלט. רוב המעברים הם ביחס גובה-רוחב של 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()
מקבלת פונקציית הטמעה, קבוצה של הגדרות build לקריאה (inputs
) וקבוצה של הגדרות build לצורך כתיבה
(outputs
). פונקציית ההטמעה כוללת שני פרמטרים, settings
ו-attr
. settings
הוא מילון {String
:Object
} מכל ההגדרות שצוינו
בפרמטר inputs
אל transition()
.
attr
הוא מילון של מאפיינים וערכים של הכלל שאליו מצורף המעבר. כשמצרפים אותם כמעבר קצה יוצא, כל הערכים של המאפיינים האלה מוגדרים ברזולוציה של פוסט-בחירה() . כשמצרפים אותם כמעבר קצה נכנס, attr
לא כולל מאפיינים שמשתמשים בבורר כדי לפתור את הערך שלהם. אם
מעבר קצה נכנס ב---foo
קורא את המאפיין bar
ולאחר מכן בוחר גם ב---foo
כדי להגדיר את המאפיין bar
, יש סיכוי
שהמעבר הנכנס יתחיל לקרוא את הערך השגוי של bar
במעבר.
פונקציית ההטמעה חייבת להחזיר מילון (או רשימה של מילונים, במקרה של מעברים עם מספר תצורות פלט) של ערכי הגדרות build חדשים. המפתחות שהוחזרו למילון חייבים
להכיל בדיוק את הקבוצה של הגדרות build שהועברו לפרמטר outputs
של פונקציית המעבר. הדבר נכון גם אם הגדרת build
לא משתנה בפועל במהלך המעבר – הערך המקורי שלה
חייב לעבור במפורש במילון שהוחזרה.
הגדרת 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-דיון@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+.
למידע על קריאת המקשים האלה, עיינו בקטע גישה למאפיינים באמצעות מעברים.
מעברים בין אפשרויות מותאמות
מעברי Starlark יכולים גם להצהיר על כתיבה וכתיבה על אפשרויות תצורה ב-build מותאמות באמצעות קידומת מיוחדת לשם האפשרות.
# 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
לטובת הגדרות build.
Bazel אינה תומכת במעבר ב---config
. הסיבה לכך היא שהסימון --config
הוא "span" המתרחב לסימונים אחרים.
באופן מהותי, ייתכן ש---config
יכלול סימונים שלא משפיעים על הגדרת ה-build,
למשל
--spawn_strategy
. Bazel, בעיצוב, לא יכולה לקשר סימונים כאלה ליעדים נפרדים. כלומר,
אין דרך עקבית להחיל אותם במעברים.
כפתרון, ניתן לציין במפורש את הסימונים העשויים להיות חלק מהתצורה שבמעבר שלך. לשם כך, אנחנו צריכים לשמור על הרחבה של --config

בשני מקומות, וזה פגם ידוע בממשק המשתמש.
אפשרות המעברים מופעלת במספר הגדרות של build
כשקובעים הגדרות build שמאפשרות לאפשר להזין מספר ערכים, יש לקבוע ערך של רשימה באמצעות רשימה.
# 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
, קשורים לרזולוציית הרשת. בעתיד נעביר את המעברים ה מפורשים לסוגים
כאלה של סימונים על ידי מעבר
בפלטפורמת היעד.
שיקולי זיכרון וביצועים
הוספת מעברים (ולכן גם תצורות חדשות) לגרסאות build כרוכה בעלות: תרשימי build גדולים יותר, פחות תרשימים של גרסאות מובנות ומבנה איטי יותר. כדאי לשקול את העלויות האלה כשבוחנים את המעברים בכללי הבנייה. הדוגמה הבאה ממחישה איך מעבר עשוי ליצור צמיחה מעריכת של תרשים ה-build שלך.
גרסאות build שהתנהגו באופן שגוי: מקרה לדוגמה
איור 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
מצרף 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\}\).
באופן זה, תרשים ה-build גדול באופן משמעותי על סמך תרשים היעד. עם השלכות תואמות על הזיכרון והביצועים.
להתחלת התהליך: מוסיפים שיטות למדידה ולצמצום הבעיות.
קריאה נוספת
פרטים נוספים על שינוי הגדרות build זמינים בכתובת:
- תצורת Starlark Build
- מפת הדרכים של Bazel Configurability
- קבוצת מלאה של דוגמאות מקצה לקצה