BazelCon 2022 מגיע בין 16 ל-17 בנובמבר לניו יורק באינטרנט.
הירשמו עוד היום!

הקטע 'הפניה לשאילתה'

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

הדף הזה הוא מדריך העזר לשפת השאילתות של Bazel המשמש כשאתם משתמשים ב-bazel query כדי לנתח יחסי תלות של build. הוא גם מתאר את הפורמטים הנתמכים של bazel query.

לתרחישי שימוש מעשיים, עיינו במדריך הבסיס לשאילתה.

הפנייה נוספת לשאילתה

בנוסף לעמודה query, שמוצגת בתרשים היעד של הטעינה לאחר הטעינה, Bazel כוללת שאילתה בתרשים פעולה ושאילתה ניתנת להגדרה.

שאילתה בתרשים תרשים

שאילתת תרשים הפעולה (aquery) פועלת בתרשים היעד לאחר ניתוח הנתונים וחושפת מידע על פעולות, פריטי מידע שנוצרו בתהליך פיתוח (Artifact) והקשרים שלהם. aquery שימושי אם אתם מתעניינים בנכסים של הפעולות/פריטי המידע שנוצרו מתרשים היעד המוגדר. לדוגמה, הפקודות בפועל פועלות והקלטים, התפוקות והשירים שלהם.

לפרטים נוספים, עיינו בחומר העזר בנושא שאילתות.

שאילתה ניתנת להגדרה

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

פרטים נוספים זמינים בחומר העזר בנושא שאילתות.

דוגמאות

איך אנשים משתמשים בbazel query? כמה דוגמאות טיפוסיות:

למה עץ //foo תלוי ב-//bar/baz? הצגת נתיב:

somepath(foo/..., //bar/baz:all)

אילו ספריות C++ תלויות בכל הבדיקות של foo שהיעד foo_bin לא משפיע עליהן?

kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo:foo_bin))

