Trang này trình bày cách bắt đầu sử dụng ngôn ngữ truy vấn của Bazel để theo dõi các phần phụ thuộc trong mã của bạn.
Để biết thông tin chi tiết về ngôn ngữ và --output cờ, vui lòng xem
hướng dẫn tham khảo, tài liệu tham khảo về truy vấn Bazel
và tài liệu tham khảo về cquery Bazel. Bạn có thể nhận trợ giúp bằng cách nhập bazel help query hoặc bazel help cquery trên dòng lệnh.
Để thực thi một truy vấn trong khi bỏ qua các lỗi như mục tiêu bị thiếu, hãy sử dụng cờ --keep_going.
Tìm các phần phụ thuộc của một quy tắc
Để xem các phần phụ thuộc của //foo, hãy sử dụng hàm deps trong truy vấn bazel:
$ bazel query "deps(//foo)" //foo:foo //foo:foo-dep ...
Đây là tập hợp tất cả các mục tiêu cần thiết để tạo //foo.
Theo dõi chuỗi phần phụ thuộc giữa hai gói
Thư viện //third_party/zlib:zlibonly không có trong tệp BUILD cho //foo, nhưng đây là một phần phụ thuộc gián tiếp. Làm cách nào để theo dõi đường dẫn phần phụ thuộc này? Có 2 hàm hữu ích ở đây: allpaths và somepath. Bạn cũng có thể muốn loại trừ các phần phụ thuộc của công cụ bằng --notool_deps nếu chỉ quan tâm đến những nội dung có trong cấu phần phần mềm mà bạn đã tạo, chứ không phải mọi công việc có thể có.
Để hình dung biểu đồ của tất cả các phần phụ thuộc, hãy chuyển đầu ra của truy vấn bazel qua
công cụ dòng lệnh dot:
$ bazel query "allpaths(//foo, third_party/...)" --notool_deps --output graph | dot -Tsvg > /tmp/deps.svg
Khi biểu đồ phần phụ thuộc lớn và phức tạp, bạn có thể bắt đầu với một đường dẫn duy nhất:
$ 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
Nếu không chỉ định --output graph bằng allpaths, bạn sẽ nhận được danh sách phẳng của biểu đồ phần phụ thuộc.
$ 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
Lưu ý: phần phụ thuộc ngầm ẩn
Tệp BUILD cho //foo không bao giờ tham chiếu đến //translations/tools:aggregator. Vậy phần phụ thuộc trực tiếp ở đâu?
Một số quy tắc bao gồm các phần phụ thuộc ngầm ẩn trên các thư viện hoặc công cụ bổ sung.
Ví dụ: để tạo quy tắc genproto, trước tiên, bạn cần tạo Trình biên dịch giao thức, vì vậy, mọi quy tắc genproto đều có một phần phụ thuộc ngầm ẩn trên trình biên dịch giao thức. Các phần phụ thuộc này không được đề cập trong tệp bản dựng, nhưng được thêm vào bằng công cụ bản dựng. Tập hợp đầy đủ các phần phụ thuộc ngầm ẩn hiện
chưa được ghi lại. Việc sử dụng --noimplicit_deps cho phép bạn lọc các phần phụ thuộc này khỏi kết quả truy vấn. Đối với cquery, điều này sẽ bao gồm các chuỗi công cụ đã phân giải.
Phần phụ thuộc ngược
Bạn có thể muốn biết tập hợp các mục tiêu phụ thuộc vào một số mục tiêu. Ví dụ: nếu bạn sắp thay đổi một số mã, bạn có thể muốn biết những mã khác mà bạn sắp làm hỏng. Bạn có thể sử dụng rdeps(u, x) để tìm các phần phụ thuộc ngược
của các mục tiêu trong x trong bao đóng bắc cầu của u.
Truy vấn Sky của Bazel
hỗ trợ hàm allrdeps, cho phép bạn truy vấn các phần phụ thuộc ngược
trong một vũ trụ mà bạn chỉ định.
Các cách sử dụng khác
Bạn có thể sử dụng bazel query để phân tích nhiều mối quan hệ phụ thuộc.
Những gì tồn tại ...
Những gói nào tồn tại bên dưới foo?
bazel query 'foo/...' --output package
Những quy tắc nào được xác định trong gói foo?
bazel query 'kind(rule, foo:*)' --output label_kind
Những tệp nào được tạo bởi các quy tắc trong gói foo?
bazel query 'kind("generated file", //foo:*)'Những mục tiêu nào được tạo bởi macro starlark foo?
bazel query 'attr(generator_function, foo, //path/to/search/...)'
Tập hợp các tệp BUILD cần thiết để tạo //foo là gì?
bazel query 'buildfiles(deps(//foo))' | cut -f1 -d:
Những thử nghiệm riêng lẻ mà test_suite mở rộng là gì?
bazel query 'tests(//foo:smoke_tests)'
Những thử nghiệm nào trong số đó là thử nghiệm C++?
bazel query 'kind(cc_.*, tests(//foo:smoke_tests))'
Những thử nghiệm nào trong số đó là thử nghiệm nhỏ? Thử nghiệm trung bình? Thử nghiệm lớn?
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))'
Những thử nghiệm nào bên dưới foo khớp với một mẫu?
bazel query 'filter("pa?t", kind(".*_test rule", //foo/...))'Mẫu là một biểu thức chính quy và được áp dụng cho tên đầy đủ của quy tắc. Tương tự như việc thực hiện
bazel query 'kind(".*_test rule", //foo/...)' | grep -E 'pa?t'Gói nào chứa tệp path/to/file/bar.java?
bazel query path/to/file/bar.java --output=package
Nhãn bản dựng cho path/to/file/bar.java? là gì?
bazel query path/to/file/bar.java
Mục tiêu(các) quy tắc nào chứa tệp path/to/file/bar.java làm nguồn?
fullname=$(bazel query path/to/file/bar.java)
bazel query "attr('srcs', $fullname, ${fullname//:*/}:*)"
Những phần phụ thuộc của gói nào tồn tại ...
foo phụ thuộc vào những gói nào? (Tôi cần kiểm tra những gì để tạo foo)
bazel query 'buildfiles(deps(//foo:foo))' --output package
Cây foo phụ thuộc vào những gói nào, ngoại trừ foo/contrib?
bazel query 'deps(foo/... except foo/contrib/...)' --output package
Những phần phụ thuộc của quy tắc nào tồn tại ...
Những quy tắc genproto nào mà bar phụ thuộc vào?
bazel query 'kind(genproto, deps(bar/...))'
Tìm định nghĩa của một số thư viện JNI (C++) được phụ thuộc bắc cầu bởi một quy tắc nhị phân Java trong cây servlet.
bazel query 'some(kind(cc_.*library, deps(kind(java_binary, //java/com/example/frontend/...))))' --output location
...Bây giờ hãy tìm định nghĩa của tất cả các tệp nhị phân Java phụ thuộc vào chúng
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)'
Những phần phụ thuộc của tệp nào tồn tại ...
Tập hợp đầy đủ các tệp nguồn Java cần thiết để tạo foo là gì?
Tệp nguồn:
bazel query 'kind("source file", deps(//path/to/target/foo/...))' | grep java$Tệp được tạo:
bazel query 'kind("generated file", deps(//path/to/target/foo/...))' | grep java$Tập hợp đầy đủ các tệp nguồn Java cần thiết để tạo các thử nghiệm của QUX là gì?
Tệp nguồn:
bazel query 'kind("source file", deps(kind(".*_test rule", javatests/com/example/qux/...)))' | grep java$Tệp được tạo:
bazel query 'kind("generated file", deps(kind(".*_test rule", javatests/com/example/qux/...)))' | grep java$Những điểm khác biệt nào về phần phụ thuộc giữa X và Y tồn tại ...
//foo phụ thuộc vào những mục tiêu nào mà //foo:foolib không phụ thuộc?
bazel query 'deps(//foo) except deps(//foo:foolib)'
Những thư viện C++ nào mà các thử nghiệm foo phụ thuộc vào mà tệp nhị phân sản xuất //foo không phụ thuộc vào?
bazel query 'kind("cc_library", deps(kind(".*test rule", foo/...)) except deps(//foo))'Tại sao phần phụ thuộc này tồn tại ...
Tại sao bar phụ thuộc vào groups2?
bazel query 'somepath(bar/...,groups2/...:*)'
Sau khi có kết quả của truy vấn này, bạn thường sẽ thấy một mục tiêu duy nhất nổi bật là phần phụ thuộc không mong muốn hoặc nghiêm trọng và không mong muốn của bar. Sau đó, bạn có thể tinh chỉnh thêm truy vấn để:
Cho tôi xem đường dẫn từ docker/updater:updater_systest (py_test) đến một số cc_library mà nó phụ thuộc vào:
bazel query 'let cc = kind(cc_library, deps(docker/updater:updater_systest)) in somepath(docker/updater:updater_systest, $cc)'
Tại sao thư viện //photos/frontend:lib phụ thuộc vào 2 biến thể của cùng một thư viện //third_party/jpeglib và //third_party/jpeg?
Truy vấn này được rút gọn thành: "cho tôi xem biểu đồ con của //photos/frontend:lib phụ thuộc vào cả hai thư viện". Khi được hiển thị theo thứ tự tô pô, phần tử cuối cùng của kết quả là thủ phạm có khả năng cao nhất.
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
Những gì phụ thuộc vào ...
Những quy tắc nào trong bar phụ thuộc vào Y?
bazel query 'bar/... intersect allpaths(bar/..., Y)'
Những mục tiêu nào phụ thuộc trực tiếp vào T, trong gói của T?
bazel query 'same_pkg_direct_rdeps(T)'
Làm cách nào để phá vỡ phần phụ thuộc ...
Tôi phải phá vỡ những đường dẫn phần phụ thuộc nào để bar không còn phụ thuộc vào X nữa?
Cách xuất biểu đồ vào tệp svg:
bazel query 'allpaths(bar/...,X)' --output graph | dot -Tsvg > /tmp/dep.svg
Khác
Có bao nhiêu bước tuần tự trong bản dựng //foo-tests?
Rất tiếc, ngôn ngữ truy vấn hiện không thể cung cấp cho bạn đường dẫn dài nhất từ x đến y, nhưng có thể tìm thấy nút xa nhất (hoặc đúng hơn là một) từ điểm bắt đầu hoặc cho bạn thấy độ dài của đường dẫn dài nhất từ x đến mọi y mà nó phụ thuộc vào. Sử dụng maxrank:
bazel query 'deps(//foo-tests)' --output maxrank | tail -1 85 //third_party/zlib:zutil.c
Kết quả cho biết rằng có các đường dẫn có độ dài 85 phải xuất hiện theo thứ tự trong bản dựng này.