BazelCon 2022 מגיע בין 16 ל-17 בנובמבר לניו יורק באינטרנט. הירשמו עוד היום!
חדש: אנחנו מזמינים אותך להצטרף אלינו ליום הקהילה ב-15 בנובמבר! פרטים ורישום.

פונקציות

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

תוכן עניינים

חבילה

package(default_deprecation, default_testonly, default_visibility, features)

הפונקציה הזו מצהירה על המטא-נתונים שחלים על כל כלל עוקב בחבילה. נעשה בו שימוש פעם אחת לכל היותר בחבילה (קובץ BUILD).

יש לקרוא לפונקציית package() מיד אחרי כל הצהרות ה-load() בחלק העליון של הקובץ, לפני כל כלל.

ארגומנטים

מאפיין תיאור
default_visibility

List of labels; optional

החשיפה של הכללים האלה בברירת מחדל של החבילה.

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

default_deprecation

String; optional

הגדרת הודעת ברירת המחדל deprecation לכל הכללים בחבילה הזו.

default_testonly

Boolean; optional; default is False except as noted

מגדיר את מאפיין ברירת המחדל testonly לכל הכללים בחבילה הזו.

בחבילות של פחות מ-javatests ערך ברירת המחדל הוא 1.

features

List strings; optional

מגדיר סימונים שונים שמשפיעים על הסמנטיקה של קובץ BUILD זה.

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

דוגמאות

ההצהרה הבאה היא שהכללים בחבילה הזו גלויים רק לחברים בקבוצת החבילות //foo:target. הצהרות חשיפה ספציפיות על כלל קיים, אם יש כאלה.
package(default_visibility = ["//foo:target"])

package_group

package_group(name, packages, includes)

פונקציה זו מגדירה קבוצה של חבילות ומשייכת תווית לקבוצה. אפשר להפנות לתווית במאפייני visibility.

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

חבילה נחשבת נחשבת לקבוצה בתוך הקבוצה אם היא תואמת למאפיין packages או אם היא כבר כלולה באחת מקבוצות החבילות האחרות שמוזכרות במאפיין includes.

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

ארגומנטים

מאפיין תיאור
name

Name; required

שם ייחודי ליעד הזה.

packages

List of strings; optional

רשימה של מפרטי חבילות מאפס או יותר.

כל מחרוזת של מפרט חבילה יכולה להיות באחת מהטפסים הבאים:

  1. השם המלא של חבילה, ללא המאגר שלה, מתחיל בקו נטוי כפול. לדוגמה, המאפיין //foo/bar מציין אם החבילה כוללת את השם הזה והיא נמצאת באותו מאגר נתונים כמו קבוצת החבילות.
  2. כמו למעלה, אבל עם /... בסוף. לדוגמה, המאפיין //foo/... מציין את הקבוצה של //foo ואת כל חבילות המשנה שלה. המדיניות //... מציינת את כל החבילות במאגר הנוכחי.
  3. המחרוזות public או private, שמציינות, בהתאמה, כל חבילה או חבילה. (טופס זה מחייב הגדרה של --incompatible_package_group_has_public_syntax.)

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

