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

7.3 · 7.2 · 7.1 · 7.0 · 6.5

Trang này là tài liệu tham khảo cho Ngôn ngữ truy vấn Bazel được sử 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. Phương thức 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 truy vấn Bazel.

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

Ngoài query chạy trên biểu đồ mục tiêu giai đoạn tải sau, 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ệ giữa các hành động đó. aquery 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ế chạy và dữ liệu đầu vào, đầu ra và câu thần chú 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 khi 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 đó sẽ trả về mọi độ phân giải có thể có của 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 ban đầu này.

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

Ví dụ

Mọi người sử dụng bazel query như thế nào? Sau đây là một số 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ả các bài kiểm thử foo phụ thuộc vào thư viện C++ nào mà mục tiêu foo_bin không phụ thuộc?

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à các từ dành riêng của ngôn ngữ và mỗi từ khoá được mô tả bên dưới. Bộ từ khoá hoàn chỉnh là:

  • Từ, chẳng hạn như "foo/..." hoặc ".*test rule" hoặc "//bar/baz:all". Nếu một trình tự ký tự được "đưa vào dấu ngoặc kép" (bắt đầu và kết thúc bằng dấu ngoặc kép đơn ' hoặc bắt đầu và kết thúc bằng dấu ngoặc kép đôi "), 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 được trích dẫn là các chuỗi ký tự được lấy từ các ký tự chữ cái A-Za-z, chữ số 0-9 và các ký tự đặc biệt */@.-_:$~[] (dấu sao, dấu gạch chéo lên, dấu @, dấu chấm, dấu gạch nối, dấu gạch dưới, dấu hai chấm, dấu đô la, dấu ngã, dấu ngoặc vuông trái, dấu ngoặc vuông phải). Tuy nhiên, các từ không được trích dẫn 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 có thể bắt đầu bằng các ký tự đó.

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

    Bạn cần phải trích dẫn khi viết 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 việc trích dẫn này là ngoài mọi yêu cầu trích dẫn mà shell của bạn có thể yêu cầu, chẳng hạn như:

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

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

    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ỉ sử dụng một loại dấu ngoặc kép (tất cả dấu nháy đơn hoặc toàn bộ).

    Sau đây là ví dụ về ý nghĩa của 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ụ về ".*test rule" (không bình thường) cần có dấu ngoặc kép: ví dụ này bắt đầu bằng dấu chấm và chứa một dấu cách. Việc trích dẫn "cc_library" là không cần thiết nhưng không gây 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 ,. Bạn phải đặt dấu ngoặc kép cho các từ chứa dấu câu (ngoại trừ các trường hợp ngoại lệ nêu trên).

Các ký tự khoảng trắng bên ngoài từ được trích dẫn sẽ bị bỏ qua.

Các khái niệm về 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 đều đánh giá thành một tập hợp được sắp xếp một phần các mục tiêu, hoặc tương đương là một biểu đồ (DAG) của các mục tiêu. Đây là loại dữ liệu duy nhất.

Tập hợp và biểu đồ đề cập đến cùng một loại dữ liệu, nhưng nhấn mạnh các khía cạnh khác nhau của loại dữ liệu đó, ví dụ:

  • Đặt: Thứ tự một phần của các mục tiêu không thú vị.
  • Biểu đồ: Thứ tự một phần của các mục tiêu là rất quan trọng.

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 không tuần hoàn.

Các thuật toán mà ngôn ngữ truy vấn sử dụng được dùng trong đồ thị không chu trình, nhưng vẫn mạnh mẽ chống lại các chu trình. Thông tin chi tiết về cách xử lý chu kỳ không được chỉ định và không nên dựa vào.

Phần phụ thuộc ngầm ẩn

Ngoài các phần phụ thuộc bản dựng được xác định rõ ràng trong tệp BUILD, Bazel còn thêm các phần phụ thuộc ngầm ẩn vào quy tắc. Ví dụ: mọi quy tắc Java ngầm ẩn 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 thể ghi đè các phần phụ thuộc này trong tệp BUILD.

Theo mặc định, bazel query sẽ tính đến 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ác 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.

Tính hợp lệ

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. Biểu đồ này được ngầm xác định trong mọi nội dung khai báo quy tắc trong mọi tệp BUILD. Điều quan trọng là bạn phải hiểu rằng biểu đồ này có phần trừu tượng và không phải là nội dung mô tả đầy đủ về cách thực hiện tất cả các bước của một bản dựng. Để tạo bản dựng, bạn cũng cần có cấu hình; hãy xem phần cấu hình trong Hướng dẫn sử dụng để biết thêm chi tiết.

Kết quả của việc đánh giá một biểu thức trong ngôn ngữ truy vấn Bazel là đúng đối với mọi cấu hình, có nghĩa là đó có thể là kết quả gần đúng quá mức thận trọng 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, thì công cụ này có thể báo cáo nhiều hơn mức cần thiết, chẳng hạn như 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 duy trì thứ tự biểu đồ

Các toán tử giữ nguyên mọi quy tắc ràng buộc thứ tự kế thừa từ biểu thức con. Bạn có thể coi điều này là "quy luật bảo toàn thứ 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 tập hợp đó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 kết quả sẽ được sắp xếp theo biểu đồ phần phụ thuộc. Nếu bạn bộ lọc được đặt để chỉ bao gồm các mục tiêu thuộc loại file, thì mối quan hệ thứ tự một phần bắc cầu giống nhau sẽ giữ giữa mọi cặp mục tiêu trong tập hợp con thu được – mặc dù không có cặp 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 tệp-tệp nào 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 duy trì thứ tự, nhưng một số thao tác, chẳng hạn như các thao tác tập hợp lại không giới thiệu bất kỳ quy tắc ràng buộc thứ tự nào của riêng chúng. Hãy xem xét biểu thức sau:

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ì tất cả các điều kiện ràng buộc 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 chính xác và tương ứng với 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 có trong deps(x)).

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

