בנייה עם פלטפורמות

ל-Bazel יש תמיכה מתוחכמת לבניית מודלים של פלטפורמות וכלי רשת. שילוב כזה עם פרויקטים אמיתיים מצריך שיתוף פעולה יעיל בין בעלי קודים, מתחזקי כללים ומפתחי Bazel ליבה.

בדף הזה מופיע סיכום של מטרת הפלטפורמות ומוסבר איך לבנות אותן ביחד.

tl;dr: ממשקי API של Bazel' זמינים, אבל הם לא יפעלו בכל מקום עד שכל כללי השפה, select() והפניות מדור קודם אחרות יתעדכנו. העבודה מתבצעת. בסופו של דבר, כל גרסאות ה-build יהיו מבוססות על פלטפורמה. בהמשך אפשר לראות איפה ה-build שלך מתאים.

לקבלת מידע רשמי יותר, אפשר לעיין במאמרים הבאים:

רקע

פלטפורמות ושרשראות כלים הושקו כדי לתקן את האופן שבו פרויקטים בתוכנות מטרגטים מכונות שונות ובונים אותם באמצעות כלי השפה המתאימים.

זוהי תוספת יחסית יחסית לבזל. בהשראת התפיסה, הבודקים כבר עשו זאת באופן אד-הוק. לדוגמה, כללי C++ משתמשים ב---cpu וב---crosstool_top כדי להגדיר מעבד יעד (CPU) וכלי כלי +C++. אף אחד מהם לא יוצר מודל תקין ל-"platform". ניסיונות היסטוריים לעשות זאת גרמו לפיתוחים מביכים ולא מדויקים. הסימונים האלה גם לא שולטים באוסף Java, שפיתח ממשק עצמאי משלו עם --java_toolchain.

Bazel מיועדת לפרויקטים גדולים מרובי שפות, מרובי פלטפורמות. לשם כך צריכה להיות תמיכה רבה יותר בקונספטים האלה, כולל ממשקי API ברורים שמעודדים שפה ויכולת פעולה הדדית של פרויקטים. זאת המטרה של ממשקי ה-API החדשים.

העברה

ממשקי ה-API של הפלטפורמה וכלי הכלים פועלים רק כשהפרויקטים משתמשים בהם בפועל. זה לא טריגר, כי הלוגיקה של הפרויקט, שרשראות הכלים, התלויות וה-select() צריכים להיות נתמכים. לשם כך, צריך רצף מיגרציה ברור כדי שכל הפרויקטים והתלות שלהם יהיו תקינים.

לדוגמה, פלטפורמות התמיכה של Bazel'sC++ . אבל כללי Apple אינם עושים זאת. ייתכן שפרויקט C++ לא ישפיע על Apple. אבל ייתכן שאחרים יעשו זאת. לכן עדיין לא בטוח להפעיל בכל העולם פלטפורמות לכל גרסאות ה-C+.

שאר הדף הזה מתאר את רצף המיגרציה הזה ואיך הפרויקטים יכולים להתאים.

יעד

העברת הפלטפורמה של Bazel' מתבצעת כאשר כל הפרויקטים בונים באמצעות הטופס:

bazel build //:myproject --platforms=//:myplatform

כלומר:

  1. לפי הכללים שהפרויקט שלך משתמש בהם, אפשר להסיק מחזיקי כלים נכונים מתוך //:myplatform.
  2. הכללים שהתלויים בפרויקט שלך יכולים להסיק מהם ערכות כלים נכונות מ-//:myplatform.
  3. כל הפרויקטים, בהתאם לפרויקטים שלכם, תומכים ב-//:myplatform או בפרויקט שלכם שתומך בממשקי API מדור קודם (כמו --crosstool_top).
  4. //:myplatform הפניות [הצהרות נפוצות][הצהרת פלטפורמה משותפת]{: .external} של CPU, OS ומושגים כלליים אחרים שתומכים בתאימות אוטומטית בין פרויקטים.
  5. כל הפרויקטים הרלוונטיים' select()s להבין את מאפייני המכונה שמשתמע מהם //:myplatform.
  6. //:myplatform מוגדר במקום ברור לשימוש חוזר: בנכס ובפרויקט שלכם, אם הפלטפורמה ייחודית לפרויקט שלכם, אחרת כל הפרויקטים שעשויים להשתמש בה יוכלו למצוא אותה.