קבוצת החבילות מכילה חבילה שתואמת לפחות לאחד מהמפרטים החיוביים שלה, ולא מכילה מפרטים שליליים. לדוגמה, הערך [//foo/..., -//foo/tests/...] כולל את כל חבילות המשנה של //foo שהן לא חבילות משנה של //foo/tests. (//foo עצמו כלול ואילו //foo/tests עצמו לא.)

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

אם המאפיין הזה חסר, הוא זהה להגדרת רשימה ריקה, שהיא גם זהה להגדרתה לרשימה שמכילה רק private.

הערה: בתצורה //... יש התנהגות קודמת זהה לזו של public. ההתנהגות הזו מושבתת כאשר --incompatible_fix_package_group_reporoot_syntax מופעלת.

הערה: כהתנהגות מדור קודם, כאשר המאפיין הזה מוצג בצורה סידורית כחלק מ-bazel query --output=proto (או --output=xml), הקווים התחתונים המובילים מושמטים אם --incompatible_package_group_includes_double_slash לא מופעל. לדוגמה, הפונקציה //pkg/foo/... תפלט כ-\"pkg/foo/...\".

includes

List of labels; optional

קבוצות חבילות אחרות שכלולות בקבוצה הזו.

התוויות במאפיין הזה חייבות להתייחס לקבוצות אחרות של חבילות. חבילות בקבוצות חבילות שהוזכרו נחשבות כחלק מקבוצת החבילות הזו. זהו חולף – אם קבוצת החבילות a כוללת את קבוצת החבילות b, והחבילה b כוללת את קבוצת החבילות c, כל החבילה ב c תהיה גם היא בקבוצה a.

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

דוגמאות

הצהרת package_group הבאה מציינת קבוצת חבילות בשם "טרופי." שמכילה פירות טרופיים.

package_group(
    name = "tropical",
    packages = [
        "//fruits/mango",
        "//fruits/orange",
        "//fruits/papaya/...",
    ],
)

ההצהרות הבאות מציינות את קבוצות החבילות של אפליקציה בדיונית:

package_group(
    name = "fooapp",
    includes = [
        ":controller",
        ":model",
        ":view",
    ],
)

package_group(
    name = "model",
    packages = ["//fooapp/database"],
)

package_group(
    name = "view",
    packages = [
        "//fooapp/swingui",
        "//fooapp/webui",
    ],
)

package_group(
    name = "controller",
    packages = ["//fooapp/algorithm"],
)

מייצא_קבצים

exports_files([label, ...], visibility, licenses)

המדיניות exports_files() מציינת רשימה של קבצים ששייכים לחבילה הזו שיוצאו לחבילות אחרות.

קובץ BUILD של חבילה עשוי להפנות ישירות לקובצי מקור ששייכים לחבילה אחרת רק אם מתבצע ייצוא מפורש שלהם באמצעות הצהרת exports_files(). בקישור הבא אפשר לקרוא מידע נוסף על חשיפה של קבצים.

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

ארגומנטים

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

דוגמה

בדוגמה הבאה מתבצע ייצוא של golden.txt, קובץ טקסט מהחבילה test_data, כך שחבילות אחרות עשויות להשתמש בה, למשל, במאפיין data של בדיקות.

# from //test_data/BUILD

exports_files(["golden.txt"])

גלובוס

glob(include, exclude=[], exclude_directories=1, allow_empty=True)

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

תווית של קובץ מקור כלולה בתוצאה אם הנתיב של החבילה היחסית תואם לדפוסים של include ולא לאף אחד מהדפוסים של exclude.

הרשימות include ו-exclude מכילות דפוסי נתיבים יחסיים לחבילה הנוכחית. כל דפוס עשוי להכיל פלח אחד או יותר של נתיב. כרגיל עם נתיבי Unix, הפלחים האלה מופרדים באמצעות /. פלחים עשויים להכיל את התו הכללי לחיפוש *: הוא תואם לכל מחרוזת משנה בקטע הנתיב (גם למחרוזת המשנה הריק), מלבד מפריד הספרייה /. ניתן להשתמש בתו הכללי הזה מספר פעמים בקטע מקטע נתיב אחד. בנוסף, התו הכללי לחיפוש ** יכול להתאים לאפס פלחי נתיב שלמים, אבל צריך להצהיר עליו כפלח עצמאי בנתיב.

דוגמאות:
  • foo/bar.txt תואם בדיוק לקובץ foo/bar.txt בחבילה הזו
  • foo/*.txt תואם לכל הקבצים בספריית foo/ אם הקובץ מסתיים ב-.txt (אלא אם foo/ היא חבילת משנה)
  • foo/a*.htm* תואם לכל קובץ בספרייה foo/ שמתחיל ב-a, לאחר מכן יש מחרוזת שרירותית (יכול להיות ריקה), ואז יש .htm, ואז מסתיים במחרוזת שרירותית אחרת. כמו foo/axx.htm ו-foo/a.html או foo/axxx.html
  • **/a.txt תואם לכל קובץ a.txt בכל ספריית המשנה של החבילה הזו
  • **/bar/**/*.txt תואם לכל קובץ .txt בכל ספריית משנה של החבילה הזו, אם לפחות ספרייה אחת בנתיב שמתקבל נקראת bar, כגון xxx/bar/yyy/zzz/a.txt או bar/a.txt (חשוב לזכור שגם ** תואם אפס פלחים) או bar/zzz/a.txt
  • ** תואם לכל קובץ בכל ספריית משנה של החבילה הזו
  • התבנית foo**/a.txt לא חוקית, כי ** חייב לעמוד בפני עצמו כפלח

אם הארגומנט exclude_directories מופעל (מוגדר ל-1), קבצים של ספריית סוגים יושמטו מהתוצאות (ברירת מחדל 1).

אם הארגומנט allow_empty מוגדר לערך False, הפונקציה glob תיכשל אם התוצאה תהיה רשימה ריקה.

יש מספר מגבלות ואזהרות חשובות:

  1. מכיוון ש-glob() פועל במהלך הערכה של קובץ BUILD, glob() תואם לקבצים רק בעץ המקור שלך, הקבצים לא נוצרו אף פעם. אם יוצרים יעד שנדרש לה קובץ מקור וגם קובץ שנוצר, צריך להוסיף ל-glob את רשימת האתרים המפורשים שנוצרו. אפשר לעיין בדוגמה בהמשך עם :mylib ו-:gen_java_srcs.

  2. אם לכלל יש שם זהה לקובץ מקור מותאם, הכלל "apple" הקובץ.

    כדי להבין זאת, חשוב לזכור שהפונקציה glob() מחזירה רשימה של נתיבים, ולכן השימוש ב-glob() בכללים אחרים' (למשל srcs = glob(["*.cc"])) זהה להשפעה של רישום הנתיבים התואמים באופן מפורש. לדוגמה, glob() מניב ["Foo.java", "bar/Baz.java"] אבל יש גם כלל בחבילה בשם "food.Java" (מותר, אבל Bazel מציג אזהרה), לאחר מכן, הצרכן של glob() ישתמש ב-"foo.Java&quot לפרטים נוספים, ניתן לעיין בבעיה של GitHub מס' 10395.

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

    לדוגמה, ביטוי כדור הארץ **/*.cc בחבילה x לא כולל את x/y/z.cc אם x/y קיים כחבילה (למשל x/y/BUILD או במקום אחר בנתיב החבילה). המשמעות היא שהתוצאה של ביטוי כדור הארץ תלויה בפועל בקיומם של קובצי BUILD. כלומר, אותו ביטוי של גלובוס יכלול את x/y/z.cc אם לא נמצאה חבילה בשם x/y, או שהוא סומן כמחוק באמצעות הדגל --delete_packages .

  5. ההגבלה שלמעלה חלה על כל הביטויים ל-גלובוס, לא משנה באיזה תווים כלליים לחיפוש הם משתמשים.
  6. קובץ מוסתר עם שם קובץ שמתחיל ב-. מתאים באופן מלא ל-** ולתווים הכלליים לחיפוש *. אם ברצונך להתאים קובץ מוסתר לתבנית מורכבת, התבנית צריכה להתחיל ב-.. לדוגמה, * ו-.*.txt יתאימו ל-.foo.txt, אבל *.txt לא יתאימו. גם ספריות מוסתרות תואמות באותו אופן. ספריות מוסתרות יכולות לכלול קבצים שלא נדרשים כקלט, וכך להגדיל את מספר הקבצים שצורכים לזיכרון ואת צריכת הזיכרון שלא לצורך. כדי להחריג ספריות מוסתרות, צריך להוסיף אותן לארגומנט של רשימת &מירכאות.
  7. בתו הכללי לחיפוש&****; יש תו כללי אחד לדוגמה: התבנית "**" לא תואמת לנתיב הספרייה של החבילה. כלומר, ב-glob(["**"], exclude_directories = 0), כל הקבצים והספריות תואמים רק באופן זמני במאגר הנוכחי של הספרייה (אבל כמובן שלא נכללים בספריות של חבילות משנה – ראו את ההערה הקודמת).

באופן כללי, כדאי לנסות לספק תוסף מתאים (למשל *.html) במקום להשתמש בבסיס חשוף '*' לתבנית של גלובוס. השם הבוטה יותר הוא תיעוד עצמי ומבטיח שלא תתאים בטעות קובצי גיבוי, או שהקובץ emx/vi/ יישמר אוטומטית.

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

דוגמאות ל-גלובוס

יצירה של ספריית Java שנבנתה מכל קובצי ה-Java שבספרייה הזו וכל הקבצים שנוצרו על ידי הכלל :gen_java_srcs.

java_library(
    name = "mylib",
    srcs = glob(["*.java"]) + [":gen_java_srcs"],
    deps = "...",
)

genrule(
    name = "gen_java_srcs",
    outs = [
        "Foo.java",
        "Bar.java",
    ],
    ...
)

צריך לכלול את כל קובצי ה-txt בנתוני הבדיקה של הספרייה, למעט experiment.txt. הערה: קבצים בספריות משנה של נתוני בדיקה לא ייכללו בקובץ. אם רוצים לכלול את הקבצים האלה, צריך להשתמש בגלובוס חוזר (**).

sh_test(
    name = "mytest",
    srcs = ["mytest.sh"],
    data = glob(
        ["testdata/*.txt"],
        exclude = ["testdata/experimental.txt"],
    ),
)

דוגמאות לכדורים חוזרים

הבדיקה צריכה להיות תלויה בכל קובצי ה-TXT בספריית נתוני הבדיקה ובכל ספריות המשנה שלה (וספריות המשנה שלו, וכן הלאה). המערכת מתעלמת מספריות משנה שמכילות קובץ BUILD. (ראו מגבלות ואזהרות למעלה).

sh_test(
    name = "mytest",
    srcs = ["mytest.sh"],
    data = glob(["testdata/**/*.txt"]),
)

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