Truy vấn bầu trời

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

Các hàm đặc biệt chỉ có trong SkyQuery

Chế độ Truy vấn bầu trời 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 tại sao chúng không có ý nghĩa đối với Truy vấn thông thường).

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

Chế độ Truy vấn trên bầu trời được kích hoạt bằng cách truyền hai 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 tính năng đóng kín bắc cầu của mẫu mục tiêu do các mẫu mục tiêu chỉ định, có thể là cả tính năng cộng và 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 từ biểu thức truy vấn. Giá trị suy luậ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à những gì 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ý vấn đề 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 trong vũ trụ, bằng cách tạo! 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à một lệnh gọi truy vấn có ý nghĩa đang cố gắng tính toán các mục tiêu kiểm thử trong phần 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. Tại đây, --infer_universe_scope rất thuận tiện, đặc biệt là trong trường hợp lựa chọn --universe_scope yêu cầu bạn 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ử trong phạm vi vũ trụ như allrdepsrbuildfiles, hãy nhớ chỉ sử dụng --infer_universe_scope nếu hành vi của toán tử đó là điều bạn muốn.

Truy vấn Sky có một số ưu điểm 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 nhất định bị cấm. Ưu điểm của truy vấn này là cung cấp hai toán tử (allrdepsrbuildfiles) không có trong truy vấn mặc định. Ngoài ra, Truy vấn Sky thực hiện công việc của mình bằng cách tự kiểm tra biểu đồ Skyframe, thay vì tạo một biểu đồ mới, đây là cách triển khai mặc định. Do đó, trong một số trường hợp, công cụ 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à cú pháp của ngôn ngữ truy vấn Bazel, được biểu thị 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ả lần lượt từng quy tắc sản xuất của cú pháp này.

Mẫu mục tiêu

expr ::= word

Về mặt cú pháp, mẫu mục tiêu chỉ là một từ. Giá trị này được hiểu là một tập hợp các 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 duy nhất (tệp hoặc quy tắc). Ví dụ: mẫu mục tiêu //foo:bar sẽ đá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.

