Bazel יכולה לבנות ולבחון קוד במגוון חומרה, מערכות הפעלה ותצורות מערכת, באמצעות גרסאות שונות של כלי בנייה כמו מקשרים ומהדרים. כדי לנהל את המורכבות הזו, ל-Bazel יש מושג לגבי מגבלות ופלטפורמות. אילוץ הוא מאפיין שבו סביבות הבנייה או ההפקה עשויות להיות שונות, כמו ארכיטקטורת מעבד (CPU), נוכחות של מעבד גרפי (CPU) או היעדר מכונה, או גרסת מהדר שהותקן על ידי המערכת. פלטפורמה היא אוסף עם שם של האפשרויות האלה, המייצג את המשאבים הספציפיים הזמינים בסביבה מסוימת.
יצירת סביבה כפלטפורמה עוזרת ל-Bazel לבחור באופן אוטומטי את שרשראות הכלים המתאימות לפעולות build. אפשר גם להשתמש בפלטפורמות בשילוב עם הכלל config_setting כדי לכתוב מאפיינים שאפשר להגדיר.
Bazel מזהה שלושה תפקידים שפלטפורמה יכולה למלא:
- מארח – הפלטפורמה שבה פועל Bazel עצמה.
- ביצוע – פלטפורמה שבה כלי ה-build מבצעים פעולות build כדי ליצור פלט ביניים ופלט סופי.
- Target – פלטפורמה שבה ממוקם הפלט הסופי ומבצע אותו.
Bazel תומכת בתרחישי build הבאים בנוגע לפלטפורמות:
גרסאות build של פלטפורמה יחידה (ברירת מחדל) – פלטפורמות מארח, ביצוע ויעד זהות. לדוגמה, בניית הפעלה של Linux ב-Ubuntu פועלת במעבד Intel x64.
יצירת אוספים בהרכבות שונות – פלטפורמת האירוח והפלטפורמה זהות, אבל פלטפורמת היעד שונה. לדוגמה, בניית אפליקציה ל-iOS ב-macOS Pro ב-MacBook Pro.
פלטפורמות ליצירת פלטפורמות מרובות – המארחות, הביצוע ופלטפורמות היעד שונות זו מזו.
הגדרת אילוצים ופלטפורמות
המרחב המשותף של אפשרויות אפשריות לפלטפורמות מוגדר באמצעות
הכללים constraint_setting
ו-constraint_value
בתוך קובצי BUILD
. המאפיין constraint_setting
יוצר מאפיין חדש, ואילו constraint_value
יוצר ערך חדש למאפיין נתון. יחד, הם מגדירים בפועל 'enum' (ערכים) ואת הערכים האפשריים שלהם. לדוגמה, קטע הקוד הבא של קובץ BUILD
מציין מגבלה לגרסת ה-glibc של המערכת עם שני ערכים אפשריים.
constraint_setting(name = "glibc_version")
constraint_value(
name = "glibc_2_25",
constraint_setting = ":glibc_version",
)
constraint_value(
name = "glibc_2_26",
constraint_setting = ":glibc_version",
)
ניתן להגדיר מגבלות וערכים בחבילות שונות בסביבת העבודה. הם מוזכרים בתווית, והם כפופים לאמצעי הבקרה הרגילים על הרשאות גישה. אם הרשאות הגישה מאפשרות לכם, תוכלו להרחיב הגדרת הגבלה קיימת על ידי הגדרת הערך שלכם עבורה.
הכלל platform
משיק פלטפורמה חדשה עם אפשרויות מסוימות לקביעת ערכי אילוץ. בהמשך מופיעה פלטפורמה בשם linux_x86
שאומרת שהיא מתארת סביבה שמריצה מערכת הפעלה של Linux עם ארכיטקטורת x86_64 עם גרסה 2.25 של Glibc. (ראו מידע נוסף על אילוצים מובנים של Bazel').
platform(
name = "linux_x86",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
":glibc_2_25",
],
)
אילוצים ופלטפורמות שימושיים באופן כללי
כדי לשמור על עקביות בסביבה העסקית, צוות Bazel מנהל מאגר עם הגדרות מוגבלות לארכיטקטורות ה-CPU ומערכות ההפעלה הפופולריות ביותר. כל אלה נמצאים בכתובת https://github.com/bazelbuild/platforms.
Bazship ships עם ההגדרה המיוחדת הבאה של הפלטפורמה:
@local_config_platform//:host
. זהו הערך של פלטפורמת המארח שזוהה באופן אוטומטי – מייצג את הפלטפורמה שזוהתה באופן אוטומטי עבור המערכת ש-Bazel פועל בה.
ציון פלטפורמה עבור build
אפשר לציין את פלטפורמת המארח ואת פלטפורמת היעד לגרסת ה-build באמצעות הסימונים הבאים בשורת הפקודה:
--host_platform
– ברירת מחדל היא@bazel_tools//platforms:host_platform
--platforms
– ברירת מחדל היא@bazel_tools//platforms:target_platform
מדלג על יעדים לא תואמים
כשמפתחים פלטפורמת פלטפורמה ספציפית, לעיתים קרובות עדיף לדלג על יעדים אף פעם לא יפעלו בפלטפורמה הזו. לדוגמה, סביר להניח שהנהג של מכשיר Windows יפיק הרבה שגיאות מהדר במהלך יצירה במחשב Linux עם //...
. משתמשים במאפיין
target_compatible_with
כדי לספר ל-Bazel אילו מגבלות יש לקוד של פלטפורמת היעד.
השימוש הפשוט ביותר במאפיין הזה מגביל יעד לפלטפורמה יחידה.
היעד לא יהיה מבוסס על פלטפורמה שלא עומדת בכל המגבלות. בדוגמה הבאה, win_driver_lib.cc
מוגבל ל-64 ביט של Windows.
cc_library(
name = "win_driver_lib",
srcs = ["win_driver_lib.cc"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
],
)
:win_driver_lib
תואם רק לבניית Windows 64 ביט, והוא לא תואם לכל השאר. חוסר תאימות הוא חולף. כל יעד שמבוסס באופן זמני על יעד לא תואם ייראה לא תואם.
מתי מדלגים על יעדים?
המערכת תדלג על מטרות עסקיות אם הן ייחשבו לא תואמות ונכללו במסגרת כחלק מהרחבת יעד. לדוגמה, שתי ההפעלות הבאות מדלגות על יעדים לא תואמים שנמצאו בהרחבת תבנית יעד.
$ bazel build --platforms=//:myplatform //...
$ bazel build --platforms=//:myplatform //:all
המערכת תדלג באופן דומה על בדיקות לא תואמות ב-test_suite
גם אם ה-test_suite
מצוין בשורת הפקודה עם --expand_test_suites
.
כלומר, test_suite
יעדים בשורת הפקודה מתנהגים כמו :all
ו-...
. השימוש ב---noexpand_test_suites
מונע הרחבה וגורם
גם לחוסר התאמה בtest_suite
יעדים עם בדיקות לא תואמות.
ציון מפורש של יעד לא תואם בשורת הפקודה מוביל להודעת שגיאה ולבנייה נכשלה.
$ bazel build --platforms=//:myplatform //:target_incompatible_with_myplatform
...
ERROR: Target //:target_incompatible_with_myplatform is incompatible and cannot be built, but was explicitly requested.
...
FAILED: Build did NOT complete successfully
אילוצים מבטאים יותר
אם אתם לא רוצים לבטא אילוצים, אפשר להשתמש
@platforms//:incompatible
constraint_value
בפלטפורמה שלא עומדת בדרישות שלנו.
השתמשו ב-select()
בשילוב עם
@platforms//:incompatible
כדי לבטא הגבלות מורכבות יותר. לדוגמה, השתמשו בו כדי ליישם לוגיקת OR בסיסית. ברשימה שבהמשך מצוין ספרייה שתואמת ל-macOS ול-Linux, אבל לא קיימות פלטפורמות אחרות.
cc_library(
name = "unixish_lib",
srcs = ["unixish_lib.cc"],
target_compatible_with = select({
"@platforms//os:osx": [],
"@platforms//os:linux": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
)
אפשר לפרש את המידע הזה באופן הבא:
- כשמטרגטים ל-macOS, אין הגבלות.
- כשמטרגטים ל-Linux, אין הגבלות.
- אם לא, היעד כולל את המגבלה
@platforms//:incompatible
. היעד@platforms//:incompatible
לא שייך לפלטפורמה כלשהי, ולכן הוא לא תואם.
כדי שהאילוצים יהיו קריאים יותר, השתמשו ב-skylib'sselects.with_or()
.
אתם יכולים לבטא תאימות הפוכה באופן דומה. הדוגמה הבאה מתארת ספרייה שתואמת לכל דבר למעט ARM.
cc_library(
name = "non_arm_lib",
srcs = ["non_arm_lib.cc"],
target_compatible_with = select({
"@platforms//cpu:arm": ["@platforms//:incompatible"],
"//conditions:default": [],
],
)
זיהוי יעדים לא תואמים באמצעות bazel cquery
אתם יכולים להשתמש
IncompatiblePlatformProvider
בפורמט סטארליק
bazel cquery
כדי להבחין בין יעדים לא תואמים ליעדים תואמים.
אפשר להשתמש במסנן הזה כדי לסנן יעדים שאינם תואמים. בדוגמה הבאה תודפס רק תוויות של יעדים תואמים. יעדים לא תואמים לא מודפסים.
$ cat example.cquery
def format(target):
if "IncompatiblePlatformProvider" not in providers(target):
return target.label
return ""
$ bazel cquery //... --output=starlark --starlark:file=example.cquery
בעיות ידועות
יעדים לא תואמים מתעלמים מהגבלות החשיפה.