הדרכה בנושא Bazel

ריכזנו במאמר הזה מידע על תחילת העבודה עם שפת השאילתות של Bazel&#39. מעקב אחר יחסי תלות בקוד שלכם.

כדי לקבל פרטים על השפה ופרטים על הדגל של --output, עיינו במדריכים הרלוונטיים, בהפניות לשאילתות ב-Bazel ובהפניות לשאילתות ב-Bazel. כדי לקבל עזרה, מקלידים bazel help query או bazel help cquery בשורת הפקודה.

כדי לבצע שאילתה תוך התעלמות משגיאות כמו יעדים חסרים, יש להשתמש בסימון --keep_going.

מציאת תלויות של כלל

כדי לראות את התלות של //foo, צריך להשתמש בפונקציה deps בשדה השאילתה:

$ bazel query "deps(//foo)"
//foo:foo
//foo:foo-dep
...

זוהי הקבוצה של כל היעדים הנדרשים ליצירת //foo.

מעקב אחר שרשרת התלות בין שתי חבילות

הספרייה //third_party/zlib:zlibonly לא נמצאת בקובץ BUILD עבור //foo, אבל היא תלויה באופן עקיף. איך אפשר לעקוב אחרי נתיב התלות הזה? יש שתי פונקציות שימושיות כאן: allpaths וsomepath. יכול להיות שתרצו להחריג גם את התלות בכלים של --notool_deps, אם חשוב לכם רק מה שנכלל בחפצי האומנות שיצרתם, ולא כל משימה אפשרית.

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

$ bazel query "allpaths(//foo, third_party/...)" --notool_deps --output graph | dot -Tsvg > /tmp/deps.svg

כאשר תרשים תלות הוא גדול ומורכב, מומלץ להתחיל עם נתיב אחד:

$ bazel query "somepath(//foo:foo, third_party/zlib:zlibonly)"
//foo:foo
//translations/tools:translator
//translations/base:base
//third_party/py/MySQL:MySQL
//third_party/py/MySQL:_MySQL.so
//third_party/mysql:mysql
//third_party/zlib:zlibonly

אם לא תציינו את --output graph באמצעות allpaths, תוצג רשימה שטוחה של תרשים התלות.

$ bazel query "allpaths(//foo, third_party/...)"
  ...many errors detected in BUILD files...
//foo:foo
//translations/tools:translator
//translations/tools:aggregator
//translations/base:base
//tools/pkg:pex
//tools/pkg:pex_phase_one
//tools/pkg:pex_lib
//third_party/python:python_lib
//translations/tools:messages
//third_party/py/xml:xml
//third_party/py/xml:utils/boolean.so
//third_party/py/xml:parsers/sgmlop.so
//third_party/py/xml:parsers/pyexpat.so
//third_party/py/MySQL:MySQL
//third_party/py/MySQL:_MySQL.so
//third_party/mysql:mysql
//third_party/openssl:openssl
//third_party/zlib:zlibonly
//third_party/zlib:zlibonly_v1_2_3
//third_party/python:headers
//third_party/openssl:crypto

לצד: יחסי תלות מרומזים

קובץ BUILD עבור //foo אף פעם לא מפנה ל-//translations/tools:aggregator. כלומר, היכן התלות הישירה?

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

יחסי תלות הפוך

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

Bazel's Sky Query מאפשרת להפעיל את הפונקציה allrdeps, המאפשרת לבצע שאילתות על יחסי תלות הפוךים ביקום שצוין.

שימושים שונים

אפשר להשתמש ב-bazel query כדי לנתח קשרים תלויים רבים.

מה קיים ...

אילו חבילות קיימות מתחת ל-foo?

bazel query 'foo/...' --output package

אילו כללים מוגדרים בחבילה foo?

bazel query 'kind(rule, foo:*)' --output label_kind

אילו קבצים נוצרים על ידי כללים בחבילה foo?

bazel query 'kind("generated file", //foo:*)'

אילו יעדים נוצרים על ידי מאקרו Starlark foo?

bazel query 'attr(generator_function, foo, //path/to/search/...)'

איזו קבוצת קבצים של BUILD נדרשת כדי לבנות את //foo?

bazel query 'buildfiles(deps(//foo))' | cut -f1 -d:

לאילו בדיקות אישיות מתרחבת test_suite?

bazel query 'tests(//foo:smoke_tests)'

אילו מהבדיקות הבאות הן C++ ?

bazel query 'kind(cc_.*, tests(//foo:smoke_tests))'

אילו מהן קטנות? בינוני? גדול?

bazel query 'attr(size, small, tests(//foo:smoke_tests))'

bazel query 'attr(size, medium, tests(//foo:smoke_tests))'

bazel query 'attr(size, large, tests(//foo:smoke_tests))'

מהן הבדיקות שמתחת ל-foo שתואמות לדפוס?

bazel query 'filter("pa?t", kind(".*_test rule", //foo/...))'

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

bazel query 'kind(".*_test rule", //foo/...)' | grep -E 'pa?t'

איזו חבילה מכילה את הקובץ path/to/file/bar.java?

 bazel query path/to/file/bar.java --output=package