ממשקי ה-API הישנים יוסרו ברגע שתגיעו ליעד הזה. לאחר מכן זו תהיה הדרך הרגילה שבה פרויקטים בוחרים בפלטפורמות ובערכות כלים.

האם כדאי להשתמש בפלטפורמות?

אם אתם רק רוצים לבנות פרויקט או לבצע הידור מוצלב, עליכם לעקוב אחר התיעוד הרשמי של הפרויקט.

אם אתם פרויקטים, שפות או תחזוקת כלי עבודה, בסופו של דבר תרצו לתמוך בממשקי ה-API החדשים. אם אתם ממתינים עד שההעברה הגלובלית תושלם או אם תביעו הסכמה בשלב מוקדם, הערך תלוי בעלות / בערך הספציפיים שלכם:

ערך

  • תוכלו select() או לבחור ערכות כלים בנכסים המדויקים שחשובים לכם, במקום לבצע התרעות לגבי קידודים קשיחים כמו --cpu. לדוגמה, מעבדים שונים יכולים לתמוך באותה קבוצת הוראה.
  • גרסאות build נכונות יותר. אם בדוגמה המתוארת למעלה יש select() ו---cpu נוספו, יחידת CPU חדשה שתומכת באותה קבוצת הוראה נכשלה, ה-select() ייכשל לזיהוי המעבד החדש. אבל select() בפלטפורמות נשארות מדויקות.
  • חוויית משתמש פשוטה יותר. כל הפרויקטים מבינים: --platforms=//:myplatform. אין צורך בסימונים ספציפיים לשפה בשורת הפקודה.
  • עיצוב שפה פשוט יותר. לכל השפות יש API משותף להגדרת ערכות כלים, לשימוש בערכות כלים ולבחירת שרשרת הכלים המתאימה לפלטפורמה.
  • ניתן לדלג על יעדים בשלב היצירה והבדיקה אם הם לא תואמים לפלטפורמת היעד.

עלויות

  • ייתכן שפרויקטים תלויים שעדיין לא תומכים בפלטפורמות לא יפעלו באופן אוטומטי עם הפרויקט שלכם.
  • כדי שהן יפעלו, ייתכן שתצטרכו תחזוקה זמנית נוספת.
  • כדי להימנע מבלבול, יש צורך בהנחיה זהירה יותר בקרב משתמשים חדשים וממשקי API מדור קודם.
  • ההגדרות הקנוניות של נכסים משותפים כמו OS ו-CPU עדיין מתפתחות, וייתכן שיהיה צורך להוסיף להן נתונים ראשוניים.
  • ההגדרות הקנוניות לערכות כלים הספציפיות לשפה עדיין מתפתחות, וייתכן שיהיה צורך להוסיף להן תרומות ראשוניות.

בדיקת API

platform הוא אוסף של constraint_value יעדים:

platform(
    name = "myplatform",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:arm",
    ],
)

constraint_value הוא מאפיין של מחשב. ערכים של אותו &מירכאות;סוג" מקובצים תחת מאפיין משותף constraint_setting:

constraint_setting(name = "os")
constraint_value(
    name = "linux",
    constraint_setting = ":os",
)
constraint_value(
    name = "mac",
    constraint_setting = ":os",
)

toolchain הוא כלל Starstark. המאפיינים שלה מצהירים על כלים מסוימים (כמו compiler = "//mytoolchain:custom_gcc"). הספקים שלהם מעבירים את המידע הזה לכללים שצריך לבנות באמצעות הכלים האלה.