Mẫu mục tiêu tổng quát hoá các nhãn để bao gồm ký tự đại diện trên 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á thành một tập hợp chứa tất cả quy tắc trong mọi gói theo đệ quy bên dưới thư mục foo; bar/baz:all là một mẫu mục tiêu đánh giá thành 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 của gói đó.

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

Vì ký tự đại diện :* khớp với các tệp cũng như quy tắc nên thường hữu ích hơn :all đối với các 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.

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

Các mẫu mục tiêu có thể đánh giá thành một tập singleton (trong trường hợp là nhãn), thành 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 thành tập rỗ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 được sắp xếp chính xác tương ứng 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 đồ của các mục tiêu đó. (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ự 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 với kết quả của expr2, trong đó 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/....

Một lần xuất hiện tham chiếu biến name khác với trong biểu thức let name = ... bao hàm là lỗi. Nói cách khác, biểu thức truy vấn cấp cao nhất không được có biến tự do.

Trong các sản phẩm ngữ pháp ở trên, name giống như word, nhưng có thêm điều kiện ràng buộc là phải là giá trị nhận dạng hợp lệ trong ngôn ngữ lập trình C. Bạn phải thêm ký tự "$" vào đầu tham chiếu đến biến.

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 đều 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, vì tập hợp con các từ là tên biến hợp pháp bị tách khỏi tập hợ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 cảm của ngôn ngữ truy vấn: mọi truy vấn có thể biểu thị bằng ngôn ngữ này cũng có thể được biểu thị mà không cần biểu thức let. Tuy nhiên, chúng giúp cải thiện tính súc tích của nhiều truy vấn và cũng có thể giúp đánh giá truy vấn hiệu quả hơn.

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

expr ::= (expr)

Dấu ngoặc đơn liên kết các biểu thức con để buộc một thứ tự đánh giá. Biểu thức trong dấu ngoặc đơn sẽ đánh giá giá trị của đối số.

Các phép toán trên tập hợp đại số: giao, hợp, 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 toán tử thông thường của tập hợp cho đối số của chúng. Mỗi toán tử có hai dạng, dạng danh nghĩa, chẳng hạn như intersect và dạng tượng trưng, chẳng hạn như ^. Cả hai dạng đều tương đương; dạng biểu tượng giúp nhập nhanh hơn. (Để rõ ràng, phần còn lại của trang này sử dụng các dạng danh từ.)

Ví dụ:

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

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

Bạn có thể viết cùng một truy vấn như sau:

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

Các phép toán intersect (^) và union (+) có tính giao hoán (đối xứng); except (-) có tính không đối xứng. Trình phân tích cú pháp coi cả ba toán tử là liên kết bên trái và có cùng mức độ ưu tiên, vì vậy, bạn có thể muốn sử dụng dấu ngoặc đơn. Ví dụ: hai biểu thức đầu tiên trong số 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ừ một nguồn bên ngoài: set

expr ::= set(word *)

Toán tử set(a b c ...) tính toán hợp của một tập hợp các mẫu mục tiêu không hoặc nhiều hơ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 một tệp văn bản thông thường, thao tác với 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 kết quả trở lại công cụ truy vấn dưới dạng một 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 toán bằng cách lọc các giá trị maxrank bằng 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 các 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 đó yêu cầu. Các hàm sau đây có sẵn:

Đóng vòng lặp bắc cầu của các phần phụ thuộc: deps

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

Toán tử deps(x) đánh giá thành biểu đồ được tạo bằng cách đóng bắc cầu các phần phụ thuộc của tập hợp đối số x. Ví dụ: giá trị của deps(//foo) là biểu đồ phần phụ thuộc đã bị can thiệp vào hệ thống tại 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ả quy tắc trong mọi gói bên dưới 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 quy tắc và tệp, do đó, các tệp BUILD và Starlark cần thiết để tạo các mục tiêu này sẽ không được đưa vào đây. Để làm được điều đó, bạn nên sử dụng toán tử buildfiles.

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

Toán tử deps chấp nhận đối số thứ hai không bắt buộc, là một số nguyên cố định chỉ định giới hạn trên về độ sâu của lượt tìm kiếm. Vì vậy, deps(foo:*, 0) trả về tất cả các mục tiêu trong gói foo, trong khi deps(foo:*, 1) bao gồm cả 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 foodeps(foo:*, 2) bao gồm cả các nút có thể truy cập trực tiếp từ các nút trong deps(foo:*, 1), v.v. (Các số này tương ứng với thứ hạng 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ị ràng buộc: hệ thống tính toán việc đóng bắc cầu phản xạ cho các điều kiện tiên quyết.

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

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

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

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

Toán tử rdeps chấp nhận đối số thứ ba không bắt buộc, là một số nguyên cố định chỉ định giới hạn trên về độ sâu của lượt tìm kiếm. Biểu đồ kết quả chỉ bao gồm các nút trong khoảng cách chiều sâu đã chỉ đị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 tập hợp đóng bắc cầu của //foo trực tiếp phụ thuộc vào //common. (Những số này tương ứng với thứ hạng hiển thị trong định dạng đầu ra minrank.) Nếu bạn bỏ qua tham số depth, thì quá trình tìm kiếm sẽ không bị ràng buộc.

Đóng vòng lặp bắc cầu của tất 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 "bộ 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) 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) sẽ đá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ố và mục tiêu phụ thuộc trực tiếp vào tập hợp đó.

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

expr ::= siblings(expr)

Toán tử siblings(x) đánh giá cho tập hợp đầy đủ các mục tiêu nằm trong cùng một gói với 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ỳ ý từ tập hợp đối số x và đánh giá thành một 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à một 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ộ tập hợp đối số x sẽ được trả về.

Ví dụ: biểu thức some(//foo:main union //bar:baz) đánh giá thành một tập hợp singleton chứa //foo:main hoặc //bar:baz, mặc dù tập hợp 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à lỗi nếu tập hợp đố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, allpaths

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 gồm các điểm bắt đầu và một tập hợp E gồm các điểm kết thúc. somepath trả về biểu đồ các nút trên một số đường dẫn tuỳ ý 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ả đường dẫn từ bất kỳ mục tiêu nào trong S đến bất kỳ mục tiêu nào trong E.

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

Đường dẫn nào đó
somepath(S1 + S2, E), 1 kết quả có thể có.
Somepath
somepath(S1 + S2, E) thân mến, có thể có một kết quả khác.
Allpaths
allpaths(S1 + S2, E)

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

expr ::= kind(word, expr)

Toán tử kind(pattern, input) áp dụng một bộ lọc cho một tập hợp các mục tiêu và loại bỏ những 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 kiểu cho 4 mục tiêu được xác định bởi tệp BUILD (cho gói p) hiển thị dưới đây đượ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 genrule
//p:a.in tệp nguồn
//p:a.out tệp được 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. bên dưới fookind("source file", deps(//foo)) đánh giá đối vớ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.

Bạn thường phải trích dẫn đối số pattern vì nếu không, nhiều biểu thức chính quy, chẳng hạn như source file.*_test, sẽ không được trình phân tích cú pháp coi là từ.

Khi so khớp với 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 một bộ lọc cho một tập hợp 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á thành một tập hợp con của 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 trên tên mục tiêu. Biểu thức filter sẽ đánh giá tập hợp chứa tất cả các mục tiêu x sao cho x là một 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 một kết quả trùng khớp (không neo) cho 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ể sử dụng tên này thay cho neo biểu thức chính quy ^.

Toán tử này thường cung cấp một giải pháp thay thế nhanh và mạnh mẽ hơn nhiều so với 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ả các tệp BUILD trong cây bar. Việc này sẽ chậm và dễ xảy ra lỗi trong các tệp BUILD không liên quan. Một phương án thay thế sẽ là:

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

bộ lọc này sẽ tính toán tập hợp các phần phụ thuộc //foo rồi sau đó 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à các 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 đuôi tệp. Ví dụ:

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

sẽ cung cấp danh sách tất cả tệp .cc 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 một bộ lọc cho một tập hợp mục tiêu và loại bỏ các mục tiêu không phải là quy tắc, mục tiêu quy tắc không xác định thuộc tính name hoặc mục tiêu quy tắc mà giá trị thuộc tính không khớp với biểu thức chính quy pattern đã cung cấp; toán tử này đánh giá thành một tập hợp con của 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 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. Biểu thức attr đánh giá thành tập hợp chứa tất 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 name được xác định và giá trị thuộc tính chứa một kết quả khớp (không 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 dùng để so sánh. Ví dụ:

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

sẽ chọn tất cả các phần phụ thuộc //foo được phép có thuộc tính sharelink (chẳng hạn như quy tắc cc_binary) và đặt thuộc tính này thành 0 một cách rõ ràng hoặc không đặt thuộc tính này nhưng giá trị mặc định là 0 (chẳng hạn như đối với 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 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 định nhiều giá trị. Nhãn được chuyển đổi thành chuỗi bằng cách sử dụng dạng tuyệt đối của nhãn. Ví dụ: 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 luôn hiển thị, vì vậy 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ả cá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ó độ dài ít nhất là 3 ký tự do //:).

Để chọn tất cả quy tắc trong số các phần phụ thuộc //foovalue 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 hoạt động vì ký tự trước value sẽ là [ hoặc 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 một bộ lọc cho một tập hợp mục tiêu và loại bỏ các mục tiêu 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à tất cả mục tiêu trong đầu ra phải hiển thị. Biểu thức visible đánh giá thành tập hợp chứa tất cả các mục tiêu x sao cho x là thành viên của tập hợp input và đối với tất cả các mục tiêu y trong predicate, x hiển thị với y. Ví dụ:

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

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

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

expr ::= labels(word, expr)

Toán tử labels(attr_name, inputs) trả về tập hợp các mục tiêu được chỉ định trong thuộc tính attr_name thuộc loại "nhãn" 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 có thuộc tính srcs trong tập hợp inputs, thì kết quả hợp nhất của srcs sẽ được trả về.

Mở rộng và lọc test_suites: tests

expr ::= tests(expr)

Toán tử tests(x) trả về tập hợp tất 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 bài kiểm thử riêng lẻ mà chúng tham chiếu đến và áp dụng bộ lọc theo tagsize.

Theo mặc định, hoạt động đá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 tất cả quy tắc test_suite. Bạn có thể thay đổi tuỳ chọn này thành lỗi bằng tuỳ chọn --strict_test_suite.

Ví dụ: truy vấn kind(test, foo:*) liệt kê tất cả quy tắc *_testtest_suite trong gói foo. Tất cả kết quả đều là (theo định nghĩa) thành viên của gói foo. Ngược lại, truy vấn tests(foo:*) sẽ trả về tất cả các chương trình kiểm thử riêng lẻ sẽ được bazel test foo:* thực thi: điều này có thể bao gồm các chương trình 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 các quy tắc test_suite.

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

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à gói đó 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 tệp hoặc gói cần có để xây dựng mục tiêu đã chỉ định, 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 một cách bắc cầu.

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

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

Toán tử rbuildfiles lấy 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ư các 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à vũ trụ do cờ --universe_scope chỉ định. 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) bị bỏ qua, ngay cả khi chúng được đề cập rõ ràng trong tệp BUILD. Tuy nhiên, đường liên kết tượng trưng được tôn trọng, vì vậy, nếu foo/BUILD là đườ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ả.

Toán tử rbuildfiles gần như là nghịch đảo của toán tử buildfiles. Tuy nhiên, sự đảo ngược đạo đức này giữ vững mạnh hơn theo một hướng: dữ liệu đầu ra của rbuildfiles cũng giống như dữ liệu đầu vào của buildfiles; dữ liệu đầu vào chỉ chứa mục tiêu tệp BUILD trong các gói và dữ liệu đầu ra có thể chứa các mục tiêu như vậy. Ở hướng ngược lại, mối tương ứng sẽ 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 cần thiết cho một dữ liệu đầ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: tảifile

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 hợ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 của gói đó.

Đị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à bazel query trình bày biểu đồ này thông qua tuỳ chọn dòng lệnh --output.

Khi chạy bằng Truy vấn Sky, bạn chỉ được phép sử dụng các định dạng đầu ra tương thích với đầu ra không theo thứ tự. 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 từng tuỳ chọn đầu ra được thêm tiền tố là định dạng đầu ra tương ứng, vì vậy, --graph:factored chỉ áp dụng khi bạn sử dụng --output=graph; tuỳ chọn này không có hiệu lực nếu bạn sử dụng định dạng đầu ra không phải graph. Tương tự, --xml:line_numbers chỉ áp dụng khi --output=xml đang được sử dụng.

Về thứ tự của kết quả

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

Giá trị mặc định của cờ này là auto, giúp in kết quả theo thứ tự bảng chữ cái. Tuy nhiên, khi 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à tuỳ chọn nhanh nhất. Tuy nhiên, định dạng này không được hỗ trợ khi --output là một trong các định dạng 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 kết quả theo một số thứ tự tô pô, 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ừ nút này đến nút kia) có thể được in theo thứ tự bất kỳ.

Khi cờ này là full, Bazel sẽ in các nút theo thứ tự xác định đầy đủ (tổng). 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 một quá trình tìm kiếm theo thứ tự sau, trong đó các cạnh đi đến các nút chưa được truy cập được duyệt theo thứ tự bảng chữ cái của các nút kế tiếp. Cuối cùng, các nút được in theo thứ tự ngược lại với thứ tự 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 các nút này khi thuật toán tất định là quan trọng.

In dạng nguồn của mục tiêu như sẽ xuất hiện trong BUILD

--output build

Với tuỳ chọn này, cách trình bày từng mục tiêu sẽ giống như được viết tay bằng ngôn ngữ BUILD. Tất cả cá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 hữu ích để xem hiệu ứng của macro Starlark. Ngoài ra, mỗi quy tắc có hiệu lực sẽ báo cáo một giá trị generator_name và/hoặc generator_function), đồng thời cung cấp tên của macro đã được đánh giá để tạo quy tắc có hiệu lực.

Mặc dù đầu ra sử dụng cùng cú pháp với 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 mỗi mục tiêu trong biểu đồ thu được sẽ được in, mỗi dòng một nhãn, theo thứ tự tôpô (trừ phi bạn chỉ định --noorder_results, hãy xem ghi chú về thứ tự kết quả). (Thứ tự tô pô là thứ tự trong đó một nút biểu đồ xuất hiện sớm hơn tất cả các nút kế tiếp.) Tất nhiên, có nhiều thứ tự topo có thể có của một biểu đồ (thứ tự hậu đảo ngược chỉ là một trong số đó); không chỉ định thứ tự nào được chọn.

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 hiếm gặ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 (ngầm ẩn) của quy tắc đó đều 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ì kết quả (ở định dạng label) sẽ xuất hiện một mục 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à mục tiêu còn lại có loại 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 lại đứng trước nhãn theo loại mục tiêu.

--output proto

In kết quả truy vấn dưới dạng vùng đệm giao thức QueryResult.

--output streamed_proto

In luồng được phân tách theo độ dài của các vùng đệm giao thức Target. Điều này hữu ích để (i) khắc phục các giới hạn về kích thước của vùng đệm giao thức khi có quá nhiều mục tiêu để vừa với một QueryResult hoặc (ii) để bắt đầu xử lý trong khi Bazel vẫn đang xuất.

--output textproto

Tương tự như --output proto, in vùng đệm giao thức QueryResult nhưng ở định dạng văn bản.

--output streamed_jsonproto

Tương tự như --output streamed_proto, hãy in luồng vùng đệm giao thức Target nhưng ở định dạng ndjson.

--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ự topo, các nhãn này xuất hiện theo thứ tự thứ hạng, đứng trước là số thứ hạng. Các giá trị này không bị ảnh hưởng bởi cờ --[no]order_results sắp xếp kết quả (xem các lưu ý về việc sắp xếp kết quả).

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

maxrank xếp hạng mỗi nút theo độ dài của đường dẫn dài nhất từ mộ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 một so với 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ỳ đều được coi là có thứ hạng bằng nhau. (Hầu hết biểu đồ đều không tuần hoàn, nhưng chu kỳ vẫn xảy ra chỉ vì tệp BUILD chứa các chu kỳ không chính xác.)

Các định dạng đầu ra này hữu ích để khám phá độ sâu của biểu đồ. Nếu được dùng cho kết quả của truy vấn deps(x), rdeps(x) hoặc allpaths, thì số thứ hạng 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 ở thứ hạng đó. Bạn có thể sử dụng maxrank để xác định trình tự dài nhất của các bước xây dựng cần thiết để tạo một mục tiêu.

Ví dụ: biểu đồ ở bên trái sẽ tạo 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 sẽ 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 tuỳ chọn này được đặt trước bằng 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 tệp sau (chẳng hạn như Emacs hoặc vi) cũng có thể sử dụng kết quả truy vấn để thực hiện một loạt các kết quả trùng khớp, cho phép sử dụng công cụ truy vấn Bazel làm "grep cho tệp BUILD" nhận biết được biểu đồ phần phụ thuộc.

Thông tin vị trí sẽ khác nhau tuỳ theo loại mục tiêu (xem toán tử kind). Đố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 tệp nguồn, vị trí của dòng 1 của tệp thực tế sẽ được in. Đối với tệp đã tạo, vị trí của quy tắc tạo 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 đã tạo và trong mọi trường hợp, tệp này có thể không tồn tại nếu bạn chưa tạo bản dựng.)

--output package

Tuỳ chọn này in tên của tất cả các gói mà một số mục tiêu trong tập hợp kết quả thuộc về. Các tên được in theo thứ tự từ vựng; các tên trùng lặp sẽ bị loại trừ. Về mặt hình thức, đây là một mặt chiếu từ tập hợp nhãn (gói, mục tiêu) lên các gói.

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

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

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

--output graph

Tuỳ chọn này sẽ in kết quả truy vấn dưới dạng biểu đồ có hướng trong đị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 đường dẫn không thể dễ dàng hiển thị khi kết xuất ở dạng tuyến tính, chẳng hạn như với --output label.

Theo mặc định, biểu đồ được hiển thị ở dạng đã nhân. Tức là các nút tương đương về mặt tô pô đượ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 đồ nhỏ gọn và dễ đọc hơn, vì các biểu đồ kết quả thông thường chứa các mẫu lặp lại nhiều lần. Ví dụ: quy tắc java_library có thể phụ thuộc vào hàng trăm tệp nguồn Java, tất cả đều do cùng một genrule tạo ra; trong biểu đồ được phân tích, tất cả các 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 đồ thị trong đầu ra. Nhãn dài hơn sẽ bị cắt ngắn; -1 sẽ tắt tính năng cắt ngắn. Do hình thức tính toán mà biểu đồ thường được in, nên nhãn 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 tuỳ chọn này. Tuỳ chọn này không có hiệu lực trừ phi bạn sử dụng --output=graph.

--[no]graph:factored

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

XML

--output xml

Tuỳ chọn này khiến các mục tiêu kết quả được in ở dạng XML. Kết quả bắt đầu bằng một tiêu đề XML như sau

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

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

</query>

Các mục nhập đơn giản được phát 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 các quy tắc, XML được cấu trúc và chứa định nghĩa của tất cả cá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ể xây dựng 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à phần phụ thuộc tiến lên (đ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 (người tiêu 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 chứa một thuộc tính name, giá trị của thuộc tính này là nhãn của mục tiêu và một thuộc tính location, giá trị của thuộc tính này là vị trí của mục tiêu do --output location in ra.

--[no]xml:line_numbers

Theo mặc định, vị trí hiển thị trong dữ liệu đầu ra XML sẽ chứa số dòng. Khi 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 rõ ràng). Tuỳ chọn này sẽ đưa các giá trị thuộc tính đó vào đầu ra XML.

Cụm từ thông dụng

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

Truy vấn bằng 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ừ 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 dưới dạng 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. Tức là trong ví dụ trên, //external:other-repo không phải là phần phụ thuộc. Tuy nhiên, bạn có thể truy vấn đối tượng này dưới dạng thành phần của gói //external, 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