מהי תווית ה-build של path/to/file/bar.java?

bazel query path/to/file/bar.java

אילו יעדים של כללים מכילים את הקובץ path/to/file/bar.java כמקור?

fullname=$(bazel query path/to/file/bar.java)
bazel query "attr('srcs', $fullname, ${fullname//:*/}:*)"

אילו תלויות חבילות קיימות ...

על אילו חבילות האפליקציה foo תלויה? (מה צריך לעשות כדי ליצור foo?)

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

על אילו חבילות תלוי עץ foo, מלבד foo/contrib?

bazel query 'deps(foo/... except foo/contrib/...)' --output package

מהם יחסי תלות של כלל ...

על אילו כללי ג'נטוטו תלויה עמודה?

bazel query 'kind(genproto, deps(bar/...))'

מאתרים את ההגדרה של ספריית JNI (C++ ) שתלויה באופן זמני בכלל בינארי של Java בעץ הגשה.

bazel query 'some(kind(cc_.*library, deps(kind(java_binary, //java/com/example/frontend/...))))' --output location
...עכשיו מוצאים את ההגדרות של כל הנתונים הבינאריים של Java שתלויים בהם
bazel query 'let jbs = kind(java_binary, //java/com/example/frontend/...) in
  let cls = kind(cc_.*library, deps($jbs)) in
    $jbs intersect allpaths($jbs, $cls)'

מהם יחסי תלות של קבצים ...

מהי הקבוצה המלאה של קובצי המקור של Java הנדרשים כדי לבנות foo?

קובצי מקור:

bazel query 'kind("source file", deps(//path/to/target/foo/...))' | grep java$

קבצים שנוצרו:

bazel query 'kind("generated file", deps(//path/to/target/foo/...))' | grep java$

מהי הקבוצה המלאה של קובצי המקור ב-Java הנדרשים כדי לבנות בדיקות QUX'

קובצי מקור:

bazel query 'kind("source file", deps(kind(".*_test rule", javatests/com/example/qux/...)))' | grep java$

קבצים שנוצרו:

bazel query 'kind("generated file", deps(kind(".*_test rule", javatests/com/example/qux/...)))' | grep java$

מה ההבדלים בין יחסי תלות בין X ל-Y ...

אילו יעדים תלויים ב//foo מבחינת //foo:foolib?

bazel query 'deps(//foo) except deps(//foo:foolib)'

באילו ספריות C++ תלויות הבדיקות foo שבינארי //foo לא תלוי?

bazel query 'kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo))'

למה התלות הזאת קיימת ...

למה bar תלוי ב-groups2?

bazel query 'somepath(bar/...,groups2/...:*)'

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

אני רוצה לראות נתיב מ-docker/updater:updater_systest (py_test) אל cc_library שהוא תלוי בו:

bazel query 'let cc = kind(cc_library, deps(docker/updater:updater_systest)) in
  somepath(docker/updater:updater_systest, $cc)'

למה הספרייה //photos/frontend:lib תלויה בשתי גרסאות של אותה ספרייה //third_party/jpeglib ו//third_party/jpeg?

השאילתה הזו מתבססת על: "Show me the subscript of //photos/frontend:lib שתלוי בשתי הספריות" כשהוא מוצג בסדר טופולוגי, הרכיב האחרון של התוצאה הוא הגורם הסביר ביותר בסבירות הגבוהה ביותר.

bazel query 'allpaths(//photos/frontend:lib, //third_party/jpeglib)
                intersect
               allpaths(//photos/frontend:lib, //third_party/jpeg)'
//photos/frontend:lib
//photos/frontend:lib_impl
//photos/frontend:lib_dispatcher
//photos/frontend:icons
//photos/frontend/modules/gadgets:gadget_icon
//photos/thumbnailer:thumbnail_lib
//third_party/jpeg/img:renderer

מה תלוי ...

אילו כללים מתחת לרף תלויים ב-Y?

bazel query 'bar/... intersect allpaths(bar/..., Y)'

אילו יעדים תלויים ישירות ב-T, בחבילת T'

bazel query 'same_pkg_direct_rdeps(T)'

איך מבטלים קשרי תלות ...

אילו נתיבי תלות עליי לשבור כדי ש-bar לא יהיה יותר תלוי ב-X?

כדי לייצא את התרשים לקובץ svg:

bazel query 'allpaths(bar/...,X)' --output graph | dot -Tsvg > /tmp/dep.svg

שונות

כמה שלבים עוקבים יש ב-build של //foo-tests?

לצערנו, שפת השאילתה לא יכולה לספק לכם את הנתיב הארוך ביותר מ-x עד Y, אבל היא יכולה למצוא את הצומת הארוך ביותר (או a) מנקודת ההתחלה או את הארוכים של האורך של הנתיב הארוך ביותר, מ-x ועד כל שנה, תלוי. שימוש בmaxrank:

bazel query 'deps(//foo-tests)' --output maxrank | tail -1
85 //third_party/zlib:zutil.c

התוצאה מצביעה על כך שיש נתיבים באורך 85 שחייבים להתרחש בסדר הזה.