Hướng dẫn truy vấn

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à thông tin chi tiết về cờ --output, vui lòng xem các sổ tay tham khảo, Tài liệu tham khảo về truy vấn BazelTà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ư thiếu mục tiê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 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ụ thuộc này? Có 2 hàm hữu ích ở đây: allpathssomepath. 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 gì 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ó.

Để trực quan hoá 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 nên bắt đầu bằng 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 được đơn giản hoá 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

Tệp BUILD cho //foo không bao giờ tham chiếu đến //translations/tools:aggregator. Vậy, sự phụ thuộc trực tiếp nằm ở đâu?

Một số quy tắc có các phần phụ thuộc ngầm 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 ProtocolCompiler, vì vậy, mọi quy tắc genproto đều có một phần phụ thuộc ngầm 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ụ tạo bản dựng. Hiện tại, toàn bộ các phần phụ thuộc ngầm ẩn đều chưa được ghi lại. Khi sử dụng --noimplicit_deps, bạn có thể lọc các deps này khỏi kết quả truy vấn. Đối với cquery, điều này sẽ bao gồm cả các chuỗi công cụ đã phân giải.

Phần phụ thuộc đảo 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 mục tiêu nào đó. Ví dụ: nếu sắp sửa đổi một số mã, bạn có thể muốn biết những mã khác mà bạn sắp sửa đổi. Bạn có thể sử dụng rdeps(u, x) để tìm các phần phụ thuộc đảo ngược của các mục tiêu trong x trong bao đóng bắc cầu của u.

Sky Query của Bazel hỗ trợ hàm allrdeps, cho phép bạn truy vấn các phần phụ thuộc đảo ngược trong một vũ trụ mà bạn chỉ định.

Các trường hợp sử dụng khác

Bạn có thể 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 nằm 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 theo các quy tắc trong gói foo?

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

Mục tiêu nào được tạo bởi macro starlark foo?

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

Cần có những tệp BUILD nào để tạo //foo?

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

test_suite mở rộng thành những kiểm thử riêng lẻ nào?

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

Những kiểm thử nào trong số đó là kiểm thử C++?

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

Những loại nào có kích thước nhỏ? Trung bình? 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 kiểm thử 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 này là một biểu thức chính quy và được áp dụng cho tên đầy đủ của quy tắc. Điều này 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 của path/to/file/bar.java? là gì

bazel query path/to/file/bar.java

(Các) mục tiêu 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 hiện có ...

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 nào của quy tắc tồn tại ...

bar phụ thuộc vào những quy tắc genproto nào?

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

Tìm định nghĩa của một số thư viện JNI (C++) mà quy tắc nhị phân Java phụ thuộc một cách bắc cầu trong cây servlet.

bazel query 'some(kind(cc_.*library, deps(kind(java_binary, //java/com/example/frontend/...))))' --output location
...Giờ đây, 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 hiện có ...

Bạn cần có những tệp nguồn Java nào để tạo foo?

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 kiểm thử 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 về phần phụ thuộc giữa X và Y là gì ...

//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 kiểm thử 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 lại có phần phụ thuộc này ...

Tại sao bar lại 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à một 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 thành:

Cho tôi xem đường dẫn từ docker/updater:updater_systest (một py_test) đến một số cc_library mà đường dẫ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 lại phụ thuộc vào 2 biến thể của cùng một thư viện //third_party/jpeglib//third_party/jpeg?

Truy vấn này được rút gọn thành: "cho tôi xem đồ thị con của //photos/frontend:lib phụ thuộc vào cả hai thư viện". Khi được hiển thị theo thứ tự liên kết, phần tử cuối cùng của kết quả là nguyên nhân 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

Điều gì phụ thuộc vào ...

Quy tắc nào dưới thanh 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ỡ một mối quan hệ phụ thuộc ...

Tôi phải phá vỡ những đường dẫ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 đồ sang 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 quy trình tạo //foo-tests?

Rất tiếc, ngôn ngữ truy vấn hiện không thể cho bạn biết đườ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 biết độ dài của đường dẫn dài nhất từ x đến mọi y mà đường dẫ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 thấy 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.