Tài liệu tham khảo về truy vấn Bazel

Trang này là tài liệu hướng dẫn tham khảo cho Ngôn ngữ truy vấn Bazel được dùng khi bạn sử dụng bazel query để phân tích các phần phụ thuộc của bản dựng. Tệp này cũng mô tả các định dạng đầu ra mà bazel query hỗ trợ.

Để biết các trường hợp sử dụng thực tế, hãy xem Hướng dẫn về truy vấn Bazel.

Tài liệu tham khảo về truy vấn khác

Ngoài query, chạy trên biểu đồ mục tiêu giai đoạn sau tải, Bazel còn bao gồm truy vấn biểu đồ hành độngtruy vấn có thể định cấu hình.

Truy vấn biểu đồ hành động

Truy vấn biểu đồ hành động (aquery) hoạt động trên Biểu đồ mục tiêu đã định cấu hình sau khi phân tích và hiển thị thông tin về Hành động, Cấu phần phần mềm và mối quan hệ của chúng. aquery rất hữu ích khi bạn quan tâm đến các thuộc tính của Hành động/Cấu phần phần mềm được tạo từ Biểu đồ mục tiêu đã định cấu hình. Ví dụ: các lệnh thực tế sẽ chạy cũng như dữ liệu đầu vào, đầu ra và hoạt động ghi nhớ của các lệnh đó.

Để biết thêm thông tin chi tiết, hãy xem tài liệu tham khảo về truy vấn.

Truy vấn có thể định cấu hình

Truy vấn Bazel truyền thống chạy trên biểu đồ mục tiêu giai đoạn sau tải và do đó không có khái niệm về cấu hình cũng như các khái niệm liên quan. Đáng chú ý là phương thức này không phân giải chính xác các câu lệnh chọn mà thay vào đó trả về tất cả độ phân giải có thể có cho các lựa chọn. Tuy nhiên, môi trường truy vấn có thể định cấu hình, cquery, xử lý đúng cách các cấu hình nhưng không cung cấp tất cả chức năng của truy vấn gốc này.

Để biết thêm thông tin chi tiết, hãy xem tài liệu tham khảo về BigQuery.

Ví dụ

Mọi người sử dụng bazel query như thế nào? Dưới đây là các ví dụ điển hình:

Tại sao cây //foo phụ thuộc vào //bar/baz? Hiển thị một đường dẫn:

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

Tất cả kiểm thử foo có thư viện C++ nào phụ thuộc vào mà mục tiêu foo_bin không?

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

Mã thông báo: Cú pháp từ vựng

