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

Báo cáo sự cố Xem nguồn

Trang này là 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. Mã này cũng mô tả các định dạng đầu ra mà bazel query hỗ trợ.

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

Tài liệu tham khảo bổ sung về truy vấn

Ngoài query, chạy trên biểu đồ mục tiêu của giai đoạn sau khi tải, Bazel còn có 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 phân tích sau 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ế chạy cũng như dữ liệu đầu vào, đầu ra và chức năng ghi nhớ 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 của giai đoạn sau tải, 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à tính năng này không giải quyết chính xác các câu lệnh chọn lọc mà thay vào đó trả về tất cả các độ phân giải có thể có của 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 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? 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ị đường dẫn:

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

Tất cả các hoạt động kiểm thử foo nào đều phụ thuộc vào những thư viện C++ nào mà mục tiêu foo_bin thì 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à các từ dành riêng trong ngôn ngữ này và đượ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 chuỗi ký tự được "dấu ngoặc kép" (bắt đầu và kết thúc bằng dấu ngoặc đơn " hoặc bắt đầu và kết thúc bằng dấu ngoặc kép "), thì đó là một từ. Nếu một chuỗi ký tự không được trích dẫn, thì hệ thống vẫn có thể phân tích cú pháp chuỗi đó dưới dạng một từ. Từ không được trích dẫn là chuỗi ký tự được vẽ từ ký tự bảng chữ cái A-Za-z, chữ số 0-9 và 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 nối, dấu gạch dưới, dấu hai chấm, ký hiệu đô la, dấu ngã, dấu ngoặc vuông trái, dấu ngoặc vuông bên phải). Tuy nhiên, từ không được trích dẫn có thể 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ự đó.

    Từ không được 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 đích. Khi viết mã tạo biểu thức truy vấn, tên mục tiêu phải được trích dẫn.

    Bạn cần trích dẫn 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 ngoặc kép này bổ sung cho bất kỳ dấu ngoặc kép nào mà shell có thể yêu cầu, chẳng hạn như:

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

    Các từ khoá và toán tử, 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 nháy đơ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 ngoặc đơn hoặc tất cả dấu ngoặc kép).

    Sau đây là các 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ùng dấu ngoặc kép trong hầu hết các trường hợp. Ví dụ về ".*test rule" (bất thường) cần có dấu ngoặc kép: bắt đầu bằng một 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 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 ,. Các từ có chứa dấu câu (trừ các trường hợp ngoại lệ nêu trên) đều phải được trích dẫn.

Hệ thống sẽ bỏ qua các ký tự khoảng trắng bên ngoài từ nằm trong 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 theo thứ tự một phần hoặc một biểu đồ (DAG) mục tiêu tương đương. Đâ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, ví dụ:

  • Đặt: Thứ tự từng phần của các mục tiêu sẽ không được quan tâm.
  • Biểu đồ: Thứ tự từng phần của các mục tiêu là 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 mạnh mẽ dựa trên chu kỳ. Chi tiết về cách xử lý các chu kỳ không được chỉ định và không nên dựa vào.

Các 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 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. Các phần phụ thuộc ngầm ẩn có thể được xác định bằng cách:

Theo mặc định, bazel query 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 phương thức triển khai chuỗi công cụ tiềm năng không được coi là phần phụ thuộc, mà chỉ xem các loại chuỗi công cụ bắt buộc. Hãy xem tài liệu về chuỗi công cụ.

Â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. 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 cần phải có một cấu hình; hãy 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 bằng ngôn ngữ truy vấn Bazel là đúng cho mọi cấu hình, có nghĩa là biểu thức đó có thể là một phép ước tính quá ước tính 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 vì 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 lưu giữ thứ tự biểu đồ

Thao tác sẽ giữ nguyên mọi quy tắc ràng buộc 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 kết quả sẽ được sắp xếp theo biểu đồ phần phụ thuộc. Nếu bạn lọc thuộc tính đó để chỉ bao gồm các mục tiêu thuộc loại file, thì quan hệ sắp xếp một phần chuyển tiếp tương tự sẽ được áp dụng 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 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 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ữ lại thứ tự, nhưng một số toán tử, chẳng hạn như thao tác đặt không áp dụng bất kỳ quy tắc ràng buộc nào về thứ 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 giữ nguyên mọi quy tắc ràng buộc theo thứ tự của 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 một cách chính xác 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ừ những mục tiêu trong y cũng xảy ra trong deps(x)).

