Trang này là hướng dẫn tham khảo cho Ngôn ngữ truy vấn Bazel được sử dụng
khi bạn dùng bazel query
để phân tích các phần phụ thuộc của bản dựng. Điều 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 khác về truy vấn
Ngoài query
, chạy trên biểu đồ mục tiêu giai đoạn sau tải,
Bazel bao gồm truy vấn biểu đồ hành động và truy vấn có thể định cấu hình.
Truy vấn trên biểu đồ hành động
Truy vấn biểu đồ hành động (aquery
) hoạt động dựa trên dữ liệu đã định cấu hình sau khi phân tích
Biểu đồ mục tiêu và hiển thị thông tin về Thao tác, Cấu phần phần mềm và
mối quan hệ của họ. aquery
rất hữu ích khi bạn quan tâm đến
của Thao tác/Cấu phần phần mềm được tạo từ Biểu đồ mục tiêu đã định cấu hình.
Ví dụ: các lệnh thực tế sẽ chạy cũng như dữ liệu đầu vào, đầu ra và hệ thống ghi nhớ của các lệnh đó.
Để biết thêm thông tin chi tiết, hãy xem tài liệu tham khảo về truy vấn.
Truy vấn có thể định cấu hình
Truy vấn Bazel truyền thống chạy trên biểu đồ mục tiêu giai đoạn sau tải và
do đó không có khái niệm về cấu hình và các khái niệm có liên quan của chúng. Đáng chú ý,
câu lệnh đó không phân giải chính xác một số câu lệnh
và thay vào đó sẽ trả về tất 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 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? 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)
Thư viện C++ nào thực hiện tất cả các kiểm thử foo
phụ thuộc vào điều đó
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 thành phần sau mã thông báo:
Từ khoá, chẳng hạn như
let
. Từ khoá là các từ dành riêng của ngôn ngữ lập trình và từng ngôn ngữ được mô tả dưới đây. Toàn bộ của từ khóa 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 "trích dẫn" (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 "), đó là một từ. Nếu một chuỗi ký tự không được trích dẫn, nhưng vẫn có thể được phân tích cú pháp dưới dạng từ. Các từ không được trích dẫn là chuỗi các từ được sắp xếp theo thứ tự ký tự được rút từ các ký tự bảng chữ cái A-Za-z, các chữ số 0-9, và các ký tự đặc biệt*/@.-_:$~[]
(dấu hoa thị, dấu gạch chéo lên, dấu 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 bên trái, hình vuông bên phải dấu ngoặc nhọn). 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 với những ký tự đó.Các từ không được trích dẫn cũng có thể không bao gồm ký tự dấu cộng
+
hoặc bằng=
, mặc dù các ký tự đó được phép trong tên đích. Thời gian viết mã tạo biểu thức truy vấn, tên đích phải được đặt trong cặp dấu ngoặc kép/dấu ngoặc đơn.Bạn cần trích dẫn khi viết tập lệnh tạo truy vấn Bazel biểu thức 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 trích dẫn này bổ sung cho bất kỳ trích dẫn nào mà có thể được yêu cầu bởi shell, 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 xem là 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" 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. Thời gian 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ộ dấu ngoặc kép).
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. Chiến lược phát hành đĩa đơn (không bình thường) Ví dụ về
".*test rule"
cần có dấu ngoặc kép: dấu này bắt đầu bằng dấu chấm và có chứa dấu cách. Việc trích dẫn"cc_library"
là không cần thiết nhưng vô hại.Dấu câu, chẳng hạn như dấu ngoặc đơn
()
, dấu chấm.
và dấu phẩy,
. Từ ngữ Phải đặt dấu ngoặc kép (ngoài các trường hợp ngoại lệ được liệt kê ở trên).
Các ký tự khoảng trắng không nằm trong từ trong dấu ngoặc kép 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à một ngôn ngữ của biểu thức. Mỗi biểu thức đánh giá là một tập hợp mục tiêu được sắp xếp một phần, hoặc tương đương là một biểu đồ (DAG) của các mục tiêu. Đây là kiểu dữ liệu.
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 sự khác biệt các khía cạnh của ứng dụng, ví dụ:
- Đặt: Thứ tự một phần của các mục tiêu không đáng chú ý.
- Biểu đồ: Thứ tự một 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
Tạo biểu đồ phần phụ thuộc phải có chu trình.
Các thuật toán được sử dụng bởi ngôn ngữ truy vấn được dành để sử dụng trong đồ thị không chu trình nhưng mạnh mẽ so với các chu kỳ. Thông tin chi tiết về cách thực hiện chu kỳ được xử lý 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 việc tạo các phần phụ thuộc được xác định rõ ràng trong tệp BUILD
,
Bazel thêm các phần phụ thuộc ngầm ẩn khác vào các quy tắc. Ví dụ:
mọi quy tắc Java đều ngầm phụ thuộc vào JavaBuilder. Các phần phụ thuộc ngầm ẩn
được thiết lập bằng các thuộc tính bắt đầu bằng $
Không thể ghi đè trong BUILD
tệp.
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 khi truy vấn không xem xét
các cấu hình, chuỗi công cụ tiềm năng sẽ không bao giờ được xem xét.
Độ âm thanh
Biểu thức ngôn ngữ truy vấn Bazel hoạt động trong bản dựng
biểu đồ phần phụ thuộc là biểu đồ được xác định ngầm theo tất cả
khai báo quy tắc trong mọi tệp BUILD
. Điều quan trọng là phải hiểu rõ
biểu đồ này hơi 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 một bản dựng. Trong
để thực hiện một bản dựng, bạn cũng cần phải có cấu hình;
xem cấu hình
của Hướng dẫn người dùng để biết thêm chi tiết.
Kết quả của việc đánh giá một biểu thức bằng ngôn ngữ truy vấn Bazel là đúng cho tất cả các cấu hình, có nghĩa là có thể ước lượng quá mức khiêm tốn và không chính xác. Nếu bạn hãy 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, tính năng này có thể báo cáo nhiều thông tin hơn mức thực sự cần thiết bởi vì công cụ truy vấn sẽ bao gồm tất cả các tệp cần thiết để hỗ trợ dịch thư, ngay cả khi 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 đồ
Thao tác giữ nguyên mọi thứ tự
các hạn chế được kế thừa từ biểu thức phụ của chúng. Bạn có thể nghĩ đến
gọi là "định luật bảo toàn trật tự từng phần". Cân nhắc sử dụng
ví dụ: nếu bạn đưa ra truy vấn để xác định việc đóng bắc cầu của
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 thứ tự
theo biểu đồ phần phụ thuộc. Nếu bạn lọc đặt thành
chỉ bao gồm các mục tiêu thuộc loại file
, giống nhau
Mối quan hệ thứ tự một phần ngoại cung 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ác cặp này thực sự liên kết trực tiếp trong đồ thị ban đầu.
(Không có cạnh 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 giữ nguyên thứ tự, một số toán tử chẳng hạn như phép toán tập hợp không đưa ra bất kỳ ràng buộc nào về thứ tự của chính URL đó. 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 ràng buộc sắp xếp 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 bằng
tôn trọng lẫn nhau. Tuy nhiên, truy vấn này không đảm bảo điều gì về
thứ tự của các mục tiêu trong y
, cũng như về thứ tự của
thứ tự của các mục tiêu trong deps(x)
so với thứ tự trong
y
(ngoại trừ các mục tiêu đó trong
y
cũng có ở deps(x)
).
Các toán tử đưa ra các hạn chế về thứ tự bao gồm:
allpaths
, deps
, rdeps
, somepath
và các ký tự đại diện mẫu mục tiêu
package:*
, dir/...
, v.v.
Truy vấn bầu trời
Sky Query là chế độ truy vấn hoạt động trong phạm vi vũ trụ được 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 allrdeps
và
rbuildfiles
Các hàm này hoạt động trên toàn bộ
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ế độ Sky Query đượ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>
cho biết truy vấn với
tải trước hệ thố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. Việc này có thể
vừa có tính cộng và trừ. Sau đó, tất cả truy vấn sẽ được đánh giá trong "phạm vi" này. Cụ thể,
allrdeps
và
Toán tử rbuildfiles
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
khỏi biểu thức truy vấn. Giá trị được suy luận này là danh sách các mẫu mục tiêu duy nhất trong
nhưng đây có thể không phải là điều bạn muốn. Ví dụ:
bazel query --infer_universe_scope --order_output=no "allrdeps(//my:target)"
Danh sách các mẫu mục tiêu duy nhất trong biểu thức truy vấn này là ["//my:target"]
, vì vậy
Bazel xử lý điề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
xây dựng! Mặt khác, hãy cân nhắc:
bazel query --infer_universe_scope --order_output=no "tests(//a/... + b/...) intersect allrdeps(siblings(rbuildfiles(my/starlark/file.bzl)))"
Đây là 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
tests
mở rộng 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 tệp .bzl
nhất định. Tại đây,
--infer_universe_scope
là thuận tiện, đặc biệt là trong trường hợp mà việc lựa chọn
Nếu không, --universe_scope
sẽ 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 các toán tử trong phạm vi vũ trụ như
allrdeps
và
Hãy nhớ rbuildfiles
sử dụng
--infer_universe_scope
chỉ khi hành vi của ứng dụng là điều bạn muốn.
Sky Query có một số ưu điểm và nhược điểm so với truy vấn mặc định. Chính
bất lợi là không thể sắp xếp đầu ra theo thứ tự trên đồ thị và do đó không chắc chắn
định dạng đầu ra bị cấm. Ưu điểm của phương pháp này là
hai toán tử (allrdeps
và
rbuildfiles
) không có trong truy vấn mặc định.
Đồng thời, Sky Query thực hiện công việc của mình bằng cách xem xét
Biểu đồ Khung trời thay vì tạo một biểu đồ mới
biểu đồ, đây là chức năng mà hoạt động triển khai mặc định thực hiện. Vì vậy, có một số trường hợp trong đó
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 tác phẩm của ngữ pháp này.
Mẫu mục tiêu
expr ::= word
Theo cú pháp, mẫu mục tiêu chỉ là một từ. Nó được hiểu là
(không theo thứ tự). Mẫu mục tiêu đơn giản nhất là một nhãn
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
cho kết quả là một tập hợp chứa một phần tử là mục tiêu là bar
.
Các mẫu mục tiêu tổng quát hoá các nhãn để đưa ký tự đại diện vào 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á một tập hợp chứa tất cả quy tắc trong mỗi gói theo cách đệ quy
bên dưới thư mục foo
; bar/baz:all
là 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 chứa các quy tắc
các gói con.
Tương tự, foo/...:*
là mẫu mục tiêu đánh giá một tập hợp chứa
tất cả các tệp mục tiêu (quy tắc và) trong mọi gói theo cách đệ quy bên dưới
Thư mục foo
; bar/baz:*
cho kết quả là một tập hợp chứa tất cả mục tiêu trong
gói bar/baz
chứ không phải các gói con của nó.
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
cho truy vấn. Ngược lại, ký tự đại diện :all
(ngầm trong
mẫu mục tiêu như foo/...
) thường hữu ích hơn cho các bản dựng.
Mẫu mục tiêu bazel query
hoạt động giống như mục tiêu bản dựng bazel build
.
Để biết thêm 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á theo một tập singleton (trong trường hợp 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 vào 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 một biểu thức mẫu mục tiêu đều được sắp xếp chính xác
tương ứng với nhau theo mối quan hệ 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 đồ trên các mục tiêu đó. (Không đảm bảo về thứ tự tương đối
của nút kết quả so với các nút khác). Để biết thêm chi tiết, hãy xem
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
biến. Kết quả đánh giá biểu thức let
giống với
là expr2, với tất cả các lần xuất hiện miễn phí
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
là
tương đương với allpaths(foo/...,//common) intersect foo/...
.
Đã xuất hiện tham chiếu biến name
khác với trong
biểu thức let name = ...
bao quanh là một
. Nói cách khác, biểu thức truy vấn cấp cao nhất không được có
biến.
Trong các tác phẩm ngữ pháp ở trên, name
giống như từ, nhưng đi kèm với
ràng buộc bổ sung rằng đó là giá trị nhận dạng hợp pháp trong chương trình C
ngôn ngữ. Phần tham chiếu đến biến phải được thêm "$" vào trước .
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 bao gồm chỉ một mã thông báo, một từ, dẫn đến sự không rõ ràng về cú pháp. Tuy nhiên, có một không có sự mơ hồ về ngữ nghĩa, vì tập hợp con các từ là biến hợp pháp tên tách rời khỏi tập hợp con 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 tăng
tính biểu đạt của ngôn ngữ truy vấn: mọi truy vấn có thể diễn đạt bằng
ngôn ngữ cũng có thể được thể hiện mà không có chúng. Tuy nhiên, chúng
giúp câu hỏi trở nên súc tích hơn, đồng thời cũng có thể dẫn đến
đánh giá truy vấn hiệu quả hơn.
Biểu thức được đặt trong ngoặc đơn
expr ::= (expr)
Dấu ngoặc đơn liên kết các biểu thức phụ để buộc một thứ tự đánh giá. Biểu thức nằm trong ngoặc đơn sẽ đánh giá giá trị của đối số.
Toán tử tập đại số: giao điểm, hợp nhất, hiệu sai số
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ử đều có hai biểu mẫu, một dạng danh nghĩa, chẳng hạn như intersect
và một
biểu tượng, chẳng hạn như ^
. Cả hai hình thức đều tương đương nhau; các hình thức tượng trưng là
nhanh hơn. (Để 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 mục tiêu phù hợ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ư:
foo/... - foo/bar/...
Các toán tử intersect
(^
) và union
(+
) có tính giao hoán (đối xứng);
except
(-
) là bất đối xứng. Trình phân tích cú pháp coi cả 3 toán tử là
liên kết trái và có mức độ ưu tiên bằng nhau, vì vậy bạn có thể cần dùng dấu ngoặc đơn. Cho
ví dụ, hai biểu thức đầu tiên trong số các biểu thức 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 các mục tiêu từ một nguồn bên ngoài: đặt
expr ::= set(word *)
set(a b c ...)
toán tử tính toán hợp của một tập hợp gồm 0 hoặc nhiều hơ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 giao diện Bourne, set()
cung cấp
phương tiện lưu kết quả của một truy vấn trong tệp văn bản thông thường, điều chỉnh
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ị để
đang xử lý. 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))
là
được tính bằng cách lọc các giá trị maxrank
thông qua chương trình awk
.
bazel query 'deps(//some_dir/foo:main)' --output maxrank | awk '($1 < 5) { print $2;} ' > foo
bazel query "kind(cc_library, set($(<foo)))"
Trong những ví dụ này, $(<foo)
là viết tắt của $(cat foo)
, nhưng shell
Bạn cũng có thể sử dụng các lệnh 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 hàm xác định số lượng và kiểu đối số cần có. Nội dung sau đây các hàm sau:
allpaths
attr
buildfiles
rbuildfiles
deps
filter
kind
labels
loadfiles
rdeps
allrdeps
same_pkg_direct_rdeps
siblings
some
somepath
tests
visible
Đóng bắc cầu các phần phụ thuộc: phần phụ thuộc
expr ::= deps(expr)
| deps(expr, depth)
Toán tử deps(x)
đánh giá biểu đồ đã 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ả
phần phụ thuộc. Giá trị của deps(foo/...)
là các biểu đồ phần phụ thuộc có nghiệm
là tất cả quy tắc trong mọi gói trong thư mục foo
. Trong bối 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 đó, BUILD
và
Các tệp Starlark cần để 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 dùng toán tử buildfiles
.
Biểu đồ kết quả được sắp xếp theo mối quan hệ phần phụ thuộc. Để biết thêm chi tiết, xem phần về 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
giá trị cố định xác định giới hạn trên về độ sâu tìm kiếm. Loại đối thủ sau lượt đánh bóng
deps(foo:*, 0)
trả về tất cả mục tiêu trong gói foo
, trong khi
deps(foo:*, 1)
bao gồm thêm các điều kiện tiên quyết trực tiếp của bất kỳ mục tiêu nào trong
Gói foo
và deps(foo:*, 2)
khác trực tiếp chứa các nút
có thể truy cập được 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ị ở định dạng đầu ra minrank
.)
Nếu tham số depth bị bỏ qua, tìm kiếm sẽ
không giới hạn: hàm tính toán đóng bắt buộc bắc cầu phản xạ của đ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)
rdeps(u, x)
toán tử đánh giá các phần phụ thuộc ngược của tập hợp đối số
x trong tập hợp bắc cầu của vũ trụ
u.
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.
Toán tử rdeps
chấp nhận một đối số thứ ba không bắt buộc, là một số nguyên
giá trị cố định xác định giới hạn trên về độ sâu tìm kiếm. Kết quả
biểu đồ chỉ bao gồm các nút nằm trong khoảng cách của độ sâu được chỉ định từ bất kỳ
trong tập hợp đối số. Vì vậy, rdeps(//foo, //common, 1)
đánh giá cho tất cả các nút
trong đóng chuyển tiếp của //foo
phụ thuộc trực tiếp vào //common
. (Đây là
số tương ứng với thứ hạng hiển thị trong dữ liệu đầu ra minrank
format.) Nếu tham số depth bị bỏ qua,
tìm kiếm không bị ràng buộc.
Đóng bắc cầu tất cả các phần phụ thuộc ngược: ardeps
expr ::= allrdeps(expr)
| allrdeps(expr, depth)
Toán tử allrdeps
hoạt động giống như rdeps
ngoại trừ "tập hợp vũ trụ" 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 vượt qua, sau đó allrdeps(//bar)
là
tương đương với rdeps(//foo/..., //bar)
.
Các 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ục tiêu trong nhóm đối số và phụ thuộc trực tiếp vào đối số đó.
Xử lý gói của mục tiêu: đồng cấp
expr ::= siblings(expr)
Toán tử siblings(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ụ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ừ
đối số x và đánh giá cho một tập hợp chứa
chỉ những mục tiêu đó. Tham số k là không bắt buộc; nếu
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 nhóm đối số x là
nhỏ hơn k, 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)
có giá trị là
tập hợp singleton chứa //foo:main
hoặc //bar:baz
(mặc dù
một giá trị 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
và
//bar:baz
.
Nếu đối số là một singleton, thì some
tính toán hàm nhận dạng: some(//foo:main)
là
tương đương với //foo:main
.
Sẽ xảy ra lỗi nếu nhóm đố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)
somepath(S, E)
và
Điện toán của toán tử allpaths(S, E)
đường dẫn giữa hai tập hợp mục tiêu. Cả hai truy vấn chấp nhận 2
đối số, một tập hợp S các điểm xuất phát và một tập hợp
Điểm cuối E. somepath
trả về
đồ thị các nút trên đường dẫn tuỳ ý một số từ một mục tiêu trong
S thành một mục tiêu tại E; allpaths
trả về biểu đồ của các nút trên tất cả đường dẫn từ bất kỳ mục tiêu nào trong
S thành mục tiêu bất kỳ 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.
somepath(S1 + S2, E) , một kết quả có thể có. |
somepath(S1 + S2, E) , một kết quả khác có thể xảy ra. |
allpaths(S1 + S2, E) |
Lọc theo loại mục tiêu: loại
expr ::= kind(word, expr)
kind(pattern, input)
toán tử á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 đúng như mong đợi. pattern
chỉ định loại mục tiêu cần so khớp.
Ví dụ: kiểu cho 4 mục tiêu được tệp BUILD
xác định
(đối với gói p
) được minh hoạ dưới đây trong bảng:
Mã | Mục tiêu | Loại |
---|---|---|
genrule( name = "a", srcs = ["a.in"], outs = ["a.out"], cmd = "...", ) |
//p:a |
quy tắc gen |
//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/...)
sẽ tính cho tập hợp
trong tất cả cc_library
, cc_binary
, v.v.
các mục tiêu quy tắc bên dưới foo
và kind("source file", deps(//foo))
đánh giá tập hợp tất cả các tệp nguồn trong đóng chuyển tiếp
phần phụ thuộc của mục tiêu //foo
.
Đối số pattern thường được trích dẫn
vì nếu không có hàm này thì nhiều biểu thức chính quy, chẳng hạn như source
file
và .*_test
, không được trình phân tích cú pháp xem 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)
filter(pattern, input)
toán tử áp dụng bộ lọc cho một tập hợp các mục tiêu và loại bỏ các mục tiêu có
các nhãn (ở dạng tuyệt đối) không khớp với mẫu; nó
cho 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á tập hợp chứa tất cả các mục tiêu x sao cho
x là một phần tử của tập hợp input và
nhãn (ở dạng tuyệt đối, chẳng hạn như //foo:bar
)
trong số x có 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 đích bắt đầu bằng //
, tên này có thể được sử dụng thay thế
thành 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ả
bar
phần phụ thuộc 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
bar
cây này có tốc độ chậm và dễ gặp lỗi trong
tệp BUILD
không liên quan. Một phương án thay thế sẽ là:
filter(//bar, deps(//foo))
Thao tác này sẽ tính toán tập hợp các phần phụ thuộc //foo
và
thì sẽ chỉ lọc các mục tiêu phù hợp với mẫu được cung cấp—trong khác
các từ, nhắm mục tiêu bằng tên chứa //bar
làm chuỗi con.
Một cách sử dụng phổ biến khác của toán tử filter(pattern,
expr)
là lọc các tệp cụ thể theo
tên hoặc tiện ích. Ví dụ:
filter("\.cc$", deps(//foo))
sẽ cung cấp danh sách tất cả tệp .cc
dùng để tạo //foo
.
Lọc thuộc tính quy tắc: attr
expr ::= attr(word, word, expr)
Chiến lược phát hành đĩa đơn
attr(name, pattern, input)
toán tử á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
quy tắc, mục tiêu quy tắc không có thuộc tính name
các mục tiêu theo quy tắc hoặc quy tắc đã xác định mà trong đó giá trị thuộc tính không khớp với giá trị được cung cấp
biểu thức chính quy pattern; mã này đánh giá
cho một tập hợp con đầu vào.
Đối số đầu tiên, name là tên quy tắc
được so khớp với thuộc tính đã cung cấp
mẫu biểu thức chính quy. Đối số thứ hai,
pattern là một biểu thức chính quy trên thuộc tính
giá trị. Biểu thức attr
có giá trị là tập hợp chứa mọi mục tiêu
x sao cho x là một
phần tử của tập hợp input, là một quy tắc có thuộc tính
name và giá trị thuộc tính có chứa ký ức
kết hợp (không neo) cho biểu thức chính quy
pattern. Nếu name là một
thuộc tính và quy tắc tùy chọn không chỉ định rõ ràng rồi làm mặc định
giá trị thuộc tí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 được liên kết được chia sẻ (chẳng hạn như quy tắc cc_binary
) và có thuộc tính đó
được đặt rõ ràng thành 0 hoặc hoàn toàn không đặt nhưng giá trị mặc định là 0 (chẳng hạn như cho
cc_binary
quy tắc).
Các thuộc tính loại danh sách (chẳng hạn như srcs
, data
, v.v.) là
được chuyển đổi thành các 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 biế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 []
cho mục đích so khớp. Ví dụ:
attr("srcs", "\[\]", deps(//foo))
sẽ chọn tất cả các quy tắc trong số //foo
phần phụ thuộc 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ố //foo
phần phụ thuộc chỉ định tại
ít nhất một giá trị trong thuộc tính data
(mỗi nhãn ít nhất
dài 3 ký tự do //
và :
).
Để chọn tất cả quy tắc trong số các phần phụ thuộc //foo
có value
cụ thể trong một
thuộc tính loại danh sách, hãy sử dụng
attr("tags", "[\[ ]value[,\]]", deps(//foo))
Điều này hiệu quả vì ký tự trước value
sẽ là [
hoặc một dấu cách và
ký tự sau value
sẽ là dấu phẩy hoặc ]
.
Lọc chế độ hiển thị quy tắc: hiển thị
expr ::= visible(expr, expr)
Toán tử visible(predicate, input)
áp dụng bộ lọc cho một tập hợp các mục tiêu và loại bỏ các mục tiêu 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 dữ liệu đầu ra phải hiển thị với. Biểu thức visible đánh giá tập hợp chứa tất cả các mục tiêu x sao cho x là một thành phần của tập hợp input và cho tất 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
mà //foo
có thể phụ thuộc mà không vi phạm 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)
labels(attr_name, inputs)
toán tử 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" inch
một số quy tắc trong tập hợp inputs.
Ví dụ: labels(srcs, //foo)
trả về tập hợp
các mục tiêu xuất hiện trong thuộc tính srcs
của
quy tắc //foo
. Nếu có nhiều quy tắc
với thuộc tính srcs
trong tập hợp inputs,
hợp nhất của srcs
sẽ được trả về.
Mở rộng và lọc test_suites: testing
expr ::= tests(expr)
Toán tử tests(x)
trả về tập hợp mọi bài kiểm thử
các quy tắc trong tập hợp x, mở rộng mọi quy tắc test_suite
thành
một tập hợp các thử nghiệm riêng lẻ mà chúng tham chiếu đến và áp dụng lọc theo
tag
và size
.
Theo mặc định, việc đánh giá truy vấn
bỏ qua mọi mục tiêu không phải kiểm thử trong tất cả quy tắc test_suite
. Thông tin này có thể là
đã thay đổi thành lỗi với 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 *_test
và test_suite
trong gói foo
. Tất cả kết quả là (của
format) thành viên của gói foo
. Ngược lại,
truy vấn tests(foo:*)
sẽ trả về tất cả
riêng từng chương trình kiểm thử sẽ được bazel test
foo:*
thực thi: có thể bao gồm các lượt 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: tệp bản dựng
expr ::= buildfiles(expr)
Toán tử buildfiles(x)
trả về tập hợp
tệp xác định các gói của từng mục tiêu trong
đặt 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
. Lưu ý rằng
cũng trả về các tệp BUILD
của các gói chứa
Tệp load
.
Toán tử này thường được dùng khi xác định tệp hoặc
cần có các gói để xây dựng một mục tiêu cụ thể, thường được kết hợp với
tuỳ chọn --output package
ở bên dưới). Ví dụ:
bazel query 'buildfiles(deps(//foo))' --output package
trả về tập hợp tất cả các gói mà //foo
phụ thuộc bắc cầu.
Tệp định nghĩa gói: rbuildfile
expr ::= rbuildfiles(word, ...)
Toán tử rbuildfiles
lấy một danh sách các đoạn đườ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, sau đó rbuildfiles(foo/BUILD)
sẽ trả về
//foo:BUILD
mục tiêu. Nếu tệp foo/BUILD
có
Thêm load('//bar:file.bzl'...
trong nhóm, sau đó rbuildfiles(bar/file.bzl)
sẽ
trả về mục tiêu //foo:BUILD
cũng như mục tiêu cho bất kỳ tệp BUILD
nào khác
tải //bar:file.bzl
Phạm vi của toán tử --universe_scope
. Các tệp không tương ứng trực tiếp với tệp BUILD
và .bzl
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 chúng được đề cập rõ ràng trong tệp BUILD
. Tuy nhiên, các đường liên kết tượng trưng được tôn trọng để
nếu foo/BUILD
là liên kết tượng trưng với bar/BUILD
thì
rbuildfiles(bar/BUILD)
sẽ đưa //foo:BUILD
vào kết quả.
Về mặt đạo đức, toán tử rbuildfiles
gần như là nghịch đảo của toán tử
Toán tử buildfiles
. Tuy nhiên, sự đảo ngược đạo đức này
sẽ giữ chắc chắn hơn theo một hướng: đầu ra của rbuildfiles
cũng giống như
giá trị đầu vào của buildfiles
; trước đây sẽ chỉ chứa BUILD
mục tiêu tệp trong các gói,
và chính sách thứ hai có thể chứa các mục tiêu như vậy. Ngược lại, sự tương ứng sẽ yếu hơn. Chiến lược phát hành đĩa đơn
đầu ra của toán tử buildfiles
là mục tiêu tương ứng với tất cả các gói và .bzl
các tệp cần thiết cho một đầu vào nhất định. Tuy nhiên, dữ liệu đầu vào của toán tử rbuildfiles
là
không phải 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 để tải gói của từng mục tiêu trong
đặt x. Nói cách khác, đối với mỗi gói, giá trị này sẽ trả về giá trị
Các tệp .bzl được tham chiếu từ các tệp BUILD
của tệp đó.
Đị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à
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 Sky Query, chỉ những định dạng đầu ra tương thích với
cho phép đầu ra không theo thứ tự. Cụ thể, graph
, minrank
và
maxrank
định dạng đầu ra bị cấm.
Một số định dạng đầu ra chấp nhận các tuỳ chọn bổ sung. Tên của
mỗi tuỳ chọn đầu ra có tiền tố là định dạng đầu ra mà nó
nên --graph:factored
sẽ chỉ áp dụng
khi --output=graph
đang được sử dụng; thì việc đó không có hiệu lực nếu
sẽ 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.
Theo thứ tự kết quả
Mặc dù biểu thức truy vấn luôn tuân theo "luật của
bảo tồn thứ tự biểu đồ", trình bày các kết quả có thể
theo thứ tự phụ thuộc hoặc không theo thứ tự. Điều này không
ảnh hưởng đến các mục tiêu trong tập hợp kết quả hoặc cách tính toán truy vấn. Chỉ
ảnh hưởng đến cách kết quả được in sang stdout. Hơn nữa, các nút
tương đương về thứ tự phần phụ thuộc có thể hoặc không thể đượ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 hợp con các chức năng
cờ --order_output
và không được dùng nữa.)
Giá trị mặc định của cờ này là auto
, in kết quả từ điển học
đơn đặt hàng. Tuy nhiên, khi somepath(a,b)
được sử dụng, kết quả sẽ được in bằng
Thay vào đó, đơn đặt hàng deps
.
Khi cờ này là no
và --output
là một trong
build
, label
, label_kind
, location
, package
, proto
hoặc
xml
, các dữ liệu đầu ra sẽ được in theo thứ tự tuỳ ý. Đây là
thường là lựa chọn nhanh nhất. Tính năng này không được hỗ trợ mặc dù khi
--output
là một trong số graph
, minrank
hoặc
maxrank
: với các định dạng này, Bazel luôn in kết quả
được sắp xếp theo thứ tự hoặc thứ hạng của phần phụ thuộc.
Khi cờ này là deps
, Bazel in kết quả theo một thứ tự cấu trúc liên kết nào đó, tức là
trước tiên. Tuy nhiên, các nút không được sắp xếp theo thứ tự phần phụ thuộc
(vì không có đường dẫn từ mã này đến mã khác) có thể được in theo thứ tự bất kỳ.
Khi cờ này là full
, Bazel in các nút theo thứ tự (tổng số) hoàn toàn tất định.
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
tìm kiếm theo chiều sâu sau theo thứ tự trong đó các cạnh đi tới các nút chưa được truy cập được truyền tải trong
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 ngược thứ tự
nơi họ đượ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 các nút này khi thuật toán tất định là rất 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, mỗi mục tiêu sẽ được thể hiện như thể
viết tay bằng ngôn ngữ BUILD. Tất cả biến và lệnh gọi hàm
(chẳng hạn như hình cầu, macro) được mở rộng, điều này rất hữu ích khi xem hiệu ứng
của macro Starlark. Ngoài ra, mỗi quy tắc có hiệu lực báo cáo một
giá trị generator_name
và/hoặc generator_function
),
đặt tên của macro đã được đánh giá để tạo quy tắc có hiệu lực.
Mặc dù kết quả sử dụng cú pháp giống như tệp BUILD
, nhưng thực tế thì không
đảm bảo tạo tệp BUILD
hợp lệ.
In nhãn của từng mục tiêu
--output label
Với tùy chọn này, một tập hợp tên (hoặc nhãn) của mỗi mục tiêu
trong biểu đồ kết quả được in ra, một nhãn trên mỗi dòng, trong
thứ tự cấu trúc liên kết (trừ phi --noorder_results
được chỉ định, xem
ghi chú về thứ tự kết quả).
(Thứ tự cấu trúc liên kết là thứ tự mà trong đó biểu đồ
nút xuất hiện sớm hơn tất cả nút kế tiếp). Tất nhiên là ở đó
có nhiều thứ tự tôpô có thể có của một đồ thị (ngược lại
Postorder là một); cái nào được chọn không được chỉ định.
Khi in kết quả của truy vấn somepath
, thứ tự
trong đó các nút được in là thứ tự của đường dẫn.
Cảnh báo: trong một số trường hợp góc khuất, có thể có hai mục tiêu riêng biệt với
cùng nhãn; ví dụ: quy tắc sh_binary
và quy tắc
cả hai tệp srcs
duy nhất (ngầm ẩn) đều có thể được gọi
foo.sh
. Nếu kết quả của một truy vấn chứa cả
những mục tiêu này, thì kết quả (ở định dạng label
) sẽ xuất hiện
có chứa một bản sao. Khi sử dụng label_kind
(xem
dưới đây), thì sự khác biệt rõ ràng: hai mục tiêu này
cùng tên, nhưng một thuộc tính có loại sh_binary rule
và
loại source file
khác.
In nhãn và loại của từng mục tiêu
--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 đồ thu được, theo thứ tự cấu trúc liên kết, nhưng
thêm vào trước nhãn bằng loại mục tiêu.
In mục tiêu ở định dạng vùng đệm giao thức
--output proto
In kết quả truy vấn dưới dạng
QueryResult
vùng đệm giao thức.
In các mục tiêu ở định dạng vùng đệm giao thức được phân tách độ dài
--output streamed_proto
In
phân tách theo độ dài
luồng
Target
vùng đệm giao thức. Thông tin này rất hữu ích để (i) di chuyển
giới hạn về kích thước
vùng đệm giao thức khi có quá nhiều mục tiêu để vừa trong một vùng đệm
QueryResult
hoặc (ii) để bắt đầu xử lý trong khi Bazel vẫn đang xuất.
In mục tiêu ở định dạng văn bản proto
--output textproto
Tương tự như --output proto
, hãy in
QueryResult
vùng đệm giao thức nhưng trong
định dạng văn bản.
In các mục tiêu ở định dạng ndjson
--output streamed_jsonproto
Tương tự như --output streamed_proto
, hãy in một luồng gồm
Target
vùng đệm giao thức nhưng ở định dạng ndjson.
In nhãn của từng mục tiêu theo thứ tự xếp hạng
--output minrank --output maxrank
Giống như label
, minrank
và maxrank
định dạng đầu ra in nhãn của mỗi định dạng
vào biểu đồ kết quả, nhưng thay vì xuất hiện trong
thứ tự cấu trúc liên kết, chúng xuất hiện theo thứ tự xếp hạng, trước chúng
số thứ hạng. Thứ tự kết quả không ảnh hưởng đến những số liệu này
Cờ --[no]order_results
(xem ghi chú trên
thứ tự kết quả).
Có hai biến thể của định dạng này: thứ hạng minrank
mỗi nút theo độ dài của đường dẫn ngắn nhất từ một nút gốc đến nút đó.
"Gốc" các nút (những nút không có cạnh sắp tới) có hạng 0,
kẻ kế tiếp của chúng sẽ xếp hạng 1, v.v. (Như thường lệ, các cạnh điểm từ một
mục tiêu theo điều kiện tiên quyết: các mục tiêu mà nó phụ thuộc.)
maxrank
xếp hạng mỗi nút theo độ dài của khoảng thời gian
đường dẫn từ một nút gốc đến nút đó. Lại là "gốc" có hạng 0, tất cả các giá trị khác
các nút có thứ hạng lớn hơn thứ hạng tối đa của tất cả các nút
những người tiền nhiệm.
Tất cả các nút trong một chu kỳ được xem là có thứ hạng bằng nhau. (Hầu hết các biểu đồ
không tuần hoàn, nhưng chu kỳ vẫn xảy ra
chỉ vì tệp BUILD
chứa chu kỳ lỗi.)
Các định dạng đầu ra này rất hữu ích trong việc khám phá độ sâu của biểu đồ.
Nếu được sử dụng cho kết quả của deps(x)
, rdeps(x)
,
hoặc allpaths
, thì số thứ hạng bằng với
độ dài ngắn nhất (với minrank
) hoặc dài nhất
(với maxrank
) từ x
đến một nút trong
thứ hạng đó. Bạn có thể sử dụng maxrank
để xác định
chuỗi các bước tạo bản dựng dài nhất cần thiết để tạo mục tiêu.
Ví dụ: đồ thị bên trái cho biết kết quả ở bên phải
khi --output minrank
và --output maxrank
được chỉ định tương ứ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 |
In vị trí của mỗi mục tiêu
--output location
Tương tự 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 nó
có tiền tố là một chuỗi mô tả vị trí của mục tiêu đó như một
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 sau (chẳng hạn như Emacs
hoặc vi) cũng có thể sử dụng kết quả truy vấn để duyệt qua một loạt
khớp, cho phép sử dụng công cụ truy vấn Bazel làm
"grep for BUILD files" (grep cho tệp BUILD) của phần phụ thuộc nhận biết được 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 quy tắc,
vị trí của phần khai báo quy tắc trong tệp BUILD
được in.
Đối với các tệp nguồn, vị trí của dòng 1 của tệp thực tế là
đã in. Đối với tệp được tạo, vị trí của quy tắc
sẽ tạo ra tập lệnh được in ra. (Công cụ truy vấn không có đủ
để tìm vị trí thực tế của tệp được tạo và
trong mọi trường hợp, mã đó có thể không tồn tại nếu chưa tạo bản dựng).
In tập hợp gói
--output package
Tuỳ chọn này in tên của tất cả các gói một số mục tiêu trong tập hợp kết quả. Tên được in bằng thứ tự từ điển học; trùng lặp sẽ bị loại trừ. Trên thực tế, là một hình chiếu từ tập hợp nhãn (gói, mục tiêu) lên .
Các gói trong kho lưu trữ bên ngoài được định dạng như
@repo//foo/bar
trong khi các gói trong kho lưu trữ chính là
có định dạng là foo/bar
.
Cùng với truy vấn deps(...)
, kết quả này
có thể dùng để tìm tập hợp các gói phải được kiểm tra
nhằm xây dựng 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 khiến kết quả truy vấn được in dưới dạng lệnh chuyển hướng
biểu đồ ở đị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 tiện ích đó 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 allpaths
,
deps
hoặc rdeps
truy vấn mà kết quả
bao gồm một nhóm đường dẫn không thể dễ dàng hiển thị khi
hiển thị ở dạng tuyến tính, chẳng hạn như với --output label
.
Theo mặc định, biểu đồ hiển thị ở dạng được phân tích nhân tố. Tức là
các nút tương đương về cấu trúc được hợp nhất với nhau thành một nút duy nhất
nút có nhiều nhãn. Điều này làm cho biểu đồ nhỏ gọn hơn
và dễ đọc, vì đồ thị kết quả thông thường chứa
những mẫu hình lặp lại. Ví dụ: quy tắc java_library
có thể phụ thuộc vào hàng trăm tệp nguồn Java mà tất cả được tạo bởi
cùng genrule
; trong đồ thị đượ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. Hành vi này có thể bị vô hiệu hoá
với tuỳ chọn --nograph:factored
.
--graph:node_limit n
Tùy chọn này chỉ định độ dài tối đa của chuỗi nhãn cho
nút biểu đồ ở đầu ra. Nhãn dài hơn sẽ bị cắt bớt; Giảm 1
sẽ tắt tính năng cắt bớt. Do dạng được tính trong đó đồ thị
thường được in, nhãn nút có thể rất dài. GraphViz không thể
xử lý các nhãn vượt quá 1.024 ký tự, đây là giá trị mặc định
về tuỳ chọn này. Tuỳ chọn này không có hiệu lực trừ phi
--output=graph
đang được sử dụng.
--[no]graph:factored
Theo mặc định, biểu đồ hiển thị ở dạng có yếu tố, như được giải thích
ở trên.
Khi chỉ định --nograph:factored
, biểu đồ sẽ
được in mà không cần phân tích. Điều này giúp 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 bên
(chẳng hạn như grep). Lựa 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 trong một tệp XML biểu mẫu. Dữ liệu đầu ra sẽ bắt đầu bằng một tiêu đề XML, chẳng hạn như
<?xml version="1.0" encoding="UTF-8"?>
<query version="2">
và sau đó tiếp tục với phần tử XML cho mỗi 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 theo thứ tự được yêu cầu), và sau đó kết thúc bằng cách chấm dứt
</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' .../>
Nhưng đối với 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ả còn bao gồm rule-input
và
Phần tử rule-output
để cấu trúc liên kết của
biểu đồ phần phụ thuộc có thể được xây dựng lại mà không cần phải biết điều đó,
Ví dụ: các phần tử của thuộc tính srcs
là
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 (người 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
--noimplicit_deps
đã được chỉ định.
<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 của một mục tiêu đều chứa một name
có giá trị là nhãn của mục tiêu và
thuộc tính location
có giá trị là giá trị của mục tiêu
vị trí như được in bởi --output location
.
--[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 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 này
không được chỉ định trong tệp BUILD
hoặc giá trị mặc định là
được cung cấp rõ ràng). Tùy chọn này khiến các giá trị thuộc tính đó
đượ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, nên bạn có thể dùng
cú pháp đầy đủ cho
java.util.regex.Pattern
.
Truy vấn bằng các kho lưu trữ bên ngoài
Nếu bản dựng phụ thuộc vào quy tắc của các kho lưu trữ bên ngoài (được xác định trong
WORKSPACE) thì kết quả truy vấn sẽ bao gồm các phần phụ thuộc này. Cho
ví dụ: nếu //foo:bar
phụ thuộc vào //external:some-lib
và //external:some-lib
được liên kết với @other-repo//baz:lib
, sau đó
bazel query 'deps(//foo:bar)'
sẽ liệt kê cả @other-repo//baz:lib
và
//external:some-lib
làm phần phụ thuộc.
Bản thân các 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. Nó
có thể được truy vấn với tư cách là thành viên của gói //external
, tuy nhiên,
ví dụ:
# Querying over all members of //external returns the repository.
bazel query 'kind(http_archive, //external:*)'
//external:other-repo
# ...but the repository is not a dependency.
bazel query 'kind(http_archive, deps(//foo:bar))'
INFO: Empty results