Biểu thức trong ngôn ngữ truy vấn bao gồm các mã thông báo sau:

  • Từ khoá, chẳng hạn như let. Từ khoá là những từ dành riêng của ngôn ngữ và mỗi từ được mô tả ở bên dưới. Bộ từ khoá hoàn chỉnh là:

  • Các từ, chẳng hạn như "foo/..." hoặc ".*test rule" hoặc "//bar/baz:all". Nếu một chuỗi ký tự "được trích dẫn" (bắt đầu và kết thúc bằng một dấu ngoặc đơn " hoặc bắt đầu và kết thúc bằng một dấu ngoặc kép "), thì đó là một từ. Nếu một chuỗi ký tự không được đặt trong dấu ngoặc kép, thì chuỗi đó vẫn có thể được phân tích cú pháp dưới dạng một từ. Từ không trích dẫn là chuỗi ký tự được vẽ từ các ký tự bảng chữ cái A-Za-z, chữ số từ 0 đến 9 và các ký tự đặc biệt */@.-_:$~[] (dấu hoa thị, dấu gạch chéo lên, at, dấu chấm, dấu gạch ngang, dấu gạch dưới, dấu hai chấm, ký hiệu đô la, dấu ngã, dấu ngoặc vuông bên trái, dấu ngoặc vuông bên phải). Tuy nhiên, các từ không trong dấu ngoặc kép không được bắt đầu bằng dấu gạch nối - hoặc dấu hoa thị *, mặc dù [tên mục tiêu] tương đối][(/Concept/labels#target-names) có thể bắt đầu bằng các ký tự đó.

    Các từ không trích dẫn cũng có thể không bao gồm các ký tự dấu cộng + hoặc dấu bằng =, mặc dù các ký tự đó được phép trong tên mục tiêu. Khi viết mã tạo biểu thức truy vấn, tên mục tiêu phải được đặt trong dấu ngoặc kép.

    Việc trích dẫn cần thiết khi viết các tập lệnh tạo biểu thức truy vấn Bazel từ các giá trị do người dùng cung cấp.

     //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.
    

    Xin lưu ý rằng dấu trích dẫn này bổ sung cho mọi đoạn trích dẫn có thể được shell yêu cầu, chẳng hạn như:

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

    Từ khoá, khi được trích dẫn, được xem là các từ thông thường. Ví dụ: some là một từ khoá, nhưng "một số" là một từ. Cả foo và "foo" đều là các từ.

    Tuy nhiên, hãy cẩn thận khi sử dụng dấu ngoặc đơn hoặc dấu ngoặc kép trong tên mục tiêu. Khi trích dẫn một hoặc nhiều tên mục tiêu, chỉ dùng một loại dấu ngoặc kép (toàn bộ hoặc toàn bộ dấu ngoặc kép).

    Sau đây là ví dụ về chuỗi truy vấn 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
    

    Chúng tôi chọn cú pháp này để không cần dấu ngoặc kép trong hầu hết các trường hợp. Ví dụ ".*test rule" (bất thường) cần dấu ngoặc kép: bắt đầu bằng dấu chấm và chứa dấu cách. Việc trích dẫn "cc_library" là không cần thiết nhưng vô hại.

  • Dấu câu, chẳng hạn như dấu ngoặc đơn (), dấu chấm . và dấu phẩy ,. Những từ có chứa dấu câu (ngoài các trường hợp ngoại lệ liệt kê ở trên) phải được đặt trong dấu ngoặc kép.

Hệ thống sẽ bỏ qua các ký tự khoảng trắng bên ngoài một từ đặt trong cặp dấu ngoặc kép.

Khái niệm ngôn ngữ truy vấn Bazel

Ngôn ngữ truy vấn Bazel là ngôn ngữ của biểu thức. Mỗi biểu thức đánh giá một tập hợp mục tiêu được sắp xếp một phần hoặc một biểu đồ (DAG) của mục tiêu tương đương. Đây là kiểu dữ liệu duy nhất.

Thiết lập và biểu đồ đề cập đến cùng một kiểu dữ liệu, nhưng nhấn mạnh các khía cạnh khác nhau, ví dụ:

  • Đã đặt: Thứ tự một phần của các mục tiêu sẽ không được quan tâm.
  • Biểu đồ: Thứ tự một phần của các mục tiêu rất quan trọng.

Các chu kỳ trong biểu đồ phần phụ thuộc

Biểu đồ phần phụ thuộc của bản dựng phải tuần hoàn.

Các thuật toán mà ngôn ngữ truy vấn sử dụng nhằm mục đích sử dụng trong biểu đồ tuần hoàn, nhưng có hiệu quả dựa trên chu kỳ. Thông tin chi tiết về cách xử lý chu kỳ không được nêu rõ và bạn không nên dựa vào.

Phần phụ thuộc ngầm

Ngoài các phần phụ thuộc bản dựng được xác định rõ ràng trong các tệp BUILD, Bazel còn thêm các phần phụ thuộc ngầm ẩn khác vào các quy tắc. Ví dụ: mọi quy tắc Java đều ngầm phụ thuộc vào JavaBuilder. Các phần phụ thuộc ngầm ẩn được thiết lập bằng cách sử dụng các thuộc tính bắt đầu bằng $ và không được ghi đè trong tệp BUILD.

Theo mặc định, bazel query sẽ xem xét các phần phụ thuộc ngầm ẩn khi tính toán kết quả truy vấn. Bạn có thể thay đổi hành vi này bằng tuỳ chọn --[no]implicit_deps. Xin lưu ý rằng vì truy vấn không xem xét cấu hình, nên các chuỗi công cụ tiềm năng sẽ không bao giờ được xem xét.

Âm thanh

Biểu thức ngôn ngữ truy vấn Bazel hoạt động trên biểu đồ phần phụ thuộc của bản dựng, đây là biểu đồ được xác định ngầm bởi tất cả các nội dung khai báo quy tắc trong mọi tệp BUILD. Điều quan trọng là bạn cần hiểu rằng biểu đồ này có phần trừu tượng và không tạo thành nội dung mô tả đầy đủ về cách thực hiện tất cả các bước của bản dựng. Để tạo bản dựng, bạn cũng phải có cấu hình; xem phần cấu hình trong Hướng dẫn người dùng để biết thêm chi tiết.

Kết quả đánh giá một biểu thức trong ngôn ngữ truy vấn Bazel là đúng cho mọi cấu hình, tức là biểu thức này có thể là một phép ước tính quá mức vừa phải và không chính xác. Nếu bạn sử dụng công cụ truy vấn để tính toán tập hợp tất cả các tệp nguồn cần thiết trong quá trình tạo bản dựng, công cụ truy vấn có thể báo cáo nhiều hơn những gì thực sự cần thiết vì công cụ truy vấn sẽ bao gồm tất cả các tệp cần thiết để hỗ trợ dịch thông báo, mặc dù bạn không có ý định sử dụng tính năng đó trong bản dựng.

Về việc lưu giữ thứ tự trên biểu đồ

Các thao tác sẽ giữ nguyên mọi giới hạn về thứ tự kế thừa từ các biểu thức phụ. Bạn có thể coi đây là "định luật bảo toàn trật tự một phần". Hãy xem xét một ví dụ: nếu bạn đưa ra một truy vấn để xác định trạng thái đóng bắc cầu của các phần phụ thuộc của một mục tiêu cụ thể, thì tập hợp thu được sẽ được sắp xếp theo biểu đồ phần phụ thuộc. Nếu bạn lọc để chỉ bao gồm các mục tiêu thuộc loại file, thì quan hệ thứ tự một phần bắc cầu tương tự sẽ được áp dụng cho mọi cặp mục tiêu trong tập hợp con thu được – mặc dù không có cặp mục tiêu nào trong số này thực sự được kết nối trực tiếp trong biểu đồ ban đầu. (Không có cạnh của tệp-tệp trong biểu đồ phần phụ thuộc của bản dựng).

Tuy nhiên, mặc dù tất cả các toán tử đều giữ nguyên thứ tự, nhưng một số toán tử, chẳng hạn như thao tác đặt không đưa ra bất kỳ quy tắc ràng buộc nào về thứ tự của riêng các toán tử đó. Hãy xem xét biểu thức này:

deps(x) union y

Thứ tự của tập hợp kết quả cuối cùng được đảm bảo để duy trì mọi giới hạn theo thứ tự của các biểu thức phụ, cụ thể là tất cả các phần phụ thuộc bắc cầu của x được sắp xếp đúng cách và tôn trọng lẫn nhau. Tuy nhiên, truy vấn này không đảm bảo gì về thứ tự của các mục tiêu trong y cũng như thứ tự của các mục tiêu trong deps(x) so với các mục tiêu trong y (ngoại trừ các mục tiêu trong y cũng xảy ra trong deps(x)).

Các toán tử giới thiệu các quy tắc ràng buộc theo thứ tự bao gồm: allpaths, deps, rdeps, somepath và các ký tự đại diện của mẫu mục tiêu package:*, dir/..., v.v.

Cụm từ tìm kiếm về Sky

Truy vấn Sky là một chế độ truy vấn hoạt động trong một phạm vi vũ trụ được chỉ định.

Hàm đặc biệt chỉ có trong SkyQuery

Chế độ Sky Query có các hàm truy vấn bổ sung allrdepsrbuildfiles. Các hàm này hoạt động trên toàn bộ phạm vi vũ trụ (đó là lý do chúng không phù hợp với Truy vấn thông thường).

Chỉ định phạm vi vũ trụ

Chế độ Sky Query được kích hoạt bằng cách truyền 2 cờ sau: (--universe_scope hoặc --infer_universe_scope) và --order_output=no. --universe_scope=<target_pattern1>,...,<target_patternN> yêu cầu truy vấn tải trước việc đóng bắc cầu của mẫu mục tiêu do các mẫu mục tiêu chỉ định. Các mẫu mục tiêu này có thể vừa có tính cộng thêm vừa có tính trừ. Sau đó, tất cả các truy vấn sẽ được đánh giá trong "phạm vi" này. Cụ thể, các toán tử allrdepsrbuildfiles chỉ trả về kết quả từ phạm vi này. --infer_universe_scope yêu cầu Bazel suy ra một giá trị cho --universe_scope thông qua biểu thức truy vấn. Giá trị được dự đoán này là danh sách các mẫu mục tiêu duy nhất trong biểu thức truy vấn, nhưng đây có thể không phải là điều bạn muốn. Ví dụ:

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

Danh sách các mẫu mục tiêu duy nhất trong biểu thức truy vấn này là ["//my:target"], vì vậy, Bazel xử lý trường hợp này giống như lệnh gọi:

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

Nhưng kết quả của truy vấn đó với --universe_scope chỉ là //my:target; không có phần phụ thuộc ngược nào của //my:target có trong vũ trụ, bằng cách xây dựng! Mặt khác, hãy cân nhắc:

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

Đây là lệnh gọi truy vấn có ý nghĩa đang cố gắng tính toán mục tiêu kiểm thử trong quá trình mở rộng tests của các mục tiêu trong một số thư mục phụ thuộc bắc cầu vào các mục tiêu có định nghĩa sử dụng một tệp .bzl nhất định. Ở đây, --infer_universe_scope rất thuận tiện, đặc biệt trong trường hợp lựa chọn --universe_scope yêu cầu bạn phải tự phân tích cú pháp biểu thức truy vấn.

Vì vậy, đối với biểu thức truy vấn sử dụng toán tử ở phạm vi toàn cầu như allrdepsrbuildfiles, hãy nhớ chỉ sử dụng --infer_universe_scope nếu hành vi của biểu thức đó là điều bạn muốn.

Sky Query có một số ưu và nhược điểm so với truy vấn mặc định. Nhược điểm chính là không thể sắp xếp đầu ra theo thứ tự biểu đồ, do đó một số định dạng đầu ra bị cấm. Ưu điểm của phương thức này là cung cấp 2 toán tử (allrdepsrbuildfiles) không có trong truy vấn mặc định. Ngoài ra, Sky Query thực hiện công việc của nó bằng cách xem xét biểu đồ Skyframe thay vì tạo một biểu đồ mới, đây là cách triển khai mặc định. Do đó, có một số trường hợp, tính năng này nhanh hơn và sử dụng ít bộ nhớ hơn.

Biểu thức: Cú pháp và ngữ nghĩa của ngữ pháp

Đây là ngữ pháp của ngôn ngữ truy vấn Bazel, được thể hiện bằng ký hiệu 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 ... ')'

Các phần sau đây mô tả theo thứ tự việc tạo ra ngữ pháp này.

Mẫu mục tiêu

expr ::= word

Về cú pháp, mẫu mục tiêu chỉ là một từ. Đây được hiểu là một tập hợp mục tiêu (không theo thứ tự). Mẫu mục tiêu đơn giản nhất là nhãn, giúp xác định một mục tiêu (tệp hoặc quy tắc). Ví dụ: mẫu mục tiêu //foo:bar đánh giá thành một tập hợp chứa một phần tử (mục tiêu) quy tắc bar.

Các mẫu mục tiêu khái quát hoá nhãn để bao gồm cả ký tự đại diện thay cho các gói và mục tiêu. Ví dụ: foo/...:all (hoặc chỉ foo/...) là một mẫu mục tiêu đánh giá cho một tập hợp chứa tất cả quy tắc trong mọi gói được đệ quy bên dưới thư mục foo; bar/baz:all là một mẫu mục tiêu đánh giá cho một tập hợp chứa tất cả các quy tắc trong gói bar/baz, nhưng không phải các gói con.

Tương tự, foo/...:* là một mẫu mục tiêu đánh giá cho một tập hợp chứa tất cả các mục tiêu (quy tắc tệp) trong mỗi gói theo quy tắc đệ quy trong thư mục foo; bar/baz:* đánh giá là một tập hợp chứa tất cả các mục tiêu trong gói bar/baz, chứ không phải các gói con.

Vì ký tự đại diện :* khớp với các tệp cũng như quy tắc, nên ký tự đại diện này thường hữu ích hơn :all đối với truy vấn. Ngược lại, ký tự đại diện :all (ngầm ẩn trong các mẫu mục tiêu như foo/...) thường hữu ích hơn cho các bản dựng.

Mẫu mục tiêu bazel query hoạt động giống như mục tiêu bản dựng bazel build. Để biết thêm chi tiết, hãy xem Mẫu mục tiêu hoặc nhập bazel help target-syntax.

Các mẫu mục tiêu có thể đánh giá cho tập hợp singleton (trong trường hợp là một nhãn), cho một tập hợp chứa nhiều phần tử (như trong trường hợp foo/..., có hàng nghìn phần tử) hoặc cho tập hợp trống, nếu mẫu mục tiêu không khớp với mục tiêu nào.

Tất cả các nút trong kết quả của biểu thức mẫu mục tiêu đều được sắp xếp đúng cách so với nhau theo mối quan hệ phần phụ thuộc. Vì vậy, kết quả của foo:* không chỉ là tập hợp các mục tiêu trong gói foo, mà còn là biểu đồ theo các mục tiêu đó. (Chúng tôi không đảm bảo thứ tự tương đối của các nút kết quả so với các nút khác.) Để biết thêm thông tin chi tiết, hãy xem phần thứ tự trong biểu đồ.

Biến

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

Ngôn ngữ truy vấn Bazel cho phép định nghĩa và tham chiếu đến các biến. Kết quả đánh giá biểu thức let giống như kết quả của expr2, với tất cả các lần xuất hiện tự do của biến name được thay thế bằng giá trị của expr1.

Ví dụ: let v = foo/... in allpaths($v, //common) intersect $v tương đương với allpaths(foo/...,//common) intersect foo/....

Lỗi nếu xuất hiện một tham chiếu biến name không phải trong biểu thức let name = ... đính kèm. Nói cách khác, biểu thức truy vấn cấp cao nhất không được chứa biến miễn phí.

Trong các cấu trúc ngữ pháp nêu trên, name giống như từ, nhưng có thêm một quy tắc ràng buộc bổ sung rằng đây là giá trị nhận dạng hợp pháp trong ngôn ngữ lập trình C. Các tham chiếu đến biến phải được thêm vào trước ký tự "$".

Mỗi biểu thức let chỉ xác định một biến, nhưng bạn có thể lồng các biến đó.

Cả mẫu mục tiêu và tham chiếu biến chỉ bao gồm một mã thông báo duy nhất, một từ, tạo ra sự không rõ ràng về cú pháp. Tuy nhiên, không có sự không rõ ràng về ngữ nghĩa, bởi vì tập hợp con các từ là tên biến hợp pháp được tách biệt với tập con các từ là mẫu mục tiêu hợp pháp.

Về mặt kỹ thuật, biểu thức let không làm tăng tính biểu đạt của ngôn ngữ truy vấn: mọi truy vấn có thể diễn đạt bằng ngôn ngữ này cũng có thể được biểu thị mà không cần ngôn ngữ đó. Tuy nhiên, chúng giúp cải thiện mức độ súc tích của nhiều truy vấn và cũng có thể giúp đánh giá truy vấn một cách hiệu quả hơn.

Biểu thức trong ngoặc đơn

expr ::= (expr)

Dấu ngoặc đơn liên kết các biểu thức phụ để buộc sắp xếp thứ tự đánh giá. Biểu thức trong ngoặc đơn đánh giá giá trị của đối số.

Phép toán tập đại số: giao điểm, hợp số, hiệu tập hợp

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

Ba toán tử này tính toán các phép toán thông thường trên tập hợp đối số. Mỗi toán tử có hai dạng, dạng danh nghĩa (ví dụ: intersect) và dạng tượng trưng (chẳng hạn như ^). Cả hai dạng đều tương đương nhau; dạng tượng trưng thì nhanh hơn. (Để cho rõ ràng, phần còn lại của trang này sử dụng các hình thức danh nghĩa.)

Ví dụ:

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

đánh giá tập hợp mục tiêu khớp với foo/... chứ không khớp với foo/bar/....

Bạn có thể viết cùng một truy vấn dưới dạng:

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

Toán tử intersect (^) và union (+) mang tính giao hoán (đối xứng); except (-) là bất đối xứng. Trình phân tích cú pháp coi cả 3 toán tử là kết hợp trái và có mức độ ưu tiên như nhau, vì vậy, bạn nên dùng dấu ngoặc đơn. Ví dụ: 2 biểu thức đầu tiên trong số các biểu thức này tương đương nhau, nhưng biểu thức thứ ba thì không:

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

Đọc mục tiêu từ nguồn bên ngoài: đã đặt

expr ::= set(word *)

Toán tử set(a b c ...) tính toán tập hợp của một tập hợp gồm từ 0 mẫu mục tiêu trở lên, được phân tách bằng khoảng trắng (không có dấu phẩy).

Cùng với tính năng $(...) của Bourne shell, set() cung cấp một phương thức để lưu kết quả của một truy vấn trong tệp văn bản thông thường, chỉnh sửa tệp văn bản đó bằng các chương trình khác (chẳng hạn như các công cụ shell UNIX tiêu chuẩn), sau đó đưa lại kết quả vào công cụ truy vấn dưới dạng giá trị để xử lý thêm. Ví dụ:

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

Trong ví dụ tiếp theo,kind(cc_library, deps(//some_dir/foo:main, 5)) được tính bằng cách lọc các giá trị maxrank thông qua chương trình awk.

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

Trong những ví dụ này, $(<foo) là viết tắt của $(cat foo), nhưng bạn cũng có thể sử dụng các lệnh shell khác ngoài cat, chẳng hạn như lệnh awk trước đó.

Hàm

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

Ngôn ngữ truy vấn xác định một số hàm. Tên của hàm xác định số lượng và loại đối số mà hàm này yêu cầu. Có các hàm sau:

Đóng bắc cầu các phần phụ thuộc: phần phụ thuộc

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

Toán tử deps(x) đánh giá biểu đồ hình thành do quá trình đóng bắc cầu các phần phụ thuộc của tập đối số x. Ví dụ: giá trị của deps(//foo) là biểu đồ phần phụ thuộc bắt nguồn từ nút duy nhất foo, bao gồm tất cả các phần phụ thuộc của nút đó. Giá trị của deps(foo/...) là các biểu đồ phần phụ thuộc có gốc là tất cả các quy tắc trong mọi gói trong thư mục foo. Trong ngữ cảnh này, "phần phụ thuộc" chỉ có nghĩa là các mục tiêu tệp và quy tắc. Do đó, các tệp BUILD và Starlark cần thiết để tạo các mục tiêu này không được đưa vào đây. Để làm được việc đó, bạn nên sử dụng toán tử buildfiles.

Biểu đồ kết quả được sắp xếp theo mối quan hệ phần phụ thuộc. Để biết thêm thông tin chi tiết, hãy xem phần về thứ tự biểu đồ.

Toán tử deps chấp nhận một đối số thứ hai không bắt buộc. Đây là một số nguyên xác định giới hạn trên về mức độ tìm kiếm. Vì vậy, deps(foo:*, 0) sẽ trả về tất cả mục tiêu trong gói foo, trong khi deps(foo:*, 1) bao gồm thêm các điều kiện tiên quyết trực tiếp của bất kỳ mục tiêu nào trong gói foo, và deps(foo:*, 2) bao gồm thêm các nút có thể truy cập trực tiếp từ các nút trong deps(foo:*, 1), v.v. (Những con số này tương ứng với thứ hạng được hiển thị trong định dạng đầu ra minrank.) Nếu tham số depth bị bỏ qua, lượt tìm kiếm sẽ không bị giới hạn: sẽ tính toán việc đóng bắc cầu phản xạ của các điều kiện tiên quyết.

Đóng bắc cầu phần phụ thuộc ngược: rdeps

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

Toán tử rdeps(u, x) đánh giá các phần phụ thuộc đảo ngược của đối số đã đặt x trong trường hợp đóng bắc cầu của tập hợp vũ trụ u.

Biểu đồ kết quả được sắp xếp theo mối quan hệ phần phụ thuộc. Hãy xem phần về thứ tự trong biểu đồ để biết thêm thông tin chi tiết.

Toán tử rdeps chấp nhận một đối số thứ ba không bắt buộc. Đây là một số nguyên xác định giới hạn trên về mức độ tìm kiếm. Biểu đồ thu được chỉ bao gồm các nút nằm trong một khoảng cách có độ sâu đã chỉ định tính từ bất kỳ nút nào trong tập hợp đối số. Vì vậy, rdeps(//foo, //common, 1) sẽ đánh giá tất cả các nút trong đóng bắc cầu của //foo phụ thuộc trực tiếp vào //common. (Các số này tương ứng với thứ hạng được hiển thị trong định dạng đầu ra minrank.) Nếu tham số depth bị bỏ qua, hoạt động tìm kiếm sẽ không bị giới hạn.

Đóng bắc cầu tất cả các phần phụ thuộc ngược: allrdeps

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

Toán tử allrdeps hoạt động giống như toán tử rdeps, ngoại trừ việc "tập hợp vũ trụ" là bất kỳ cờ --universe_scope nào được đánh giá, thay vì được chỉ định riêng. Do đó, nếu --universe_scope=//foo/... được truyền, thì allrdeps(//bar) sẽ tương đương với rdeps(//foo/..., //bar).

Phần phụ thuộc đảo ngược trực tiếp trong cùng một gói: same_pkg_direct_rdeps

expr ::= same_pkg_direct_rdeps(expr)

Toán tử same_pkg_direct_rdeps(x) đánh giá tập hợp đầy đủ các mục tiêu nằm trong cùng gói với một mục tiêu trong tập hợp đối số và phụ thuộc trực tiếp vào mục tiêu đó.

Xử lý gói của mục tiêu: đồng cấp

expr ::= siblings(expr)

Toán tử siblings(x) đánh giá tập hợp đầy đủ các mục tiêu nằm trong cùng một gói với một mục tiêu trong tập hợp đối số.

Lựa chọn tuỳ ý: một số

expr ::= some(expr)
       | some(expr, count )

Toán tử some(x, k) chọn tối đa k mục tiêu tuỳ ý trong tập hợp đối số x và đánh giá tập hợp chỉ chứa các mục tiêu đó. Tham số k là không bắt buộc; nếu thiếu, kết quả sẽ là tập hợp singleton chỉ chứa một mục tiêu được chọn tuỳ ý. Nếu kích thước của tập hợp đối số x nhỏ hơn k, thì toàn bộ đối số được đặt x sẽ được trả về.

Ví dụ: biểu thức some(//foo:main union //bar:baz) đánh giá cho một nhóm singleton chứa //foo:main hoặc //bar:baz, mặc dù biểu thức nào không được xác định. Biểu thức some(//foo:main union //bar:baz, 2) hoặc some(//foo:main union //bar:baz, 3) trả về cả //foo:main//bar:baz.

Nếu đối số là một singleton, thì some sẽ tính toán hàm nhận dạng: some(//foo:main) tương đương với //foo:main.

Đây là một lỗi nếu bộ đối số được chỉ định bị trống, như trong biểu thức some(//foo:main intersect //bar:baz).

Toán tử đường dẫn: somepath, allpath

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

Toán tử somepath(S, E)allpaths(S, E) tính toán đường dẫn giữa hai nhóm mục tiêu. Cả hai truy vấn đều chấp nhận hai đối số, một tập hợp S điểm bắt đầu và một tập hợp E điểm kết thúc. somepath trả về biểu đồ của các nút trên đường dẫn tuỳ ý một số đường dẫn từ một mục tiêu trong S đến một mục tiêu trong E; allpaths trả về biểu đồ các nút trên tất cả các đường dẫn từ một mục tiêu bất kỳ trong S đến một mục tiêu bất kỳ trong E.

Các biểu đồ thu được được sắp xếp theo mối quan hệ phụ thuộc. Xem phần về thứ tự biểu đồ để biết thêm chi tiết.

Lối đi nào đó
somepath(S1 + S2, E), có thể có một kết quả.
Lối đi nào đó
somepath(S1 + S2, E), có thể có một kết quả khác.
Tất cả đường dẫn
allpaths(S1 + S2, E)

Lọc loại mục tiêu: loại

expr ::= kind(word, expr)

Toán tử kind(pattern, input) áp dụng bộ lọc cho một tập hợp các mục tiêu và loại bỏ các mục tiêu không thuộc loại dự kiến. Tham số pattern chỉ định loại mục tiêu cần so khớp.

Ví dụ: các loại cho 4 mục tiêu được xác định bằng tệp BUILD (đối với gói p) hiển thị bên dưới được minh hoạ trong bảng:

Mục tiêu Loại
        genrule(
            name = "a",
            srcs = ["a.in"],
            outs = ["a.out"],
            cmd = "...",
        )
      
//p:a quy tắc giá trị
//p:a.in tệp nguồn
//p:a.out tệp đã tạo
//p:BUILD tệp nguồn

Do đó, kind("cc_.* rule", foo/...) đánh giá tập hợp tất cả các mục tiêu quy tắc cc_library, cc_binary, v.v. đánh giá tới tập hợp tất cả tệp nguồn trong quá trình đóng bắc cầu các phần phụ thuộc của mục tiêu //foo.fookind("source file", deps(//foo))

Thường thì bạn bắt buộc phải đặt dấu ngoặc kép của đối số pattern, vì nếu không có dấu ngoặc kép, nhiều biểu thức chính quy, chẳng hạn như source file.*_test, không được trình phân tích cú pháp xem là các từ.

Khi so khớp cho package group, các mục tiêu kết thúc bằng :all có thể không mang lại kết quả nào. Thay vào đó, hãy sử dụng :all-targets.

Lọc tên mục tiêu: bộ lọc

expr ::= filter(word, expr)

Toán tử filter(pattern, input) áp dụng bộ lọc cho một tập hợp các mục tiêu và loại bỏ các mục tiêu có nhãn (ở dạng tuyệt đối) không khớp với mẫu; toán tử này đánh giá một tập hợp con dữ liệu đầu vào.

Đối số đầu tiên, pattern là một từ chứa biểu thức chính quy thay vì tên mục tiêu. Biểu thức filter đánh giá tập hợp chứa tất cả các mục tiêu x sao cho x là một thành phần của tập hợp input và nhãn (ở dạng tuyệt đối, chẳng hạn như //foo:bar) của x chứa kết quả khớp (không liên kết) với biểu thức chính quy pattern. Vì tất cả tên mục tiêu đều bắt đầu bằng //, nên bạn có thể dùng tên này để thay thế cho biểu thức liên kết chính quy ^.

Toán tử này thường cung cấp giải pháp thay thế nhanh và mạnh mẽ hơn nhiều cho toán tử intersect. Ví dụ: để xem tất cả các phần phụ thuộc bar của mục tiêu //foo:foo, bạn có thể đánh giá

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

Tuy nhiên, câu lệnh này sẽ yêu cầu phân tích cú pháp tất cả tệp BUILD trong cây bar. Điều này sẽ chậm và dễ xảy ra lỗi trong các tệp BUILD không liên quan. Phương án thay thế sẽ là:

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

trước tiên sẽ tính toán tập hợp các phần phụ thuộc //foo, sau đó sẽ chỉ lọc các mục tiêu khớp với mẫu đã cung cấp – nói cách khác là những mục tiêu có tên chứa //bar dưới dạng chuỗi con.

Một cách sử dụng phổ biến khác của toán tử filter(pattern, expr) là lọc các tệp cụ thể theo tên hoặc tiện ích. Ví dụ:

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

sẽ cung cấp danh sách tất cả các tệp .cc được dùng để tạo //foo.

Lọc thuộc tính quy tắc: attr

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

Toán tử attr(name, pattern, input) áp dụng bộ lọc cho một tập hợp các mục tiêu và loại bỏ các mục tiêu không phải quy tắc, các mục tiêu quy tắc không có thuộc tính name được xác định hoặc các mục tiêu quy tắc trong đó giá trị thuộc tính không khớp với biểu thức chính quy pattern đã cung cấp; nó đánh giá một tập hợp con dữ liệu đầu vào.

Đối số đầu tiên, name là tên của thuộc tính quy tắc cần được so khớp với mẫu biểu thức chính quy đã cung cấp. Đối số thứ hai, pattern là một biểu thức chính quy trên các giá trị thuộc tính. Một biểu thức attr đánh giá tập hợp chứa tất cả các mục tiêu x sao cho x là một thành phần của tập hợp input, là một quy tắc có thuộc tính được xác định name và giá trị thuộc tính chứa kết quả trùng khớp (chưa liên kết) cho biểu thức chính quy pattern. Nếu name là một thuộc tính không bắt buộc và quy tắc không chỉ định rõ ràng thì giá trị thuộc tính mặc định sẽ được sử dụng để so sánh. Ví dụ:

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

sẽ chọn mọi phần phụ thuộc //foo được phép có thuộc tính được chia sẻ liên kết (chẳng hạn như quy tắc cc_binary) và đặt thuộc tính này một cách rõ ràng thành 0 hoặc không đặt giá trị mặc định nhưng giá trị mặc định là 0 (chẳng hạn như đối với các quy tắc cc_binary).

Các thuộc tính loại danh sách (chẳng hạn như srcs, data, v.v.) được chuyển đổi thành các chuỗi ở dạng [value<sub>1</sub>, ..., value<sub>n</sub>], bắt đầu bằng dấu ngoặc [, kết thúc bằng dấu ngoặc ] và sử dụng "," (dấu phẩy, dấu cách) để phân cách nhiều giá trị. Nhãn được chuyển đổi thành chuỗi bằng cách sử dụng nhãn ở dạng tuyệt đối. Ví dụ: một thuộc tính deps=[":foo", "//otherpkg:bar", "wiz"] sẽ được chuyển đổi thành chuỗi [//thispkg:foo, //otherpkg:bar, //thispkg:wiz]. Các dấu ngoặc vuông luôn có sẵn, do đó danh sách trống sẽ sử dụng giá trị chuỗi [] để so khớp. Ví dụ:

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

sẽ chọn tất cả quy tắc trong số các phần phụ thuộc //foo có thuộc tính srcs trống, trong khi

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

sẽ chọn tất cả quy tắc trong số các phần phụ thuộc //foo chỉ định ít nhất một giá trị trong thuộc tính data (mỗi nhãn có ít nhất 3 ký tự do //:).

Để chọn tất cả quy tắc trong số các phần phụ thuộc //foo có một value cụ thể trong thuộc tính loại danh sách, hãy sử dụng

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

Cách này hiệu quả vì ký tự trước value sẽ là [ hoặc một dấu cách và ký tự sau value sẽ là dấu phẩy hoặc ].

Lọc chế độ hiển thị quy tắc: hiển thị

expr ::= visible(expr, expr)

Toán tử visible(predicate, input) áp dụng bộ lọc cho một tập hợp các mục tiêu và loại bỏ các mục tiêu mà không có chế độ hiển thị bắt buộc.

Đối số đầu tiên, predicate, là một tập hợp các mục tiêu mà mọi mục tiêu trong đầu ra phải được hiển thị. Biểu thức visible đánh giá tập hợp chứa tất cả các mục tiêu x sao cho x là một thành phần của tập hợp input và đối với tất cả mục tiêu y trong predicate x sẽ hiển thị cho y. Ví dụ:

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

sẽ chọn tất cả mục tiêu trong gói //bar//foo có thể dựa vào mà không vi phạm các quy định hạn chế về chế độ hiển thị.

Đánh giá các thuộc tính quy tắc của nhãn loại: nhãn

expr ::= labels(word, expr)

Toán tử labels(attr_name, inputs) trả về tập hợp mục tiêu được chỉ định trong thuộc tính attr_name thuộc loại "label" hoặc "danh sách nhãn" trong một số quy tắc trong tập hợp inputs.

Ví dụ: labels(srcs, //foo) trả về tập hợp các mục tiêu xuất hiện trong thuộc tính srcs của quy tắc //foo. Nếu có nhiều quy tắc với các thuộc tính srcs trong tập hợp inputs, thì hệ thống sẽ trả về hợp nhất srcs của các quy tắc đó.

Mở rộng và lọc test_suites: thử nghiệm

expr ::= tests(expr)

Toán tử tests(x) trả về tập hợp tất cả các quy tắc kiểm thử trong tập hợp x, mở rộng mọi quy tắc test_suite thành tập hợp các quy tắc kiểm thử riêng lẻ mà các quy tắc đó tham chiếu đến và áp dụng cơ chế lọc theo tagsize.

Theo mặc định, việc đánh giá truy vấn sẽ bỏ qua mọi mục tiêu không phải mục tiêu kiểm thử trong mọi quy tắc test_suite. Bạn có thể thay đổi tuỳ chọn này thành các lỗi có tuỳ chọn --strict_test_suite.

Ví dụ: truy vấn kind(test, foo:*) liệt kê tất cả các quy tắc *_testtest_suite trong gói foo. Tất cả kết quả đều là thành phần (theo định nghĩa) của gói foo. Ngược lại, truy vấn tests(foo:*) sẽ trả về tất cả các bài kiểm thử riêng lẻ sẽ được bazel test foo:* thực thi: có thể bao gồm các bài kiểm thử thuộc các gói khác được tham chiếu trực tiếp hoặc gián tiếp thông qua quy tắc test_suite.

Tệp định nghĩa gói: buildfile

expr ::= buildfiles(expr)

Toán tử buildfiles(x) trả về tập hợp các tệp xác định gói của từng mục tiêu trong tập hợp x; nói cách khác, đối với mỗi gói, tệp BUILD của gói đó cùng với mọi tệp .bzl mà nó tham chiếu thông qua load. Xin lưu ý rằng thao tác này cũng trả về các tệp BUILD của các gói chứa các tệp load này.

Toán tử này thường được dùng khi xác định những tệp hoặc gói cần thiết để tạo một mục tiêu cụ thể, thường kết hợp với tuỳ chọn --output package ở bên dưới). Ví dụ:

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

trả về tập hợp tất cả các gói mà //foo phụ thuộc bắc cầu.

Tệp định nghĩa gói: rbuildfiles

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

Toán tử rbuildfiles sẽ lấy một danh sách các mảnh đường dẫn được phân tách bằng dấu phẩy và trả về tập hợp các tệp BUILD phụ thuộc bắc cầu vào các mảnh đường dẫn này. Ví dụ: nếu //foo là một gói, thì rbuildfiles(foo/BUILD) sẽ trả về mục tiêu //foo:BUILD. Nếu tệp foo/BUILDload('//bar:file.bzl'..., thì rbuildfiles(bar/file.bzl) sẽ trả về mục tiêu //foo:BUILD, cũng như mục tiêu cho mọi tệp BUILD khác tải //bar:file.bzl

Phạm vi của toán tử rbuildfiles là phạm vi được chỉ định bởi cờ --universe_scope. Các tệp không tương ứng trực tiếp với tệp BUILD và tệp .bzl sẽ không ảnh hưởng đến kết quả. Ví dụ: các tệp nguồn (như foo.cc) sẽ bị bỏ qua, ngay cả khi các tệp này được đề cập rõ ràng trong tệp BUILD. Tuy nhiên, các liên kết biểu tượng được tôn trọng, để nếu foo/BUILD là một đường liên kết tượng trưng đến bar/BUILD, thì rbuildfiles(bar/BUILD) sẽ đưa //foo:BUILD vào kết quả.

Về mặt đạo đức, toán tử rbuildfiles là nghịch đảo của toán tử buildfiles. Tuy nhiên, sự đảo ngược về mặt đạo đức này vẫn có một hướng mạnh mẽ hơn: đầu ra của rbuildfiles cũng giống như đầu vào của buildfiles; đầu ra trước sẽ chỉ chứa các mục tiêu tệp BUILD trong các gói và đầu ra sau có thể chứa các mục tiêu như vậy. Ở hướng khác, hoạt động trao đổi thông tin yếu hơn. Đầu ra của toán tử buildfiles là các mục tiêu tương ứng với tất cả các gói và các tệp .bzl tệp cần thiết cho một giá trị đầu vào nhất định. Tuy nhiên, dữ liệu đầu vào của toán tử rbuildfiles không phải là các mục tiêu đó mà là các mảnh đường dẫn tương ứng với các mục tiêu đó.

Tệp định nghĩa gói: loadfiles

expr ::= loadfiles(expr)

Toán tử loadfiles(x) trả về tập hợp các tệp Starlark cần thiết để tải các gói của từng mục tiêu trong tập x. Nói cách khác, đối với mỗi gói, hàm này sẽ trả về các tệp .bzl được tham chiếu từ các tệp BUILD.

Định dạng đầu ra

bazel query tạo một biểu đồ. Bạn chỉ định nội dung, định dạng và thứ tự mà theo đó bazel query sẽ hiển thị biểu đồ này bằng tuỳ chọn dòng lệnh --output.

Khi chạy bằng Sky Query, chỉ các định dạng đầu ra tương thích với đầu ra không theo thứ tự mới được cho phép. Cụ thể, các định dạng đầu ra graph, minrankmaxrank bị cấm.

Một số định dạng đầu ra chấp nhận các tuỳ chọn bổ sung. Tên của mỗi tuỳ chọn đầu ra được thêm tiền tố là định dạng đầu ra mà tuỳ chọn đó áp dụng. Vì vậy, --graph:factored chỉ áp dụng khi sử dụng --output=graph; chế độ này sẽ không có hiệu lực nếu sử dụng định dạng đầu ra khác với graph. Tương tự, --xml:line_numbers chỉ áp dụng khi --output=xml đang được sử dụng.

Theo thứ tự của kết quả

Mặc dù biểu thức truy vấn luôn tuân theo "quy tắc bảo tồn thứ tự trong biểu đồ", nhưng bạn có thể trình bày kết quả theo thứ tự phần phụ thuộc hoặc không theo thứ tự. Điều này không ảnh hưởng đến các mục tiêu trong tập hợp kết quả hay cách tính toán truy vấn. Thuộc tính này chỉ ảnh hưởng đến cách in kết quả vào stdout. Hơn nữa, các nút tương đương theo thứ tự phần phụ thuộc có thể được sắp xếp hoặc không được sắp xếp theo thứ tự bảng chữ cái. Bạn có thể dùng cờ --order_output để kiểm soát hành vi này. (Cờ --[no]order_results có một tập con chức năng của cờ --order_output và không được dùng nữa.)

Giá trị mặc định của cờ này là auto, in ra kết quả thứ tự từ điển. Tuy nhiên, khi bạn sử dụng somepath(a,b), kết quả sẽ được in theo thứ tự deps.

Khi cờ này là no--output là một trong các giá trị build, label, label_kind, location, package, proto hoặc xml, kết quả sẽ được in theo thứ tự tuỳ ý. Đây thường là cách nhanh nhất. Định dạng này không được hỗ trợ khi --output là một trong các graph, minrank hoặc maxrank: với các định dạng này, Bazel luôn in kết quả theo thứ tự hoặc thứ hạng phần phụ thuộc.

Khi cờ này là deps, Bazel sẽ in theo một thứ tự cấu trúc liên kết nào đó, tức là các phần phụ thuộc trước tiên. Tuy nhiên, các nút không được sắp xếp theo thứ tự phần phụ thuộc (vì không có đường dẫn từ một trong hai nút này đến nút khác) có thể được in theo bất kỳ thứ tự nào.

Khi cờ này là full, Bazel sẽ in các nút theo thứ tự xác định (tổng) hoàn toàn. Trước tiên, tất cả các nút được sắp xếp theo thứ tự bảng chữ cái. Sau đó, mỗi nút trong danh sách được dùng làm điểm bắt đầu của lượt tìm kiếm ưu tiên theo chiều sâu theo thứ tự sau, trong đó các cạnh đi đến các nút chưa truy cập sẽ được truyền tải theo thứ tự bảng chữ cái của các nút kế thừa. Cuối cùng, các nút được in theo thứ tự đảo ngược với thứ tự mà các nút đó được truy cập.

Việc in các nút theo thứ tự này có thể chậm hơn. Vì vậy, bạn chỉ nên sử dụng tính năng này khi thuật toán tất định đóng vai trò quan trọng.

In biểu mẫu nguồn của các mục tiêu như sẽ xuất hiện trong BUILD

--output build

Với tuỳ chọn này, nội dung của từng mục tiêu sẽ giống như được viết tay bằng ngôn ngữ XÂY DỰNG. Tất cả biến và lệnh gọi hàm (chẳng hạn như glob, macro) đều được mở rộng. Điều này rất hữu ích để xem tác động của các macro Starlark. Ngoài ra, mỗi quy tắc hiệu quả báo cáo một giá trị generator_name và/hoặc generator_function), đưa ra tên của macro được đánh giá để tạo ra quy tắc hiệu quả.

Mặc dù kết quả sử dụng cú pháp giống như tệp BUILD, nhưng không đảm bảo sẽ tạo ra tệp BUILD hợp lệ.

--output label

Với tuỳ chọn này, tập hợp tên (hoặc nhãn) của từng mục tiêu trong biểu đồ thu được sẽ được in, một nhãn trên mỗi dòng, theo thứ tự cấu trúc liên kết (trừ khi --noorder_results được chỉ định, hãy xem ghi chú về thứ tự của kết quả). (Thứ tự cấu trúc liên kết là thứ tự mà trong đó một nút biểu đồ xuất hiện sớm hơn tất cả các thứ tự kế thừa.) Tất nhiên, có nhiều thứ tự cấu trúc liên kết có thể có của một biểu đồ (thứ tự đảo ngược chỉ là một thứ tự); thứ tự được chọn không được chỉ định.

Khi in kết quả của truy vấn somepath, thứ tự in các nút là thứ tự của đường dẫn.

Lưu ý: trong một số trường hợp, có thể có hai mục tiêu riêng biệt có cùng nhãn; ví dụ: quy tắc sh_binary và tệp srcs duy nhất của quy tắc đó (ngầm ẩn) có thể được gọi là foo.sh. Nếu kết quả của một truy vấn chứa cả hai mục tiêu này thì dữ liệu đầu ra (ở định dạng label) sẽ hiển thị nội dung trùng lặp. Khi sử dụng định dạng label_kind (xem bên dưới), sự khác biệt sẽ trở nên rõ ràng: hai mục tiêu có cùng tên, nhưng một mục tiêu có loại sh_binary rule và loại còn lại là source file.

--output label_kind

Giống như label, định dạng đầu ra này in nhãn của từng mục tiêu trong biểu đồ kết quả, theo thứ tự cấu trúc liên kết, nhưng đứng trước nhãn là loại của mục tiêu.

--output minrank --output maxrank

Giống như label, định dạng đầu ra minrankmaxrank in nhãn của từng mục tiêu trong biểu đồ thu được, nhưng thay vì xuất hiện theo thứ tự cấu trúc liên kết, các định dạng này xuất hiện theo thứ tự xếp hạng, đứng sau số thứ hạng của chúng. Những trang này không bị ảnh hưởng bởi cờ --[no]order_results theo thứ tự kết quả (xem các ghi chú về thứ tự của kết quả).

Có 2 biến thể của định dạng này: minrank xếp hạng từng nút theo độ dài của đường dẫn ngắn nhất từ nút gốc đến nút đó. Nút "Gốc" (những nút không có cạnh đến) được xếp hạng 0, nút kế thừa xếp hạng 1, v.v. (Như thường lệ, các cạnh trỏ từ mục tiêu đến điều kiện tiên quyết: các mục tiêu mà nó phụ thuộc vào.)

maxrank xếp hạng từng nút theo độ dài của đường dẫn dài nhất từ nút gốc đến nút đó. Xin nhắc lại, "gốc" có thứ hạng 0, tất cả các nút khác có thứ hạng lớn hơn thứ hạng tối đa của tất cả các nút trước đó.

Tất cả các nút trong một chu kỳ được coi là có thứ hạng bằng nhau. (Hầu hết các biểu đồ đều tuần hoàn, nhưng chu kỳ chỉ xảy ra vì các tệp BUILD chứa chu kỳ lỗi.)

Các định dạng đầu ra này rất hữu ích cho việc khám phá độ sâu của biểu đồ. Nếu được dùng cho kết quả của một truy vấn deps(x), rdeps(x) hoặc allpaths, thì số thứ hạng sẽ bằng với độ dài của đường dẫn ngắn nhất (với minrank) hoặc dài nhất (với maxrank) từ x đến một nút trong thứ hạng đó. Bạn có thể sử dụng maxrank để xác định trình tự dài nhất gồm các bước tạo bản dựng cần thiết để tạo mục tiêu.

Ví dụ: biểu đồ ở bên trái cho ra kết quả ở bên phải khi --output minrank--output maxrank được chỉ định tương ứng.

Xếp hạng thấp hơn
      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

Giống như label_kind, tuỳ chọn này in ra, đối với mỗi mục tiêu trong kết quả, loại và nhãn của mục tiêu, nhưng có tiền tố là một chuỗi mô tả vị trí của mục tiêu đó, dưới dạng tên tệp và số dòng. Định dạng giống với kết quả của grep. Do đó, các công cụ có thể phân tích cú pháp lệnh sau (chẳng hạn như Emacs hoặc vi) cũng có thể sử dụng đầu ra truy vấn để bước qua một loạt kết quả khớp, cho phép sử dụng công cụ truy vấn Bazel dưới dạng một "grep cho các tệp BUILD" có nhận biết đồ thị phụ thuộc.

Thông tin vị trí sẽ khác nhau tuỳ theo loại mục tiêu (xem toán tử loại). Đối với các quy tắc, vị trí khai báo của quy tắc trong tệp BUILD sẽ được in. Đối với các tệp nguồn, vị trí của dòng 1 của tệp thực sẽ được in. Đối với tệp đã tạo, vị trí của quy tắc tạo ra tệp sẽ được in. (Công cụ truy vấn không có đủ thông tin để tìm vị trí thực tế của tệp được tạo và trong mọi trường hợp, tệp có thể không tồn tại nếu bản dựng chưa được thực hiện.)

--output package

Tuỳ chọn này in tên của tất cả các gói có chứa một số mục tiêu trong tập hợp kết quả. Tên được in theo thứ tự từ điển; không bao gồm các bản trùng lặp. Chính thức, đây là phép chiếu từ tập hợp nhãn (gói, mục tiêu) lên gói.

Các gói trong kho lưu trữ bên ngoài được định dạng là @repo//foo/bar, còn các gói trong kho lưu trữ chính có định dạng là foo/bar.

Cùng với truy vấn deps(...), bạn có thể sử dụng tuỳ chọn đầu ra này để tìm tập hợp các gói cần được thanh toán để xây dựng một tập hợp các mục tiêu nhất định.

Hiển thị biểu đồ của kết quả

--output graph

Tuỳ chọn này giúp in kết quả truy vấn dưới dạng biểu đồ định hướng ở định dạng AT&T GraphViz phổ biến. Thông thường, kết quả sẽ được lưu vào một tệp, chẳng hạn như .png hoặc .svg. (Nếu chương trình dot chưa được cài đặt trên máy trạm, bạn có thể cài đặt chương trình này bằng lệnh sudo apt-get install graphviz.) Hãy xem phần ví dụ dưới đây để biết lệnh gọi mẫu.

Định dạng đầu ra này đặc biệt hữu ích cho các truy vấn allpaths, deps hoặc rdeps, trong đó kết quả bao gồm một tập hợp các đường dẫn không thể dễ dàng hình dung được khi hiển thị ở dạng tuyến tính, chẳng hạn như với --output label.

Theo mặc định, biểu đồ hiển thị ở dạng thành phần. Điều này nghĩa là các nút tương đương về mặt cấu trúc liên kết được hợp nhất với nhau thành một nút duy nhất có nhiều nhãn. Điều này giúp biểu đồ gọn gàng và dễ đọc hơn vì biểu đồ kết quả điển hình chứa các mẫu có tính lặp lại cao. Ví dụ: một quy tắc java_library có thể phụ thuộc vào hàng trăm tệp nguồn Java được tạo bởi cùng một genrule; trong biểu đồ phân tích, tất cả những tệp này được biểu thị bằng một nút duy nhất. Bạn có thể tắt hành vi này bằng tuỳ chọn --nograph:factored.

--graph:node_limit n

Tuỳ chọn này chỉ định độ dài tối đa của chuỗi nhãn cho một nút biểu đồ trong đầu ra. Các nhãn dài hơn sẽ bị cắt bớt; -1 sẽ tắt tính năng cắt bớt. Do dạng thức cấu thành mà biểu đồ thường được in, nên các nhãn của nút có thể rất dài. GraphViz không thể xử lý các nhãn vượt quá 1024 ký tự, đây là giá trị mặc định của tùy chọn này. Tuỳ chọn này không có hiệu lực trừ phi bạn dùng --output=graph.

--[no]graph:factored

Theo mặc định, các biểu đồ hiển thị ở dạng tích luỹ, như đã giải thích ở trên. Khi --nograph:factored được chỉ định, biểu đồ sẽ được in mà không cần phân tích. Điều này giúp việc trực quan hoá bằng GraphViz trở nên đơn giản, nhưng định dạng đơn giản hơn có thể dễ dàng xử lý bằng các công cụ khác (chẳng hạn như grep). Tuỳ chọn này không có hiệu lực trừ phi bạn sử dụng --output=graph.

XML

--output xml

Tuỳ chọn này giúp in các mục tiêu kết quả ở dạng XML. Kết quả bắt đầu bằng tiêu đề XML, chẳng hạn như

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

rồi tiếp tục với phần tử XML cho từng mục tiêu trong biểu đồ kết quả, theo thứ tự tôpô (trừ khi kết quả không theo thứ tự được yêu cầu), sau đó kết thúc bằng một điểm kết thúc

</query>

Các mục nhập đơn giản được tạo cho các mục tiêu thuộc loại file:

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

Tuy nhiên, đối với quy tắc, tệp XML được cấu trúc và chứa định nghĩa của tất cả thuộc tính của quy tắc, bao gồm cả những thuộc tính có giá trị không được chỉ định rõ ràng trong tệp BUILD của quy tắc.

Ngoài ra, kết quả bao gồm các phần tử rule-inputrule-output để có thể tạo lại cấu trúc liên kết của biểu đồ phần phụ thuộc mà không cần biết rằng, ví dụ: các phần tử của thuộc tính srcs là các phần phụ thuộc chuyển tiếp (điều kiện tiên quyết) và nội dung của thuộc tính outs là các phần phụ thuộc ngược (đối tượng sử dụng).

Các phần tử rule-input cho phần phụ thuộc ngầm ẩn sẽ bị chặn nếu bạn chỉ định --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>

Mỗi phần tử XML cho một mục tiêu đều chứa thuộc tính name (có giá trị là nhãn của mục tiêu và thuộc tính location có giá trị là vị trí của mục tiêu như được in trong --output location).

--[no]xml:line_numbers

Theo mặc định, các vị trí xuất hiện trong tệp XML sẽ chứa số dòng. Khi bạn chỉ định --noxml:line_numbers, số dòng sẽ không được in.

--[no]xml:default_values

Theo mặc định, đầu ra XML không bao gồm thuộc tính quy tắc có giá trị là giá trị mặc định cho loại thuộc tính đó (ví dụ: nếu thuộc tính không được chỉ định trong tệp BUILD hoặc giá trị mặc định được cung cấp một cách rõ ràng). Tuỳ chọn này khiến các giá trị thuộc tính như vậy được đưa vào dữ liệu đầu ra XML.

Cụm từ thông dụng

Biểu thức chính quy bằng ngôn ngữ truy vấn sử dụng thư viện biểu thức chính quy Java để bạn có thể sử dụng cú pháp đầy đủ cho java.util.regex.Pattern.

Truy vấn bằng các kho lưu trữ bên ngoài

Nếu bản dựng phụ thuộc vào các quy tắc từ các kho lưu trữ bên ngoài (được xác định trong tệp WORKSPACE) thì kết quả truy vấn sẽ bao gồm các phần phụ thuộc này. Ví dụ: nếu //foo:bar phụ thuộc vào //external:some-lib//external:some-lib được liên kết với @other-repo//baz:lib, thì bazel query 'deps(//foo:bar)' sẽ liệt kê cả @other-repo//baz:lib//external:some-lib là phần phụ thuộc.

Bản thân kho lưu trữ bên ngoài không phải là phần phụ thuộc của bản dựng. Điều này nghĩa là trong ví dụ trên, //external:other-repo không phải là phần phụ thuộc. Bạn có thể truy vấn nó như một thành phần của gói //external, tuy nhiên, ví dụ:

  # 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