Các toán tử đưa ra các quy tắc ràng buộc theo 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.

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

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ế độ 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ế độ Truy vấn Sky đượ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 hoạt động đó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ó thể có tác dụng cộng và trừ). Sau đó, tất cả các cụm từ tìm kiếm 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 dự đoán một giá trị cho --universe_scope qua 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à đ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 riêng biệt trong biểu thức truy vấn này là ["//my:target"], vì vậy, Bazel xử lý các mẫu 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 tạo 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 các 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 là một sự thuận tiện, đặc biệt là trong trường hợp việc 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 các 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 biểu thức đó là điều bạn muốn.

Truy vấn Sky 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 đồ và do đó một số định dạng đầu ra nhất định 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 bằng cách xem xét nội dung biểu đồ Skyframe, thay vì tạo một biểu đồ mới, đây là hoạt động được triển khai mặc định. Do đó, trong một số trường hợp, ứng dụng sẽ 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 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ả theo thứ tự từng quy tắc tạo ra ngữ pháp này.

Các 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 có giá trị là một tập hợp chứa một phần tử là mục tiêu và quy tắc bar.

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

Tương tự, foo/...:* là một mẫu mục tiêu đánh giá một tập hợp chứa tất cả các mục tiêu (các quy tắc tệp) trong mọi gói theo quy tắc đệ quy bên dưới thư mục foo; bar/baz:* đánh giá 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 tệp cũng như quy tắc, nên cách 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 đối với 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 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 một tập hợp singleton (trong trường hợp một nhãn), 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 được sắp xếp một cách chính xác 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 đồ của 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ự 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 cũng giống như 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/....

Lỗi khi xảy ra lỗi khi xuất hiện tham chiếu biến name khác với biểu thức let name = ... đi kèm. Nói cách khác, biểu thức truy vấn cấp cao nhất không thể có các biến tự do.

Trong các tài liệu ngữ pháp ở trên, name giống như từ, nhưng có thêm một quy tắc ràng buộc rằng đó là giá trị nhận dạng hợp pháp trong ngôn ngữ lập trình C. Phần 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 duy nhất, nhưng bạn có thể lồng các biến đó.

Cả mẫu mục tiêu và tệp 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 biệt vớ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 đạt của ngôn ngữ truy vấn: mọi truy vấn có thể được diễn đạt bằng ngôn ngữ đó cũng có thể được biểu thị mà không cần các biểu thức đó. 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 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 phụ để buộc đánh giá. Biểu thức được đặt trong dấu ngoặc đơn đánh giá giá trị của đối số.

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

Ví dụ:

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

đánh giá tập hợp các mục tiêu phù hợ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 như sau:

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

Toán tử intersect (^) và union (+) mang tính giao hoán (đối xứng); except (-) không đối xứng. Trình phân tích cú pháp sẽ coi cả 3 toán tử là có liên kết trái và có mức độ ưu tiên như nhau, vì vậy, bạn nên sử dụng dấu ngoặc đơn. Ví dụ: 2 biểu thức đầu tiên trong số này là tương đương, 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 hợp nhất một tập hợp gồm từ 0 trở lên mẫu mục tiêu, đượ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, 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ông cụ shell UNIX tiêu chuẩn), sau đó đưa lại kết quả vào công cụ truy vấn làm 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 trên 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 những ví dụ này, $(<foo) là cách 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 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ác hàm sau:

Đóng bắc cầu 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 đồ được hình thành khi đó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ừ mộ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 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 của 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 đồ thu được đượ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 thứ tự biểu đồ.

Toán tử deps chấp nhận một đối số thứ hai không bắt buộc. Đối số này là một số nguyên chỉ đị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 mọi mục tiêu 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 hiển thị ở đị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ị ràng buộc: nó sẽ tính toán hoạt động đó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 của các 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 ngược của tập hợp đối số x trong phần đó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ần phụ thuộc. Hãy xem phần về thứ tự 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. Đối số này là một số nguyên chỉ định giới hạn trên về mức độ tìm kiếm. Biểu đồ kết quả chỉ bao gồm các nút nằm trong khoảng cách tính từ độ sâu đã chỉ định so với bất kỳ nút nào trong tập đối số. Vì vậy, rdeps(//foo, //common, 1) sẽ đánh giá tất cả các nút trong trạng thái đó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 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ị ràng buộc.

Đóng bắc cầu 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 "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) 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 một 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 tập hợp mục tiêu đó.

Xử lý gói của mục tiêu: anh em

expr ::= siblings(expr)

Toán tử siblings(x) đánh giá toàn bộ 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 của nó 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 đối số x nhỏ hơn k, toàn bộ đối số tập x sẽ được trả về.

Ví dụ: biểu thức some(//foo:main union //bar:baz) có giá trị cho một tập hợp singleton chứa //foo:main hoặc //bar:baz – mặc dù một tập hợp này 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 hàm nhận dạng: some(//foo:main) tương đương với //foo:main.

Đây là 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, 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 tập hợp mục tiêu. Cả hai truy vấn 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 đường dẫn một số 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 đường dẫn tất cả 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 đồ thu được được sắp xếp theo mối quan hệ phụ thuộc. Hãy xem phần về thứ tự biểu đồ để biết thêm chi tiết.

Đường dẫn nào đó
somepath(S1 + S2, E), có thể có một kết quả.
Đường dẫn nào đó
somepath(S1 + S2, E), có thể có 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) sẽ á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) được minh hoạ trong bảng dưới đây:

Mục tiêu Loại
        genrule(
            name = "a",
            srcs = ["a.in"],
            outs = ["a.out"],
            cmd = "...",
        )
      
//p:a quy tắc tạo sinh
//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ả mục tiêu quy tắc cc_library, cc_binary, v.v. bên dưới foo, còn kind("source file", deps(//foo)) sẽ đánh giá 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.

Thông thường, bạn cần đặ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, sẽ không được trình phân tích cú pháp xem là các từ.

Khi 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 bất kỳ 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) sẽ á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ỏ 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 sẽ đánh giá một tập hợp con đầu vào.

Đối số đầu tiên, pattern là một từ có chứa biểu thức chính quy thay vì tên mục tiêu. Biểu thức filter đánh giá đến 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 một kết quả trùng khớp (không cố định) 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ể dùng tên này để thay thế cho điểm 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, người ta 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. 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. Cách khác 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 phù hợp với mẫu đã cung cấp — nói cách khác, các mục tiêu có tên chứa //bar là 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ả .cc tệp đượ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 là 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 mục tiêu quy tắc có 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á cho 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 đối với các giá trị thuộc tính. Biểu thức attr có giá trị cho 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. Đây 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 một kết quả trùng khớp (chưa cố định) 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ả phần phụ thuộc //foo được phép có thuộc tính linkshared (chẳng hạn như quy tắc cc_binary) và đặt thuộc tính đó một cách rõ ràng thành 0 hoặc hoàn toàn không đặt giá trị mặc định là 0 (chẳng hạn như cho 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 chuỗi có 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 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]. Dấu ngoặc luôn tồn tại, vì vậy, danh sách trống sẽ sử dụng giá trị chuỗi [] cho mục đích 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 dài í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 dấu cách, còn 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 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à tất cả cá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 phầ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 sẽ hiển thị cho y. Ví dụ:

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

sẽ chọn tất cả cá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 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 "label" hoặc "danh sách nhãn" trong một số quy tắc thuộc 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 thuộc tính srcs trong tập hợp inputs, thì hợp nhất của srcs sẽ được trả về.

Mở rộng và lọc test_suites: kiểm thử

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, đồng thời á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 trường hợp 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 các 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 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 qua load. Xin lưu ý rằng thao tác này cũng trả về 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 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

sẽ trả về tập hợp tất cả các gói mà //foo phụ thuộc chuyển tiếp.

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

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

Toán tử rbuildfiles 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 chuyển tiếp vào các mảnh đường dẫn này. Chẳng hạn như 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à không gian đượ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ập rõ ràng trong tệp BUILD. Tuy nhiên, các đường liên kết biểu tượng được tuân thủ để 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 pháp lý, toán tử rbuildfiles gần như là toán tử nghịch đảo của toán tử buildfiles. Tuy nhiên, sự đảo ngược đạo đức này ảnh hưởng mạnh mẽ hơn đến một hướng: đầu ra của rbuildfiles cũng giống như đầu vào của buildfiles; đầu vào 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, thư từ trao đổi 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à tệp .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: loadfile

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, phương thức 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 sẽ 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 thông qua tuỳ chọn dòng lệnh --output.

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

Về 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ự biểu đồ", nhưng việc trình bày kết quả có thể được thực hiện theo thứ tự phần phụ thuộc hoặc không có 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ả hoặc 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 với 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ể sử 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. Giá trị này in ra thứ tự từ vựng. Tuy nhiên, khi somepath(a,b) được sử dụng, 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. Thuộc tính 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ự phần phụ thuộc hoặc thứ hạng.