java_library(
    name = "mylib",
    srcs = glob(
        ["**/*.java"],
        exclude = ["**/testing/**"],
    ),
)

דוגמאות ל-גלובוס מורחב

ניתן ליצור ז'אנר יחיד עבור *_test.cc בספרייה הנוכחית, שסופרת את מספר השורות בקובץ.

# Conveniently, the build language supports list comprehensions.
[genrule(
    name = "count_lines_" + f[:-3],  # strip ".cc"
    srcs = [f],
    outs = ["%s-linecount.txt" % f[:-3]],
    cmd = "wc -l $< >$@",
 ) for f in glob(["*_test.cc"])]

אם קובץ ה-BUILD שלמעלה נמצא בחבילה //foo והחבילה מכילה שלושה קבצים תואמים, a_test.cc, b_test.cc ו-c_test.cc ואז פועל bazel query '//foo:all' יפרט את כל הכללים שנוצרו:

$ bazel query '//foo:all' | sort
//foo:count_lines_a_test
//foo:count_lines_b_test
//foo:count_lines_c_test

בחירה

select(
    {conditionA: valuesA, conditionB: valuesB, ...},
    no_match_error = "custom message"
)

select() היא פונקציית העזרה שיוצרת את מאפיין הכלל ניתן להגדרה. הוא יכול להחליף את הצד הימני של כמעט כל הקצאת מאפיינים, ולכן הערך שלו תלוי בסימונים של Bazel בשורת הפקודה. לדוגמה, אפשר להשתמש בו כדי להגדיר יחסי תלות ספציפיים לפלטפורמה או להטמיע משאבים שונים, בהתאם שהכלל מובנה במצב "developer" לעומת & "release"

