הדף הזה הוא מדריך העזר לשפת השאילתות של 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 ... ')'
שפת השאילתה מגדירה מספר פונקציות. שם הפונקציה קובע את מספר הארגומנטים ואת סוגו. הפונקציות הבאות זמינות:
allpaths
attr
buildfiles
rbuildfiles
deps
filter
kind
labels
loadfiles
rdeps
allrdeps
same_pkg_direct_rdeps
siblings
some
somepath
tests
visible
סגירה תלויה של יחסי תלות: נקודות שפל
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(expr, count )
האופרטור some(x, k)
בוחר עד k יעדים באופן שרירותי מתוך קבוצת הארגומנטים x, ומבצע הערכה לקבוצה שמכילה רק את היעדים האלה. הפרמטר k הוא אופציונלי. אם הוא חסר, התוצאה תהיה קבוצת יחיד שמכילה רק יעד אחד באופן אקראי. אם הקבוצה של הארגומנטים x קטנה מ-k, הפונקציה תחזיר את קבוצת הארגומנטים x.
לדוגמה, הביטוי some(//foo:main union //bar:baz)
מבצע הערכה לקבוצת סינגל שמכילה את //foo:main
או את //bar:baz
, למרות שהביטוי לא מוגדר. הביטוי some(//foo:main union //bar:baz, 2)
או הביטוי some(//foo:main union //bar:baz, 3)
מחזירים גם את //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.
התרשימים שמתקבלים מסודרים בהתאם ליחס התלות. מידע נוסף אפשר למצוא בקטע הזמנת תרשים.
סינון של סוג היעד: סוג
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
ההיקף של האופרטור --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