Khi cờ này là deps, Bazel sẽ in theo một thứ tự cấu trúc liên kết nào đó, nghĩa là phần phụ thuộc trước và phần phụ thuộc sau. 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ự hoàn toàn tất định (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 lượt tìm kiếm theo chiều sâu theo thứ tự sau, trong đó các cạnh bên ngoài tới các nút chưa được truy cập sẽ được di chuyển 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ự ngược lại 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 nút này khi tính tất định 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, nội dung trình bày từng mục tiêu sẽ như thể đượ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 khi 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), cung cấp 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ừ phi --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 đó nút biểu đồ xuất hiện sớm hơn tất cả các nú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ự ngược lại chỉ là một thứ tự); thứ tự được chọn sẽ không được chỉ định.

Khi in kết quả của một 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 góc, có thể có hai mục tiêu riêng biệt với cùng một nhãn; ví dụ: quy tắc sh_binary và tệp srcs duy nhất (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ẽ có vẻ như chứa một dữ liệu 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 bằng loại của 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 một luồng được phân tách theo độ dài của các vùng đệm giao thức Target. Việc này rất hữu ích để (i) vượt qua 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 cần đưa vào 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, in một luồng vùng đệm giao thức Target nhưng ở định dạng ndjson.

--output minrank --output maxrank

Giống như label, các đị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 sẽ xuất hiện theo thứ tự xếp hạng, đứng sau số thứ tự của chúng. Những cờ này không bị ảnh hưởng bởi cờ theo thứ tự kết quả --[no]order_results (xem 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 đườ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 đến) được xếp hạng 0, các nút kế thừa của các nút đó là xếp hạng 1, v.v. (Như thường lệ, các cạnh trỏ từ một mục tiêu đến các đ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ừ nút gốc đến nút đó. Xin nhắc lại, "gốc" có hạng 0, tất cả các nút khác đều có hạng cao hơn một hạng so với 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 có thứ hạng bằng nhau. (Hầu hết các biểu đồ đều chu kỳ, nhưng chu kỳ chỉ xảy ra vì các tệp BUILD chứa chu kỳ không chính xác).

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 dùng cho kết quả của truy vấn deps(x), rdeps(x) hoặc allpaths, thì số thứ hạng sẽ bằng độ dài của đường dẫn ngắn nhất (với minrank) hoặc đường dẫn 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 của các bước xây dựng cần thiết để tạo mục tiêu.

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

Bị loại khỏi thứ hạng
      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 cho từng 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 phần sau (chẳng hạn như Emacs hoặc vi) cũng có thể sử dụng đầu ra truy vấn để duyệt qua một loạt kết quả so 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 biểu đồ 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 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 được 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 chưa được 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 chứa một số mục tiêu trong tập hợp kết quả. Các tên được in theo thứ tự từ điển học và không bao gồm các trường hợp 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ể dùng tuỳ chọn đầu ra này để tìm tập hợp các gói phải được kiểm tra để xây dựng một tập hợp mục tiêu nhất định.

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

--output graph

Tuỳ chọn này khiến kết quả truy vấn được in 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ả đượ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 nhìn thấy đượ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 đồ sẽ hiển thị ở dạng thành phần. Điều này nghĩa là các nút tương đương về 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 đồ trở nên gọn nhẹ 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 do cùng một genrule tạo; trong biểu đồ đã 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 biểu đồ trong đầu ra. Nhãn dài hơn sẽ bị cắt bớt; -1 tắt tính năng cắt bớt. Do biểu đồ thường được in theo hình thức bao hàm, 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 sử dụng --output=graph.

--[no]graph:factored

Theo mặc định, biểu đồ sẽ hiển thị ở dạng đã phân tích, 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 nhân tử. Điều này giúp việc trực quan hoá bằng cách sử dụng GraphViz trở nên khó tin, 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 khiến các mục tiêu thu được sẽ được in ở dạng XML. Đầu ra sẽ bắt đầu bằng tiêu đề XML, chẳng hạn như

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

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

</query>

Các mục nhập đơn giản được phát ra 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 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 tiêu dùng).

Các phần tử rule-input cho các 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 --output location in ra.

--[no]xml:line_numbers

Theo mặc định, các vị trí hiển thị 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 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 đầ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, thì kết quả truy vấn sẽ bao gồm các phần phụ thuộc đó. Ví dụ: nếu //foo:bar phụ thuộc vào @other-repo//baz:lib, thì bazel query 'deps(//foo:bar)' sẽ liệt kê @other-repo//baz:lib là phần phụ thuộc.