אסימונים: התחביר הלקסי

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

  • מילות מפתח, כגון let. מילות מפתח הן המילים השמורות בשפה, וכל אחת מהן מתוארת בהמשך. הקבוצה המלאה של מילות המפתח היא:

  • מילים, כגון "foo/... " או ".*test rule" או "//bar/baz:all". אם, אם רצף תווים לא מצוטט, עדיין אפשר לנתח אותו כמילה. מילים ללא מירכאות הן רצפים של תווים שנשלפים מהאלפבית A-Za-z, הספרות 0-9 והתווים המיוחדים */@.-_:$~[] (כוכבית, קו נטוי, נקודה, נקודה, מקף, קו תחתון, נקודתיים, סימן דולר, טילדה, סוגריים מרובעים שמאליים, סוגריים מרובעים ימניים). עם זאת, מילים ללא מירכאות לא יכולות להתחיל במקף - או בכוכבית *, אף על פי שיחסים בין [שמות היעדים][(/concepts/labels#target-names) היחסיים עשויים להתחיל בתווים האלה.

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

    יש צורך במירכאות ב בעת כתיבת סקריפטים שבונים ביטויים ב-Bazel מערכים שסופקו על ידי משתמשים.

     //foo:bar+wiz    # WRONG: scanned as //foo:bar + wiz.
     //foo:bar=wiz    # WRONG: scanned as //foo:bar = wiz.
     "//foo:bar+wiz"  # OK.
     "//foo:bar=wiz"  # OK.
    

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

    bazel query ' "//foo:bar=wiz" '   # single-quotes for shell, double-quotes for Bazel.
    

    כאשר מילות מפתח מצוטטות, הן נחשבות למילים רגילות. לדוגמה, some היא מילת מפתח, אבל "some" היא מילה. גם foo וגם "foo" הם מילים.

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

    בהמשך מפורטות דוגמאות למחרוזת השאילתה של Java:

      'a"'a'         # WRONG: Error message: unclosed quotation.
      "a'"a"         # WRONG: Error message: unclosed quotation.
      '"a" + 'a''    # WRONG: Error message: unexpected token 'a' after query expression '"a" + '
      "'a' + "a""    # WRONG: Error message: unexpected token 'a' after query expression ''a' + '
      "a'a"          # OK.
      'a"a'          # OK.
      '"a" + "a"'    # OK
      "'a' + 'a'"    # OK
    

    בחרנו בתחביר הזה כך שברוב המקרים לא יהיה צורך במירכאות. הדוגמה ".*test rule"(יוצאת דופן) כוללת מירכאות: היא מתחילה בנקודה ומכילה רווח. לא צריך להוסיף ציטוט של "cc_library", אבל זה עלול להיות פוגעני.

  • סימני פיסוק, כמו פרקים (), נקודה . ופסיק ,. יש לצטט מילים שמכילות פיסוק (למעט החריגות שצוינו למעלה).

המערכת תתעלם מתווים של רווחים מחוץ למילה המצוטטת.

קונספטים של שפת שאילתות של Bazel

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

ההגדרה והתרשים מתייחסים לאותו סוג נתונים, אך מדגישים היבטים שונים שלהם, לדוגמה:

  • הגדרה: הסדר החלק של היעדים לא מעניין.
  • תרשים: הסדר החלקי של היעדים הוא משמעותי.

מחזורים בתרשים התלות

תרשימי התלות של ה-build צריכים להיות אציקליים.

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

יחסי תלות מרומזים

בנוסף לבניית קשרי תלות המוגדרים באופן מפורש בקובצי BUILD, Bazel מוסיפה עוד יחסי תלות משתמעים לכללים. לדוגמה, כל כלל Java תלוי באופן לא מפורש ב-JavaBuilder. יחסי תלות משתמעים נקבעים באמצעות מאפיינים שמתחילים ב-$ ולא ניתן לשנות אותם ב-BUILD קבצים.

כברירת מחדל, bazel query מביא בחשבון יחסי תלות מרומזים כאשר מחשבים את תוצאת השאילתה. ניתן לשנות התנהגות זו באמצעות האפשרות --[no]implicit_deps. שימו לב: מכיוון שבשאילתה לא נלקחות בחשבון הגדרות אישיות, מחזיקי כלים פוטנציאליים לא נלקחים בחשבון.

סאונד

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

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

על השימור של סדר התרשימים

התפעול שומר על מגבלות ההזמנה שהועברו בירושה מביטויי המשנה שלהן. אפשר לחשוב על זה בתור "חוק השימור של הסדר החלקי&&; דוגמה: אם מנפיקים שאילתה כדי לקבוע את הסגירה התלויה של יחסי תלות של יעד מסוים, הסדר שמתקבל מסודר לפי תרשים התלות. אם תגדירו מסנן שכולל רק את היעדים מסוג file, אותו קשר סידורי חלקי בין הקבוצות ישויך בין כל זוגות של קבוצות משנה, למרות שאף אחד מהזוגות לא מחובר ישירות לתרשים המקורי. (אין קצוות של קובצי קבצים בתרשים תלות ה-build).

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

deps(x) union y

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

מפעילים שכוללים אילוצי הזמנה כוללים: allpaths, deps, rdeps, somepath ואת התווים הכלליים לחיפוש של יעד package:*, dir/... וכו'.

שאילתת סקיי

שאילתת Sky היא מצב שאילתה שפועלת במהלך היקף ברמת היקום שצוינה.

פונקציות מיוחדות שזמינות רק ב-SkyQuery

במצב 'שאילתת סקיי' יש את פונקציות השאילתה הנוספות allrdeps וגם rbuildfiles. פונקציות אלה פועלות בכל היקף היקום (ולכן לא הגיוני עבור שאילתה רגילה).

ציון היקף יקום

מצב 'שאילתה סקיי' מופעל על ידי העברה של שני הסימונים הבאים: (--universe_scope או --infer_universe_scope) ו---order_output=no. הפונקציה --universe_scope=<target_pattern1>,...,<target_patternN> מורה לשאילתה לטעון מראש את הסגירה העקירה של דפוס היעד שצוינה בתבניות היעד. פעולה זו יכולה להיות גם תוסף וגם הפחתה. לאחר מכן כל השאילתות מוערכים ב "היקף". ספציפית, האופרטורים allrdeps ו-rbuildfiles מחזירים תוצאות רק מההיקף הזה. --infer_universe_scope מורה ל-Bazel להסיק ערך עבור --universe_scope מביטוי השאילתה. הערך המשוער הזה הוא רשימה של דפוסי יעד ייחודיים בביטוי השאילתה, אבל ייתכן שהוא לא מה שרציתם. למשל:

bazel query --infer_universe_scope --order_output=no "allrdeps(//my:target)"

הרשימה של דפוסי היעד הייחודיים בביטוי השאילתה הזה היא ["//my:target"], כך ש-Bazel מתייחסת לכך בדיוק כמו להפעלה:

bazel query --universe_scope=//my:target --order_output=no "allrdeps(//my:target)"

אבל התוצאה של השאילתה הזו עם --universe_scope היא רק //my:target. אחד מהתלויות ההפוך של //my:target הוא לא בתוך היקום, לפי בנייה. לעומת זאת, יש להביא בחשבון:

bazel query --infer_universe_scope --order_output=no "tests(//a/... + b/...) intersect allrdeps(siblings(rbuildfiles(my/starlark/file.bzl)))"

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

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

ל-Sky Query יש כמה יתרונות וחסרונות בהשוואה לשאילתת ברירת המחדל. החיסרון העיקרי הוא שלא ניתן לסדר את הפלט לפי סדר התרשים, ולכן פורמטים מסוימים של פלט אסורים. היתרון שלו הוא שהוא מספק שני אופרטורים (allrdeps ו-rbuildfiles) שאינם זמינים בשאילתת ברירת המחדל. כמו כן, סקיי ווק עושה עבודה על ידי בחינת התרשים Skyframe, במקום על ידי יצירת גרף חדש, שהוא היישום האוטומטי של ברירת המחדל. כך, יש נסיבות מסוימות שבהן הן מהירות יותר וחוסכות פחות זיכרון.

ביטויים: תחביר וסמנטיקה של הדקדוק

זהו הדקדוק של שפת השאילתה בזל, המתוארת בסימון EBNF:

expr ::= word
       | let name = expr in expr
       | (expr)
       | expr intersect expr
       | expr ^ expr
       | expr union expr
       | expr + expr
       | expr except expr
       | expr - expr
       | set(word *)
       | word '(' int | word | expr ... ')'

בקטעים הבאים מתוארים כל אחד מהדקדוקים הבאים לפי הסדר.

דפוסי יעד

expr ::= word

באופן מלאכותי, דפוס יעד הוא רק מילה. הוא מפורש כקבוצת יעדים (לא מסודרת). דפוס היעד הפשוט ביותר הוא תווית, שמזהה יעד יחיד (קובץ או כלל). לדוגמה, דפוס היעד //foo:bar מעריך קבוצה שמכילה רכיב אחד, את היעד, את הכלל bar.

דפוסי יעד מחריגים תוויות כדי לכלול תווים כלליים לחיפוש מעל חבילות ויעדים. לדוגמה, foo/...:all (או רק foo/...) הוא דפוס יעד שמחושב לקבוצה הכוללת את כל הכללים בכל חבילה מתחת לספריית foo; bar/baz:all הוא דפוס יעד שמעריך קבוצה שמכילה את כל הכללים בחבילה של bar/baz, אבל לא את חבילות המשנה שלה.

באופן דומה, foo/...:* הוא תבנית יעד שמעריכה קבוצה שכוללת את כל היעדים (כללים ו-) בכל חבילה באופן חוזר מתחת לספריית foo. מערכת bar/baz:* מעריכה קבוצה שמכילה את כל היעדים בחבילה bar/baz, אבל לא את חבילות המשנה שלה.

מאחר שהתו הכללי לחיפוש :* תואם לקבצים ולכללים, הוא בדרך כלל שימושי יותר מ-:all לשאילתות. לעומת זאת, התו הכללי לחיפוש :all (משתמע מתבניות יעד, כמו foo/...) בדרך כלל שימושי יותר לגרסאות build.

bazel query דפוסי יעד פועלים באותו אופן כמו bazel build יעדי build. לפרטים נוספים, אפשר לעיין בתבניות יעד או להקליד bazel help target-syntax.

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

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

משתנים

expr ::= let name = expr1 in expr2
       | $name

שפת השאילתה של Bazel מאפשרת הגדרות והפניות למשתנים. התוצאה של הערכה של ביטוי let זהה לזו של expr2, וכל המופעים בחינם של המשתנה name מוחלפים בערך של expr1.

לדוגמה, הפונקציה let v = foo/... in allpaths($v, //common) intersect $v היא שווה ל-allpaths(foo/...,//common) intersect foo/....

חזרה על הפניה למשתנה name שלא מופיעה בביטוי let name = ... בכלל היא שגיאה. במילים אחרות, ביטויים של שאילתות ברמה העליונה לא יכולים לכלול משתנים משתנים.

בהפקות הדקדוק שלמעלה, name דומה ל-word, אבל מגבלה נוספת היא המזהה החוקי בשפת התכנות C. אם יש הפניה למשתנה, יש להוסיף לפניו את התו "$".

כל ביטוי ב-let מגדיר משתנה אחד בלבד, אבל אפשר לקנן אותו.

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

מבחינה טכנית, ביטויים מסוג let לא מגבירים את הביטוי הביטויי של שפת השאילתה: כל ביטוי שמבטא בשפה עם זאת, הם משפרים את התמציתיות של שאילתות רבות, ועשויים להוביל להערכה יעילה יותר של השאילתות.

ביטויים בסוגריים

expr ::= (expr)

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

פעולות באלגברה: צומת, איחוד, הפרש

expr ::= expr intersect expr
       | expr ^ expr
       | expr union expr
       | expr + expr
       | expr except expr
       | expr - expr

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

לדוגמה,

foo/... except foo/bar/...

מבצע הערכה לקבוצת היעדים שתואמים ל-foo/... אך לא ל-foo/bar/....

אפשר לכתוב שאילתה כמו:

foo/... - foo/bar/...

הפעולות intersect (^) ו-union (+) הן שונות (סימטריות). except (-) היא אסימטרית. המנתח מתייחס לכל שלושת האופרטורים כשיוך שמאלי עם עדיפות זהה, ולכן ייתכן שתרצו להוסיף סוגריים. לדוגמה, שני הביטויים הראשונים הם מקבילים, אבל השלישי לא:

x intersect y union z
(x intersect y) union z
x intersect (y union z)

קריאת יעדים ממקור חיצוני: set

expr ::= set(word *)

האופרטור set(a b c ...) מחשב את האיחוד של קבוצה של אפס או יותר דפוסי יעד, מופרדים ברווחים לבנים (ללא פסיקים).

בשילוב עם התכונה $(...) של Bourne – שארית מעטפת, set() פירושו ממוצע של שמירת תוצאות של שאילתה אחת בקובץ טקסט רגיל, ביצוע מניפולציות על קובץ הטקסט באמצעות תוכנות אחרות (כמו כלי מעטפת UNIX רגילים), ולאחר מכן הצגת התוצאה בחזרה בכלי השאילתה כערך לעיבוד נוסף. למשל:

bazel query deps(//my:target) --output=label | grep ... | sed ... | awk ... > foo
bazel query "kind(cc_binary, set($(<foo)))"

בדוגמה הבאה, kind(cc_library, deps(//some_dir/foo:main, 5)) מחושבת על ידי סינון של ערכי maxrank באמצעות תוכנית awk.

bazel query 'deps(//some_dir/foo:main)' --output maxrank | awk '($1 < 5) { print $2;} ' > foo
bazel query "kind(cc_library, set($(<foo)))"

בדוגמאות האלה, $(<foo) הוא קיצור דרך ל-$(cat foo), אבל אפשר להשתמש גם בפקודות המעטפת שאינן של cat – כמו הפקודה הקודמת של awk.

פונקציות

expr ::= word '(' int | word | expr ... ')'

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

סגירה תלויה של יחסי תלות: נקודות שפל

expr ::= deps(expr)
       | deps(expr, depth)

האופרטור deps(x) מבצע הערכה בתרשים שנוצר על סמך הסגירה התלויה של קבוצת הארגומנטים x. לדוגמה, הערך של deps(//foo) הוא תרשים תלות ששורשיו בצומת היחיד foo, כולל כל התלות שלו. הערך של deps(foo/...) הוא תרשימי התלות שהשורשים שלהם הם כל הכללים בכל חבילה מתחת לספריית foo. בהקשר הזה, 'dependencies' פירושו רק יעדים של כללים וקבצים, ולכן הקבצים של BUILD ושל Starlark הנדרשים ליצירת היעדים האלה לא נכללים כאן. לשם כך צריך להשתמש באופרטור buildfiles.

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

האופרטור deps מקבל ארגומנט שני אופציונלי, שהוא ליטרל של מספר שלם המציין גבול עליון בעומק החיפוש. כך, deps(foo:*, 0) מחזיר את כל היעדים בחבילה foo, בעוד deps(foo:*, 1) כולל את הדרישות המוקדמות הישירות של כל יעד בחבילה foo. בנוסף, deps(foo:*, 2) כולל את הצמתים שאפשר לגשת אליהם ישירות מהצמתים ב-deps(foo:*, 1), וכן הלאה. (המספרים האלה תואמים לדירוגים המוצגים בפורמט הפלט minrank). אם הפרמטר depth יושמט, החיפוש יהיה ללא גבולות: הוא מחשב את הסגירה הרגולרית של הדרישות המוקדמות.

סגירה חולפת של יחסי תלות הפוכים: להקפיד

expr ::= rdeps(expr, expr)
       | rdeps(expr, expr, depth)

האופרטור rdeps(u, x) מעריך את התלויות ההפיכות של קבוצת הארגומנטים x בתוך הסגירה העקיפה של קבוצת היקום u.

התרשים שמתקבל מסודר לפי יחס התלות. למידע נוסף, עיינו בקטע הזמנת תרשים.

האופרטור rdeps מקבל ארגומנט שלישי אופציונלי, שהוא ליטרל של מספר שלם המציין גבול עליון בעומק החיפוש. התרשים שנוצר כולל רק צמתים בטווח העומק שצוין מכל צומת בקבוצת הארגומנטים. לכן, rdeps(//foo, //common, 1) בודקת את כל הצמתים בדרך הסגורה של //foo, שתלויה ישירות ב-//common. (המספרים האלה תואמים לדירוגים המוצגים בפורמט הפלט minrank). אם הפרמטר depth יושמט, החיפוש יהיה ללא גבולות.

סגירה חולפת של כל יחסי תלות הפוכים: אלפרד

expr ::= allrdeps(expr)
       | allrdeps(expr, depth)

האופרטור allrdeps פועל בדיוק כמו האופרטור rdeps, אבל האופרטור "uniset set" הוא מה שמוערך עבור ה--universe_scope, במקום לציין אותו בנפרד. כך, אם הערך --universe_scope=//foo/... הועבר, אזallrdeps(//bar) הוא שווה ערך ל-rdeps(//foo/..., //bar).

יחסי תלות הפוכים ישירים באותה חבילה: same_pkg_direct_rdeps

expr ::= same_pkg_direct_rdeps(expr)

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

התמודדות עם חבילה של יעד/אחיות

expr ::= siblings(expr)

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

בחירה שרירותית: חלקם

expr ::= some(expr)

האופרטור some(x) בוחר יעד אחד באופן שרירותי מתוך קבוצת הארגומנטים x, ומבצע הערכה לקבוצת סינגל שמכילה רק את היעד הזה. לדוגמה, הביטוי some(//foo:main union //bar:baz) מעריך קבוצה שמכילה //foo:main או //bar:baz, אך אף אחת מהן לא מוגדרת.

אם הארגומנט הוא יחיד, הפונקציה some מחשבת את פונקציית הזהות: some(//foo:main) היא שווה ערך ל-//foo:main.

אם השגיאה ריקה לא צוינה, כמו בביטוי some(//foo:main intersect //bar:baz).

אופרטורים בנתיב: נתיב כלשהו, כל הנתיבים

expr ::= somepath(expr, expr)
       | allpaths(expr, expr)

האופרטורים somepath(S, E) ו-allpaths(S, E) מחשבים נתיבים בין שתי קבוצות של יעדים. שתי השאילתות מקבלות שני ארגומנטים, קבוצה של S נקודות התחלה וקבוצה של E נקודות קצה. somepath מחזיר את תרשים הצמתים בדרך חלקית מיעד ב-S ליעד ב-E. allpaths מחזיר את תרשים הצמתים מכל הנתיבים בכל יעד ב-S לכל יעד ב-E.

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

נתיב כלשהו
somepath(S1 + S2, E), תוצאה אפשרית אחת.
נתיב כלשהו
somepath(S1 + S2, E), תוצאה אפשרית נוספת.
כל הנתיבים
allpaths(S1 + S2, E)

סינון של סוג היעד: סוג

expr ::= kind(word, expr)

האופרטור kind(pattern, input) מפעיל מסנן על קבוצת יעדים, ומבטל את היעדים שאינם מהסוג הצפוי. הפרמטר pattern מציין את סוג היעד המתאים.

לדוגמה, הסוגים של ארבעת היעדים שהוגדרו בקובץ BUILD (לחבילה p) מופיעים בטבלה הבאה:

קוד לטירגוט סוג
        genrule(
            name = "a",
            srcs = ["a.in"],
            outs = ["a.out"],
            cmd = "...",
        )
      
//p:a כלל כללי
//p:a.in קובץ מקור
//p:a.out קובץ שנוצר
//p:BUILD קובץ מקור

כתוצאה מכך, הפונקציה kind("cc_.* rule", foo/...) בודקת את הקבוצה של כל cc_library, cc_binary ויעדי הטירגוט, מתחת ל-foo, ואת ההערכה של kind("source file", deps(//foo)) לגבי כל קובצי המקור בסגירה הזמנית של יחסי תלות של היעד //foo.

בדרך כלל יש צורך במירכאות של הארגומנט pattern, כי בלעדיו, ביטויים רגולריים רבים, כמו source file ו-.*_test, לא נחשבים למילים על ידי המנתח.

כשמתאימים לחשבון package group, ייתכן שיעדים שמסתיימים ב-:all לא יניבו תוצאות. במקומה, צריך להשתמש במדיניות :all-targets.

סינון לפי שם יעד: מסנן

expr ::= filter(word, expr)

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

הארגומנט הראשון pattern הוא מילה המכילה ביטוי רגולרי מעל שמות יעדים. ביטוי ב-filter מעריך את הקבוצה שמכילה את כל היעדים x כך ש-x חבר בקבוצה input והתווית (בנוסח מוחלט, כמו //foo:bar) מכילה התאמה (לא מעוגנת) עבור הביטוי הרגיל pattern. מאחר שכל שמות היעדים מתחילים ב-//, ניתן להשתמש בהם כחלופה לעוגן הרגיל של ^.

לרוב, האופרטור הזה מספק חלופה מהירה וחזקה יותר לאופרטור intersect. לדוגמה, כדי לראות את כל התלות של היעד bar לפי //foo:foo, אפשר להעריך

deps(//foo) intersect //bar/...

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

filter(//bar, deps(//foo))

שתחשב תחילה את קבוצת התלות של //foo, ואז תסנן רק יעדים שתואמים לדפוס שצוין – במילים אחרות, יעדים עם שמות שמכילים //bar כמחרוזת משנה.

עוד שימוש נפוץ באופרטור filter(pattern, expr) הוא סינון קבצים ספציפיים לפי השם או התוסף. לדוגמה,

filter("\.cc$", deps(//foo))

תספק רשימה של כל .cc הקבצים ששימשו ליצירת //foo.

סינון מאפיינים של כלל: מאפיין

expr ::= attr(word, word, expr)

האופרטור attr(name, pattern, input) מפעיל מסנן על קבוצת יעדים, ומבטל יעדים שאינם כללים, יעדים שהוגדרו לגביהם מאפיינים שלא הוגדרו עבורם name או יעדים של כללים שבהם ערך המאפיין לא תואם לביטוי הרגולרי pattern שצוין. הוא מבצע הערכה לקבוצת משנה של קלט.

הארגומנט הראשון, name, הוא שם מאפיין הכלל שצריך להתאים לתבנית הביטוי הרגולרי שצוינה. הארגומנט השני, pattern, הוא ביטוי רגולרי מעל ערכי המאפיינים. ביטוי מסוג attr מעריך את הקבוצה שמכילה את כל היעדים x כך ש-x הוא חבר בקבוצה input, הוא כלל עם המאפיין המוגדר name וערך המאפיין מכיל התאמה (לא מעוגנת) עבור הביטוי הרגיל pattern. אם המאפיין name הוא מאפיין אופציונלי וכלל לא מציין אותו במפורש, ערך ברירת המחדל של המאפיין ישמש להשוואה. לדוגמה,

attr(linkshared, 0, deps(//foo))

יבחר את כל יחסי תלות של //foo שמותרים לכלול מאפיין קישור משותף (למשל, כלל cc_binary) ויגדיר באופן מפורש את הערך 0 או לא להגדיר אותו בכלל, אבל ערך ברירת המחדל הוא 0 (למשל, כללי cc_binary).

מאפיינים מסוג רשימה (כמו srcs, data וכו') מומרים למחרוזות בצורה [value<sub>1</sub>, ..., value<sub>n</sub>], מתחילים בסוגריים מרובעים עם סיומת ], ומוסיפים סוגריים מסוג ] ו-"," (פסיקה, רווח) כדי להפריד בין ערכים מרובים. תוויות מומרות למחרוזות באמצעות צורה מוחלטת של התווית. לדוגמה, מאפיין deps=[":foo", "//otherpkg:bar", "wiz"] יומר למחרוזת [//thispkg:foo, //otherpkg:bar, //thispkg:wiz]. בסוגריים תמיד מופיעים, ולכן הרשימה הריקה תשתמש בערך המחרוזת [] למטרות התאמה. לדוגמה,

attr("srcs", "\[\]", deps(//foo))

יבחר את כל הכללים מתוך //foo תלויות, עם מאפיין srcs ריק,

attr("data", ".{3,}", deps(//foo))

יבחר את כל הכללים מתוך יחסי תלות של //foo המציינים לפחות ערך אחד במאפיין data (כל תווית היא באורך של לפחות 3 תווים עקב // ו-:).

כדי לבחור את כל הכללים בתוך //foo יחסי תלות עם value מסוים במאפיין מסוג רשימה, יש להשתמש

attr("tags", "[\[ ]value[,\]]", deps(//foo))

זה פועל כי התו לפני value יהיה [ או רווח, והתו שאחרי value יהיה פסיק או ].

סינון הרשאות הגישה לכלל: גלוי

expr ::= visible(expr, expr)

האופרטור visible(predicate, input) מפעיל מסנן על קבוצת יעדים, ומבטל יעדים ללא החשיפה הנדרשת.

הארגומנט הראשון, predicate, הוא קבוצה של יעדים שכל היעדים בפלט חייבים להיות גלויים. ביטוי ב-visible מעריך את הקבוצה שמכילה את כל היעדים x כך ש-x חבר בקבוצה input, ועבור כל היעדים y ב-predicate x גלוי ל-y. למשל:

visible(//foo, //bar:*)

יבחר את כל היעדים בחבילה //bar שתלויים ב-//foo, בלי להפר את הרשאות הגישה.

הערכה של מאפייני כלל בתווית מסוג: תוויות

expr ::= labels(word, expr)

האופרטור labels(attr_name, inputs) מחזיר את קבוצת היעדים שצוינה במאפיין attr_name מסוג "label" או "רשימת התוויות" בכלל מסוים בקבוצה inputs.

לדוגמה, הפונקציה labels(srcs, //foo) מחזירה את קבוצת היעדים שמופיעה במאפיין srcs של הכלל //foo. אם קיימים כללים מרובים עם מאפייני srcs בקבוצה inputs, הפונקציה srcs מוחזרת.

הרחבה וסינון של test_Suites: בדיקות

expr ::= tests(expr)

האופרטור tests(x) מחזיר את הקבוצה של כל כללי הבדיקה בקבוצה x, מרחיב את הכללים ל-test_suite למערכת של בדיקות נפרדות שאליהן מתייחס, ומחילים סינון לפי tag ו-size.

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

לדוגמה, השאילתה kind(test, foo:*) מפרטת את כל הכללים *_test ו-test_suite בחבילה foo. כל התוצאות הן (לפי ההגדרה) חברים בחבילה של foo. לעומת זאת, השאילתה tests(foo:*) תחזיר את כל הבדיקות הנפרדות שיתבצעו על ידי bazel test foo:*: התוצאות עשויות לכלול בדיקות ששייכות לחבילות אחרות, עם הפניה ישירה או עקיפה דרך כללי test_suite.

קובצי הגדרת חבילות: buildfiles

expr ::= buildfiles(expr)

האופרטור buildfiles(x) מחזיר את קבוצת הקבצים המגדירים את החבילות של כל יעד בקבוצה x. במילים אחרות, עבור כל חבילה, קובץ ה-BUILD שלה, בתוספת קובצי .bzl שאליהם היא מתייחסת דרך load. הערה: מוחזרות גם BUILD הקבצים של החבילות שמכילות את load הקבצים האלה.

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

bazel query 'buildfiles(deps(//foo))' --output package

מחזירה את הקבוצה של כל החבילות שתלויות ב-//foo באופן זמני.

קובצי הגדרת חבילות: rbuildfiles

expr ::= rbuildfiles(word, ...)

האופרטור rbuildfiles מקבל רשימה של קטעי קטעים מופרדים בפסיקים, ומחזיר את קבוצת קובצי BUILD שתלויים באופן זמני בקטעי הנתיב האלה. לדוגמה, אם //foo היא חבילה, הפונקציה rbuildfiles(foo/BUILD) תחזיר את היעד //foo:BUILD. אם הקובץ foo/BUILD מכיל את הערך load('//bar:file.bzl'..., הפונקציה rbuildfiles(bar/file.bzl) תחזיר את היעד //foo:BUILD, וכן את היעדים של כל BUILD קבצים שנטענים //bar:file.bzl

ההיקף של האופרטור rbuildfiles הוא היקום שהוגדר על ידי הדגל --universe_scope. קבצים שלא תואמים ישירות ל-BUILD קבצים ו-.bzl קבצים לא ישפיעו על התוצאות. לדוגמה, המערכת תתעלם מקובצי מקור (כמו foo.cc), גם אם הם צוינו במפורש בקובץ BUILD. עם זאת, אנחנו מכבדים קישורים חכמים. כך, אם foo/BUILD הוא קישור סימולטני אל bar/BUILD, אז rbuildfiles(bar/BUILD) יכלול בתוצאות שלו את //foo:BUILD.

האופרטור rbuildfiles הוא כמעט פונקציונלי באופן מוראלי. עם זאת, השינוי המוסרי הזה חזק יותר בכיוון אחד: הערכים של rbuildfiles דומים בדיוק לקלט של buildfiles. המאפיין הראשון מכיל רק BUILD יעדים לקבצים בחבילות, והקובץ השני עשוי להכיל יעדים כאלה. בכיוון השני, התכתובת חלשה יותר. הפלט של האופרטור buildfiles הוא יעדים התואמים לכל החבילות ול-bzl קבצים הדרושים לקלט נתון. עם זאת, הקלט של האופרטור rbuildfiles הוא לא היעדים האלה, אלא קטעי הנתיב שתואמים ליעדים האלה.

קובצי הגדרת חבילות: loadfiles

expr ::= loadfiles(expr)

האופרטור loadfiles(x) מחזיר את הקבוצה של קובצי Starlark הדרושים לטעינת החבילות של כל יעד בקבוצה x. במילים אחרות, עבור כל חבילה היא מחזירה את קובצי ה-bzl.

פורמטים של פלט

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

בעת הפעלה באמצעות Sky Query, מותר להשתמש רק בפורמטים של פלט שתואמים לפלט שלא הוזמן. באופן ספציפי, אסור להשתמש בפורמטים של graph, minrank ו-maxrank.

חלק מהפורמטים של הפלט מקבלים אפשרויות נוספות. התחילית של השם של כל אחת מאפשרויות הפלט תלויה בפורמט הפלט שעליו היא חלה, כך ש---graph:factored חל רק כשהקובץ --output=graph נמצא בשימוש. אין לו השפעה אם נעשה שימוש בפורמט פלט אחר מלבד graph. באופן דומה, --xml:line_numbers חל רק כאשר נעשה שימוש ב---output=xml.

בסדר התצוגה של התוצאות

אמנם ביטויים של שאילתות תמיד פועלים לפי &br;חוק השימור של סדר התרשימים", מציגאת התוצאות אפשר לבצע לפי סדר תלות או ללא סדר. הדבר לא משפיע על היעדים בקבוצת התוצאות או על אופן החישוב של השאילתה. הבעיה משפיעה רק על אופן ההדפסה של התוצאות ב-stdout. יותר מכך, ייתכן שצמתים שהם זהים לסדר התלות יהיו מסודרים בסדר אלפביתי. אפשר להשתמש בסימון --order_output כדי לשלוט בהתנהגות הזו. (לסימון --[no]order_results יש קבוצת משנה של הפונקציונליות של הסימונים --order_output, והיא הוצאה משימוש).

ערך ברירת המחדל של הדגל הזה הוא auto, והוא מדפיס סדר לקסקוגרפי. עם זאת, כאשר משתמשים ב-somepath(a,b), התוצאות יודפסו במקום זאת בסדר deps.

כאשר סימון זה הוא no ו---output הוא אחד מהבאים build, label, label_kind, location, package, proto או xml, התוצאות יודפסו בסדר שרירותי. בדרך כלל, זו האפשרות המהירה ביותר. עם זאת, אפשרות זו לא נתמכת כאשר --output הוא אחד מ-graph, minrank או maxrank: בפורמטים האלה, Bazel תמיד מדפיס תוצאות שמסודרות לפי סדר התלות או הדירוג.

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

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

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

הדפסת טופס המקור של יעדים כפי שהוא יופיע ב-BUILD

--output build

באפשרות זו, הייצוג של כל יעד הוא כאילו נכתב בכתב יד בשפה האנגלית. כל המשתנים והקריאות של הפונקציות (כמו גלובוס, פקודות מאקרו) מתרחבות, והן עוזרות לראות את ההשפעה של פקודות מאקרו של Starlark. בנוסף, כל כלל יעיל מדווח על הערך generator_name ו/או generator_function, ומציין את שם המאקרו שהוערך כדי להפיק את הכלל האפקטיבי.

למרות שהפלט משתמש באותה תחביר כמו קובצי BUILD, לא מובטח ליצור קובץ BUILD חוקי.

--output label

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

כשמדפיסים את הפלט של שאילתת somepath, הסדר שבו הצמתים מודפסים הוא הסדר של הנתיב.

אזהרה: במקרים מסוימים, ייתכן שיהיו שני יעדים שונים עם אותה תווית. לדוגמה, כלל sh_binary והקובץ הייחודי (המשתמע) שלו srcs עשויים להיקרא foo.sh. אם התוצאה של שאילתה מכילה את שני היעדים האלה, הפלט (בפורמט label) יופיע וכולל כפילות. כשמשתמשים בפורמט label_kind (ראו בהמשך), יש הבחנה ברורה: לשני היעדים יש שם זהה, אבל לאחד מהם יש סוג sh_binary rule וסוג אחר source file.

--output label_kind

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

--output minrank --output maxrank

בדומה לlabel, הפורמטים של הפלט minrank ו-maxrank מדפיסים את התוויות של כל יעד בתרשים שיתקבל, אבל במקום להופיע בסדר טופולוגי הם מופיעים בסדר דירוג לפני מספר הדירוג שלהם. הסימון הזה לא משפיע על סימון התוצאה --[no]order_results (ראו הערות בסדר הסדר של התוצאות).

יש שתי גרסאות של הפורמט הזה: minrank מדרג כל צומת לפי האורך של הנתיב הקצר ביותר מצומת הבסיס. "root" צמתים (שאין להם קצוות נכנסים) הם בדירוג 0, היורשים שלהם הם בדירוג 1 וכו' (כמו תמיד, הקצוות מכוונים מיעד לדרישות המוקדמות שלו: היעדים שהוא תלוי בהם).

maxrank מדרג כל צומת לפי האורך של הנתיב הארוך ביותר מצומת הבסיס. שוב, "roots" מקבלים דירוג 0, לכל שאר הצמתים יש דירוג גבוה יותר מהדירוג המקסימלי של כל הקודםים.

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

הפורמטים האלה מאפשרים לגלות את מידת העומק של התרשים. אם משתמשים בה כתוצאה משאילתה deps(x), rdeps(x) או allpaths, מספר הדירוג שווה לאורך הקצר ביותר (עם minrank) או לאורך הארוך ביותר (עם maxrank) מצומת x באותו צומת. אפשר להשתמש ב-maxrank כדי לקבוע את הרצף הארוך ביותר של שלבי build הנדרשים ליצירת יעד.

לדוגמה, התרשים בצד שמאל מניב את הפלט שמשמאל כאשר מציינים את --output minrank ואת --output maxrank, בהתאמה.

בדירוג
      minrank

      0 //c:c
      1 //b:b
      1 //a:a
      2 //b:b.cc
      2 //a:a.cc
      
      maxrank

      0 //c:c
      1 //b:b
      2 //a:a
      2 //b:b.cc
      3 //a:a.cc
      
--output location

בדומה ל-label_kind, האפשרות הזו תודפס עבור כל יעד בתוצאה, הסוג והתווית של היעד, אבל הקידומת של המספר כוללת את שם היעד ומספר הקובץ. הפורמט דומה לפלט של grep. לכן, כלים שיכולים לנתח את השנייה (כגון Emacs או vi) יכולים גם להשתמש בפלט השאילתה כדי לעבור על סדרת התאמות, וכך ניתן להשתמש בכלי השאילתות של Bazel בתור תלויי-גרפיקה ו-"grip עבור קובצי BUILD.

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

--output package

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

הפורמט של חבילות במאגרים חיצוניים הוא @repo//foo/bar, ואילו חבילות במאגר הראשי הן בפורמט foo/bar.

בשילוב עם השאילתה deps(...), אפשר להשתמש באפשרות הפלט הזו כדי למצוא את חבילת החבילות שצריך לבדוק כדי ליצור קבוצה של יעדים.

הצגת תרשים של התוצאה

--output graph

אפשרות זו גורמת להדפסה של תוצאת השאילתה כתרשים מכוון בפורמט הפופולרי AT&T GraphViz. בדרך כלל, התוצאה נשמרת בקובץ כמו .png או .svg. (אם התוכנית dot לא מותקנת בתחנת העבודה שלכם, תוכלו להתקין אותה באמצעות הפקודה sudo apt-get install graphviz). ניתן לעיין בקטע לדוגמה שבהמשך כדי לראות הפעלה לדוגמה.

פורמט הפלט הזה שימושי במיוחד לשאילתות של allpaths, deps או rdeps, שהתוצאה שלהן כוללת קבוצת נתיבים שאי אפשר להמחיש בקלות בזמן עיבוד בפורמט לינארי, כמו --output label.

כברירת מחדל, התרשים מעובד באופן מחושב. כלומר, הצמתים המקבילים מבחינה טופולוגית ממוזגים ומשולבים לצומת אחד עם תוויות מרובות. לכן, התרשים קומפקטי יותר וקריא יותר, כי תרשימים של תוצאות אופייניות מכילים דפוסים שחוזרים על עצמם. לדוגמה, כלל java_library עשוי להיות תלוי במאות קובצי מקור של Java, שנוצרו כולם על ידי אותו genrule. בתרשים המקור, כל הקבצים האלה מיוצגים על ידי צומת יחיד. ייתכן שההתנהגות הזו תושבת כשבוחרים באפשרות --nograph:factored.

--graph:node_limit n

האפשרות מציינת את האורך המקסימלי של מחרוזת התווית עבור צומת גרף בפלט. תוויות ארוכות יותר יקוצרו; 1- משביתה את הקטיעה. בשל אופן החישוב של תרשימים שבהם בדרך כלל מודפסים תרשימים, התוויות של הצמתים עשויות להיות ארוכות מאוד. בתרשים GraphViz לא ניתן לטפל בתוויות שחורגים מ-1024 תווים, שהם ערך ברירת המחדל של האפשרות הזו. לאפשרות הזו אין השפעה, אלא אם נעשה שימוש ב---output=graph.

--[no]graph:factored

כברירת מחדל, התרשימים מוצגים בצורת גורמים, כפי שמוסבר למעלה. אם מציינים את --nograph:factored, התרשימים יודפסו בלי לשקלל. כך תוכלו להשתמש בהצגה חזותית באמצעות GraphViz, אבל הפורמט הפשוט יותר עשוי להקל על העיבוד באמצעות כלים אחרים (כמו grip). לאפשרות הזו אין השפעה אלא אם נעשה שימוש ב---output=graph.

XML

--output xml

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

  <?xml version="1.0" encoding="UTF-8"?>
  <query version="2">

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

</query>

נעשה שימוש בערכים פשוטים ליעדים מסוג file:

  <source-file name='//foo:foo_main.cc' .../>
  <generated-file name='//foo:libfoo.so' .../>

אבל עבור כללים, ה-XML מובנה ומכיל הגדרות של כל מאפייני הכלל, כולל אלה שהערך שלהם לא צוין במפורש בקובץ BUILD של הכלל.

בנוסף, התוצאה כוללת את הרכיבים rule-input ו-rule-output כדי שניתן יהיה לשחזר את הטופולוגיה של תרשים התלות בלי שיהיה צורך לדעת, למשל, שהמאפיינים של המאפיין srcs הם יחסי תלות (דרישות מוקדמות) והתוכן של המאפיין outs הם יחסי תלות לאחור (צרכנים).

רכיבי rule-input עבור תלויות מרומזות מבוטלים אם צוין --noimplicit_deps.

  <rule class='cc_binary rule' name='//foo:foo' ...>
    <list name='srcs'>
      <label value='//foo:foo_main.cc'/>
      <label value='//foo:bar.cc'/>
      ...
    </list>
    <list name='deps'>
      <label value='//common:common'/>
      <label value='//collections:collections'/>
      ...
    </list>
    <list name='data'>
      ...
    </list>
    <int name='linkstatic' value='0'/>
    <int name='linkshared' value='0'/>
    <list name='licenses'/>
    <list name='distribs'>
      <distribution value="INTERNAL" />
    </list>
    <rule-input name="//common:common" />
    <rule-input name="//collections:collections" />
    <rule-input name="//foo:foo_main.cc" />
    <rule-input name="//foo:bar.cc" />
    ...
  </rule>

כל רכיב XML ליעד מכיל מאפיין של name, שהערך שלו הוא תווית היעד, ומאפיין location שהערך שלו הוא מיקום היעד ב-&.

--[no]xml:line_numbers

כברירת מחדל, המיקומים שמוצגים בפלט ה-XML מכילים מספרי שורות. כאשר מציינים את --noxml:line_numbers, מספרי השורות לא מודפסים.

--[no]xml:default_values

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

ביטויים רגולריים

ביטויים רגולריים בשפה של השאילתה משתמשים בספריית הביטוי הרגולרי Java, כך שאתם יכולים להשתמש בתחביר המלא של java.util.regex.Pattern.

שליחת שאילתות עם מאגרים חיצוניים

אם ה-build תלוי בכללים ממאגרים חיצוניים (שמוגדרים בקובץ ה-WORKSPACE), תוצאות השאילתה יכללו את התלות האלה. לדוגמה, אם המאפיין //foo:bar תלוי ב-//external:some-lib ו-//external:some-lib משויך ל-@other-repo//baz:lib, אז ב-bazel query 'deps(//foo:bar)' יפורטו גם @other-repo//baz:lib וגם //external:some-lib.

מאגרים חיצוניים אחרים לא תלויים ב-build. כלומר, בדוגמה שלמעלה, //external:other-repo לא תלוי. עם זאת, ניתן לשלוח שאילתה לגבי חברות בחבילה של //external, לדוגמה:

  # Querying over all members of //external returns the repository.
  bazel query 'kind(http_archive, //external:*)'
  //external:other-repo

  # ...but the repository is not a dependency.
  bazel query 'kind(http_archive, deps(//foo:bar))'
  INFO: Empty results