ערכות הכלים מצהירות על constraint_value מחשבים שיכולים לשמש לטירגוט (target_compatible_with = ["@platforms//os:linux"]) ומכונות שניתן להפעיל עליהן פועלות (exec_compatible_with = ["@platforms//os:mac"]).

כשאתם בונים את $ bazel build //:myproject --platforms=//:myplatform, Bazel בוחרת באופן אוטומטי ארגז כלים שיכול לפעול במכשיר ה-build ולבנות נתונים בינאריים עבור //:myplatform. המכונה רזולוציה של Toolchain.

ניתן לרשום את קבוצת הכלים הזמינים בWORKSPACE באמצעות register_toolchains או בשורת הפקודה עם --extra_toolchains.

כאן אפשר לקבל מידע מפורט יותר.

סטטוס

התמיכה הנוכחית בפלטפורמה משתנה משפה לשפה. כל הכללים העיקריים של Bazel&33 עוברים לפלטפורמות. אבל התהליך הזה עשוי להימשך זמן מה. יש לכך שלוש סיבות עיקריות:

  1. יש לעדכן את הלוגיקה של הכלל כדי לקבל מידע על הכלים מה-APIchain API החדש (ctx.toolchains) ולהפסיק לקרוא הגדרות מדור קודם, כמו --cpu ו---crosstool_top. זה די פשוט.

  2. כדי לשמור על תחזוקת כלי הכלים, הם צריכים להגדיר את ערכות הכלים ולאפשר להם לגשת אליהם (במאגרי GitHub וברשומות WORKSPACE). זה קל מבחינה טכנית, אבל צריך לסדר אותן בצורה חכמה כדי לשמור על חוויית משתמש קלה.

    נדרשות גם הגדרות הפלטפורמה (אלא אם בונים עבור אותו מחשב Bazel פועל). באופן כללי, פרויקטים צריכים להגדיר את הפלטפורמות שלהם.

  3. יש להעביר פרויקטים קיימים. צריך גם להעביר select() ומעברים. זה האתגר הגדול ביותר. זה מקרה מסובך במיוחד בפרויקטים מרובי שפות (ואולי ייכשל אם כל השפות לא ייקראו.--platforms).

אם אתם מתכננים קבוצת כללים חדשה, עליכם לתמוך בפלטפורמות מההתחלה. כך, באופן אוטומטי, הכללים תואמים לפרויקטים ולכללים אחרים, כאשר הערך עולה ככל שה-API של הפלטפורמה הופך לזמין יותר.

מאפייני פלטפורמה נפוצים

צריך להצהיר על נכסי פלטפורמה כמו OS ו-CPU שנמצאים בשימוש נפוץ בפרויקטים במקום מרכזי אחד. אפשרות זו מעודדת תאימות בין פרויקטים ושפות שונות.

לדוגמה, אם בשדה MyApp יש select() ב-constraint_value @myapp//cpus:arm וב-SomeSharedLib יש select() ב-@commonlib//constraints:arm, הפעולות האלה יפעילו את ה-"arm" של המצבים עם הקריטריונים לא תואמים.