השימוש הבסיסי הוא כך:

sh_binary(
    name = "mytarget",
    srcs = select({
        ":conditionA": ["mytarget_a.sh"],
        ":conditionB": ["mytarget_b.sh"],
        "//conditions:default": ["mytarget_default.sh"]
    })
)

פעולה זו מאפשרת להגדיר את המאפיין srcs של sh_binary כתחליף להקצאה הרגילה של רשימת התוויות בקריאה ל-select שממפה את תנאי התצורה לערכים תואמים. כל תנאי הוא הפניה לתווית config_setting או constraint_value, "matches" אם ההגדרה של יעד&#39 תואמת לקבוצת ערכים צפויה. הערך של mytarget#srcs הופך לאחר מכן לרשימת התוויות שתואמת להפעלה הנוכחית.

הערות:

  • נבחר תנאי אחד בלבד בכל הפעלה.
  • אם יש כמה תנאים שתואמים לאחד מהם והם מתמחים באחד מהקריטריונים האחרים, ההתמחות מקבלת עדיפות. תנאי ב' נחשב כהתמחות של תנאי א' אם ב' כולל את כל אותם הסימונים וערכי האילוץ כמו א', וגם כמה סימונים או ערכי אילוץ נוספים. משמעות הדבר היא שרזולוציית המומחיות לא נועדה ליצור הזמנה כפי שמוצג בדוגמה 2 בהמשך.
  • אם יש כמה תנאים שתואמים לאחד מהם, והם לא מומחים בכל התנאים האחרים, Bazel נכשלה עם השגיאה.
  • פסאודו-תווית מיוחדת //conditions:default נחשבת כהתאמה אם אין תנאי אחר תואם. אם תנאי זה לא הוזן, כלל אחר חייב להתאים כדי להימנע משגיאה.
  • אפשר להטמיע את select בתוך הקצאת מאפיינים גדולה יותר. לכן srcs = ["common.sh"] + select({ ":conditionA": ["myrule_a.sh"], ...}) ו- srcs = select({ ":conditionA": ["a.sh"]}) + select({ ":conditionB": ["b.sh"]}) הם ביטויים חוקיים.
  • המאפיין select פועל עם רוב המאפיינים, אבל לא עם כולם. מאפיינים לא תואמים מסומנים בnonconfigurable במסמכים שלהם.

    חבילות משנה

    subpackages(include, exclude=[], allow_empty=True)

    subpackages() היא פונקציית עזר, בדומה ל-glob(), שמציגה חבילות משנה במקום קבצים וספריות. היא משתמשת באותם דפוסי נתיב כמו glob() ויכולה להתאים כל חבילת משנה שהיא צאצא ישיר של קובץ BUILD שנטען כרגע. בקטע glob ניתן למצוא הסבר מפורט ודוגמאות בנוגע להכללה ולהחרגה.

    הרשימה ארוזה של חבילות משנה שהוחזרה נמצאת בסדר ממוין וכוללת נתיבים יחסיים לחבילת הטעינה הנוכחית שתואמת לדפוסים הנתונים ב-include ולא את אלה ב-exclude.

    דוגמה

    בדוגמה הבאה מפורטות כל חבילות המשנה הישירות של החבילה foo/BUILD

    # The following BUILD files exist:
    # foo/BUILD
    # foo/bar/baz/BUILD
    # foo/sub/BUILD
    # foo/sub/deeper/BUILD
    #
    # In foo/BUILD a call to
    subs = subpackages(include = ["**"])
    
    # results in subs == ["sub", "bar/baz"]
    #
    # 'sub/deeper' is not included because it is a subpackage of 'foo/sub' not of
    # 'foo'
    

    באופן כללי עדיף שבמקום להתקשר לפונקציה הזו ישירות, המשתמשים משתמשים במודול 'subpackages' של skylib.