מצהירים על נכסים נפוצים בכל העולם במאגר @platforms (כך שהתווית הקנונית לפי הדוגמה שלמעלה היא @platforms//cpu:arm). יש להצהיר על נכסים משותפים בשפה שלהם בשפה שלהם.

פלטפורמות ברירת מחדל

באופן כללי, בעלי פרויקטים צריכים להגדיר פלטפורמות מפורשות כדי לתאר את סוגי המכונות שהם רוצים לבנות. לאחר מכן, הכללים האלה מופעלים באמצעות --platforms.

כאשר --platforms לא מוגדר, ברירת המחדל של Bazel היא platform המייצגת את מכונת ה-build המקומית. מידע זה נוצר באופן אוטומטי ב-@local_config_platform//:host, כך שאין צורך להגדיר אותו במפורש. היא ממפה את המכונה המקומית OS# ו-CPU עם constraint_value מוצהרים ב-@platforms.

C++‎

כללי C++ של Bazel' משתמשים בפלטפורמות כדי לבחור ערכות כלים כשמגדירים --incompatible_enable_cc_toolchain_resolution (#7260).

פירוש הדבר הוא שאתם יכולים להגדיר פרויקט C++ באמצעות:

bazel build //:my_cpp_project --platforms=//:myplatform

במקום מהדור הקודם:

bazel build //:my_cpp_project` --cpu=... --crosstool_top=...  --compiler=...

אם הפרויקט הוא בתקן C++ בלבד ואינו תלוי בפרויקטים שאינם C++, אפשר להשתמש בפלטפורמות באופן בטוח כל עוד selects ו-מעבריםתואמים. הנחיות נוספות זמינות #7260 והגדרה של ערכות כלים בנוסף ל-C+.

המצב הזה לא מופעל כברירת מחדל. הסיבה לכך היא שהפרויקטים של Apple עדיין מגדירים יחסי תלות של C++ עם --cpu ו---crosstool_top (דוגמה). לכן זה תלוי בכללים של Apple שעוברים לפלטפורמות.

Java

כללי ה-Java של Bazel&#39 משתמשים בפלטפורמות.

הפעולה הזו מחליפה את הסימונים הקודמים, --java_toolchain, --host_java_toolchain, --javabase ואת --host_javabase.

רוצים לדעת איך משתמשים בסימונים של התצורה? תוכלו להיעזר במדריך Bazel ו-Java. מידע נוסף זמין במסמך העיצוב.

אם אתם עדיין משתמשים בסימונים מדור קודם, יש לפעול לפי תהליך ההעברה במאמר בעיה מס' 7849.

Android

כללי ה-Android של Bazel&#39 משתמשים בפלטפורמות כדי לבחור ערכות כלים כשמגדירים את --incompatible_enable_android_toolchain_resolution.

אפשרות זו לא מופעלת כברירת מחדל. אבל ההעברה ממש טובה.

Apple

ה-Apple Bazel'S עדיין לא תומכות בפלטפורמות לבחירת ערכות כלים של Apple.

הם גם לא תומכים בתלות ש-C++ מופעל בפלטפורמה, כי הם משתמשים בגרסה הקודמת של --crosstool_top כדי להגדיר את 'כלי +C+'. עד שההעברה תושלם, תוכלו לשלב פרויקטים של Apple עם C++ התומכים בפלסטרים עם מיפויי פלטפורמות (דוגמה).

שפות נוספות

  • הBazel's הכללים תומכים באופן מלא בפלטפורמות.
  • Bazel's Gogos תומכים באופן מלא בפלטפורמות (פרטים).

אם אתם מעצבים כללים לשפה חדשה, השתמשו בפלטפורמות כדי לבחור את ערכות הכלים שלכם. מומלץ לעיין בתיעוד בנושא שרשראות כלים כדי לקבל הדרכה מפורטת.

select()

פרויקטים יכולים select() להופיע ב-constraint_value יעדים, אבל לא להשלים אותם. זה מכוון כדי שמערכת select() תתמוך במגוון רחב ככל האפשר של מכונות. ספרייה עם מקורות ספציפיים ל-ARM צריכה לתמוך בכל המכונות המופעלות באמצעות ARM, אלא אם יש סיבה ספציפית יותר לכך.

כדי לבחור פריט אחד או יותר מסוג constraint_value, יש להשתמש ב:

config_setting(
    name = "is_arm",
    constraint_values = [
        "@platforms//cpu:arm",
    ],
)

ההגדרה הזו מקבילה לבחירה בדרך כלל ב---cpu:

config_setting(
    name = "is_arm",
    values = {
        "cpu": "arm",
    },
)

כאן ניתן למצוא פרטים נוספים.

select ב---cpu, --crosstool_top וכו' לא מבינים את --platforms. כשמעבירים את הפרויקט לפלטפורמות, צריך להמיר אותן ל-constraint_values או להשתמש במיפויי פלטפורמות כדי לתמוך בשני הסגנונות דרך חלון ההעברה.

מעברים

מעברים ב-Starlark שינוי מסמן את כל החלקים בתרשים Build. אם בפרויקט שלכם נעשה שימוש במעבר שמגדיר את --cpu, --crossstool_top או סימונים קודמים מדור קודם, הכללים שנקראו --platforms לא יוצגו בשינויים האלה.

כשמעבירים את הפרויקט לפלטפורמות, צריך להמיר את השינויים כמו return { "//command_line_option:cpu": "arm" } ל-return { "//command_line_option:platforms": "//:my_arm_platform" } או להשתמש במיפוי פלטפורמות כדי לתמוך בשני הסגנונות דרך חלון ההעברה.

איך משתמשים בפלטפורמות היום

אם אתם רק רוצים לבנות פרויקט או לבצע הידור מוצלב, עליכם לעקוב אחר התיעוד הרשמי של הפרויקט. קובעי השפה והפרויקט הם שיקבעו מתי כדאי לשלב אותן עם פלטפורמות ואילו ערכים הן מציעות.

אם אתם פרויקטים, שפות או כלי תחזוקה, ואתם משתמשים בפלטפורמה כברירת מחדל, יש לכם שלוש אפשרויות (למעט המתנה להעברה גלובלית):

  1. סובבו את ה&צר; סמנו את הפלטפורמות ו&השפות של הפרויקט (אם יש בהן) וערכו את הבדיקות המתאימות כדי לראות אם הפרויקטים החשובים לכם עובדים.

  2. אם הפרויקטים שחשובים לכם עדיין מסתמכים על דגלים מדור קודם, כמו --cpu ו---crosstool_top, יש להשתמש בפרויקטים האלה יחד עם --platforms:

    bazel build //:my_mixed_project --platforms==//:myplatform --cpu=... --crosstool_top=...
    

    ישנן כמה עלויות תחזוקה (צריך לוודא שההגדרות תואמות ידנית). אבל אפשרות זו לא תבוצע בהיעדר מעברים.

  3. כתבו מיפויי פלטפורמות כדי לתמוך בשני הסגנונות על ידי מיפוי הגדרות בסגנון --cpu לפלטפורמות המתאימות, ולהיפך.

מיפויי פלטפורמות

מיפויי פלטפורמות הוא ממשק API זמני שמאפשר לקיים לוגיקה המופעלת באמצעות הפלטפורמה והדור הקודם, באותו מבנה דרך חלון ההוצאה משימוש.

מיפוי פלטפורמה הוא מפה של platform() אל קבוצה תואמת של דגלים מדור קודם, או להפך. למשל:

platforms:
  # Maps "--platforms=//platforms:ios" to "--cpu=ios_x86_64 --apple_platform_type=ios".
  //platforms:ios
    --cpu=ios_x86_64
    --apple_platform_type=ios

flags:
  # Maps "--cpu=ios_x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
  --cpu=ios_x86_64
  --apple_platform_type=ios
    //platforms:ios

  # Maps "--cpu=darwin --apple_platform_type=macos" to "//platform:macos".
  --cpu=darwin
  --apple_platform_type=macos
    //platforms:macos

Bazel משתמשת בהגדרה הזו כדי להבטיח שכל ההגדרות, הן מבוססות על פלטפורמה והן מדור קודם, יוחלו באופן עקבי בכל ה-build, כולל באמצעות מעברים.

כברירת מחדל, Bazel קורא מיפויים מקובץ platform_mappings ברמה הבסיסית (root) של סביבת העבודה. אפשר גם להגדיר את --platform_mappings=//:my_custom_mapping.

הפרטים המלאים זמינים כאן.

שאלות

כדי לקבל תמיכה כללית ושאלות לגבי לוח הזמנים של ההעברה, אפשר לפנות לכתובת bazel-conversation@googlegroups.com או לבעלים של הכללים המתאימים.

אם אתם רוצים לדבר על העיצוב וההתפתחות של ממשקי ה-API של הפלטפורמה או הכלי הפיתוח, צרו קשר עם bazel-dev@googlegroups.com.

מאמרים נוספים