Lệnh aquery cho phép bạn truy vấn các hành động trong biểu đồ bản dựng.
Lệnh này hoạt động trên Biểu đồ mục tiêu đã định cấu hình 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ế được chạy
và đầu vào/đầu ra/từ viết tắt của chúng.
Công cụ này chấp nhận một số lựa chọn dòng lệnh options. Đáng chú ý là lệnh aquery chạy trên bản dựng Bazel thông thường và kế thừa tập hợp các lựa chọn có sẵn trong quá trình bản dựng.
Lệnh này hỗ trợ cùng một tập hợp hàm cũng có sẵn cho truyền thống
query nhưng siblings, buildfiles và
tests.
Ví dụ về kết quả aquery (không có thông tin chi tiết cụ thể):
$ bazel aquery 'deps(//some:label)' action 'Writing file some_file_name' Mnemonic: ... Target: ... Configuration: ... ActionKey: ... Inputs: [...] Outputs: [...]
Cú pháp cơ bản
Sau đây là một ví dụ đơn giản về cú pháp cho aquery như sau:
bazel aquery "aquery_function(function(//target))"
Biểu thức truy vấn (trong dấu ngoặc kép) bao gồm những nội dung sau:
aquery_function(...): các hàm dành riêng choaquery. Xem thêm thông tin chi tiết bên dưới.function(...): các hàm tiêu chuẩn functions như truyền thốngquery.//targetlà nhãn cho mục tiêu mà bạn quan tâm.
# aquery examples:
# Get the action graph generated while building //src/target_a
$ bazel aquery '//src/target_a'
# Get the action graph generated while building all dependencies of //src/target_a
$ bazel aquery 'deps(//src/target_a)'
# Get the action graph generated while building all dependencies of //src/target_a
# whose inputs filenames match the regex ".*cpp".
$ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'
Sử dụng các hàm aquery
Có 3 hàm aquery functions:
inputs: lọc các hành động theo đầu vào.outputs: lọc các hành động theo đầu ramnemonic: lọc các hành động theo từ viết tắt
expr ::= inputs(word, expr)
Toán tử inputs trả về các hành động được tạo từ việc xây dựng expr,
có tên tệp đầu vào khớp với biểu thức chính quy do word cung cấp.
$ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'
Các hàm outputs và mnemonic có cú pháp tương tự.
Bạn cũng có thể kết hợp các hàm để thực hiện thao tác AND. Ví dụ:
$ bazel aquery 'mnemonic("Cpp.*", (inputs(".*cpp", inputs("foo.*", //src/target_a))))'
Lệnh trên sẽ tìm thấy tất cả các hành động liên quan đến việc xây dựng //src/target_a,
có từ viết tắt khớp với "Cpp.*" và đầu vào khớp với các mẫu
".*cpp" và "foo.*".
Ví dụ về lỗi cú pháp được tạo:
$ bazel aquery 'deps(inputs(".*cpp", //src/target_a))'
ERROR: aquery filter functions (inputs, outputs, mnemonic) produce actions,
and therefore can't be the input of other function types: deps
deps(inputs(".*cpp", //src/target_a))
Tùy chọn
Lựa chọn bản dựng
aquery chạy trên bản dựng Bazel thông thường và do đó kế thừa tập hợp các
lựa chọn
có sẵn trong quá trình bản dựng.
Lựa chọn Aquery
--output=(text|summary|commands|proto|jsonproto|textproto), default=text
Định dạng đầu ra mặc định (text) là định dạng mà con người có thể đọc được,
hãy sử dụng proto, textproto hoặc jsonproto cho định dạng mà máy có thể đọc được.
Thông báo proto là analysis.ActionGraphContainer.
Định dạng đầu ra commands in danh sách các lệnh bản dựng với
một lệnh trên mỗi dòng.
Nói chung, đừng phụ thuộc vào thứ tự đầu ra. Để biết thêm thông tin, xem hợp đồng đặt hàng truy vấn cốt lõi.
--include_commandline, default=true
Bao gồm nội dung của các dòng lệnh hành động trong đầu ra (có thể lớn).
--include_artifacts, default=true
Bao gồm tên của đầu vào và đầu ra hành động trong đầu ra (có thể lớn).
--include_aspects, default=true
Có đưa các hành động do Khía cạnh tạo vào đầu ra hay không.
--include_param_files, default=false
Bao gồm nội dung của các tệp tham số được dùng trong lệnh (có thể lớn).
--include_file_write_contents, default=false
Bao gồm nội dung tệp cho hành động actions.write() và nội dung của
tệp kê khai cho hành động SourceSymlinkManifest. Nội dung tệp được
trả về trong trường file_contents bằng --output=xxxproto.
Với --output=text, đầu ra có
FileWriteContents: [<base64-encoded file contents>]
dòng
--skyframe_state, default=false
Không thực hiện phân tích bổ sung, hãy kết xuất Biểu đồ hành động từ Skyframe.
Các công cụ và tính năng khác
Truy vấn theo trạng thái của Skyframe
Skyframe là mô hình đánh giá và tăng dần của Bazel. Trên mỗi phiên bản của máy chủ Bazel, Skyframe lưu trữ biểu đồ phần phụ thuộc được tạo từ các lần chạy trước của giai đoạn Phân tích.
Trong một số trường hợp, bạn nên truy vấn Biểu đồ hành động trên Skyframe. Sau đây là một ví dụ về trường hợp sử dụng:
- Chạy
bazel build //target_a - Chạy
bazel build //target_b - Tệp
foo.outđã được tạo.
Là người dùng Bazel, tôi muốn xác định xem foo.out được tạo từ việc xây dựng
//target_a hay //target_b.
Bạn có thể chạy bazel aquery 'outputs("foo.out", //target_a)' và
bazel aquery 'outputs("foo.out", //target_b)' để tìm ra hành động chịu trách nhiệm
tạo foo.out và lần lượt là mục tiêu. Tuy nhiên, số lượng mục tiêu khác nhau
được xây dựng trước đó có thể lớn hơn 2, khiến việc chạy nhiều aquery
lệnh trở nên phiền phức.
Ngoài ra, bạn có thể sử dụng cờ --skyframe_state:
# List all actions on Skyframe's action graph
$ bazel aquery --output=proto --skyframe_state
# or
# List all actions on Skyframe's action graph, whose output matches "foo.out"
$ bazel aquery --output=proto --skyframe_state 'outputs("foo.out")'
Ở chế độ --skyframe_state, aquery lấy nội dung của Biểu đồ hành động
mà Skyframe giữ trên phiên bản Bazel, (tuỳ chọn) thực hiện lọc trên đó và
xuất nội dung mà không cần chạy lại giai đoạn phân tích.
Các điểm cần cân nhắc đặc biệt
Định dạng đầu ra
--skyframe_state hiện chỉ có sẵn cho --output=proto
và --output=textproto
Không đưa nhãn mục tiêu vào biểu thức truy vấn
Hiện tại, --skyframe_state truy vấn toàn bộ biểu đồ hành động tồn tại trên Skyframe,
bất kể mục tiêu. Việc chỉ định nhãn mục tiêu trong truy vấn cùng với
--skyframe_state được coi là lỗi cú pháp:
# WRONG: Target Included
$ bazel aquery --output=proto --skyframe_state **//target_a**
ERROR: Error while parsing '//target_a)': Specifying build target(s) [//target_a] with --skyframe_state is currently not supported.
# WRONG: Target Included
$ bazel aquery --output=proto --skyframe_state 'inputs(".*.java", **//target_a**)'
ERROR: Error while parsing '//target_a)': Specifying build target(s) [//target_a] with --skyframe_state is currently not supported.
# CORRECT: Without Target
$ bazel aquery --output=proto --skyframe_state
$ bazel aquery --output=proto --skyframe_state 'inputs(".*.java")'
So sánh kết quả aquery
Bạn có thể so sánh kết quả của 2 lệnh gọi aquery khác nhau bằng công cụ aquery_differ.
Ví dụ: khi bạn thực hiện một số thay đổi đối với định nghĩa quy tắc và muốn xác minh rằng các
dòng lệnh đang chạy không thay đổi. aquery_differ là công cụ dành cho việc đó.
Công cụ này có trong kho lưu trữ bazelbuild/bazel. Để sử dụng công cụ này, hãy sao chép kho lưu trữ vào máy cục bộ. Ví dụ về cách sử dụng:
$ bazel run //tools/aquery_differ -- \ --before=/path/to/before.proto \ --after=/path/to/after.proto \ --input_type=proto \ --attrs=cmdline \ --attrs=inputs
Lệnh trên trả về sự khác biệt giữa kết quả aquery before và after:
những hành động có trong một kết quả nhưng không có trong kết quả còn lại, những hành động có
dòng lệnh/đầu vào khác nhau trong mỗi kết quả aquery, ...). Kết quả của việc chạy lệnh trên sẽ là:
Aquery output 'after' change contains an action that generates the following outputs that aquery output 'before' change doesn't:
...
/list of output files/
...
[cmdline]
Difference in the action that generates the following output(s):
/path/to/abc.out
--- /path/to/before.proto
+++ /path/to/after.proto
@@ -1,3 +1,3 @@
...
/cmdline diff, in unified diff format/
...
Lựa chọn lệnh
--before, --after: Các tệp đầu ra aquery cần so sánh
--input_type=(proto|text_proto), default=proto: định dạng của các tệp
đầu vào. Chúng tôi cung cấp tính năng hỗ trợ cho đầu ra aquery proto và textproto.
--attrs=(cmdline|inputs), default=cmdline: các thuộc tính của hành động
cần so sánh.
Khía cạnh trên khía cạnh
Bạn có thể áp dụng các Khía cạnh chồng lên nhau. Kết quả aquery của hành động do các Khía cạnh này tạo sẽ bao gồm Đường dẫn khía cạnh, là chuỗi Khía cạnh được áp dụng cho mục tiêu đã tạo hành động.
Ví dụ về Khía cạnh trên khía cạnh:
t0 ^ | <- a1 t1 ^ | <- a2 t2
Giả sử ti là mục tiêu của quy tắc ri, áp dụng Khía cạnh ai cho các phần phụ thuộc của nó.
Giả sử a2 tạo hành động X khi áp dụng cho mục tiêu t0. Kết quả văn bản của
bazel aquery --include_aspects 'deps(//t2)' cho hành động X sẽ là:
action ...
Mnemonic: ...
Target: //my_pkg:t0
Configuration: ...
AspectDescriptors: [//my_pkg:rule.bzl%**a2**(foo=...)
-> //my_pkg:rule.bzl%**a1**(bar=...)]
...
Điều này có nghĩa là hành động X được tạo bởi Khía cạnh a2 áp dụng cho
a1(t0), trong đó a1(t0) là kết quả của Khía cạnh a1 áp dụng
cho mục tiêu t0.
Mỗi AspectDescriptor có định dạng sau:
AspectClass([param=value,...])
AspectClass có thể là tên của lớp Khía cạnh (đối với các Khía cạnh gốc) hoặc
bzl_file%aspect_name (đối với các Khía cạnh Starlark). AspectDescriptor được
sắp xếp theo thứ tự tô pô của
biểu đồ phần phụ thuộc.
Liên kết với hồ sơ JSON
Trong khi aquery cung cấp thông tin về các hành động đang chạy trong bản dựng (lý do chúng đang chạy, đầu vào/đầu ra của chúng), thì hồ sơ JSON cho chúng ta biết thời gian và thời lượng thực thi của chúng. Bạn có thể kết hợp 2 tập hợp thông tin này thông qua một mẫu số chung: đầu ra chính của hành động.
Để đưa đầu ra của các hành động vào hồ sơ JSON, hãy tạo hồ sơ bằng
--experimental_include_primary_output --noslim_profile.
Hồ sơ rút gọn không tương thích với việc đưa đầu ra chính vào. Theo mặc định, đầu ra chính của hành động
được aquery đưa vào.
Hiện tại, chúng tôi không cung cấp công cụ chính tắc để kết hợp 2 nguồn dữ liệu này, nhưng bạn có thể tạo tập lệnh của riêng mình bằng thông tin ở trên.
Vấn đề đã biết
Xử lý các hành động được chia sẻ
Đôi khi, các hành động được chia sẻ giữa các mục tiêu đã định cấu hình.
Trong giai đoạn thực thi, những hành động được chia sẻ đó chỉ được coi là một và chỉ được thực thi một lần.
Tuy nhiên, aquery hoạt động trên biểu đồ hành động trước khi thực thi, sau phân tích và do đó coi những hành động này
như các hành động riêng biệt có Cấu phần phần mềm đầu ra có execPath giống hệt nhau. Do đó,
các Cấu phần phần mềm tương đương xuất hiện dưới dạng trùng lặp.
Bạn có thể tìm thấy danh sách các vấn đề/tính năng đã lên kế hoạch của aquery trên GitHub.
Câu hỏi thường gặp
ActionKey vẫn giữ nguyên ngay cả khi nội dung của tệp đầu vào thay đổi.
Trong bối cảnh của aquery, ActionKey đề cập đến String nhận được từ
ActionAnalysisMetadata#getKey:
Returns a string encoding all of the significant behaviour of this Action that might affect the
output. The general contract of `getKey` is this: if the work to be performed by the
execution of this action changes, the key must change.
...
Examples of changes that should affect the key are:
- Changes to the BUILD file that materially affect the rule which gave rise to this Action.
- Changes to the command-line options, environment, or other global configuration resources
which affect the behaviour of this kind of Action (other than changes to the names of the
input/output files, which are handled externally).
- An upgrade to the build tools which changes the program logic of this kind of Action
(typically this is achieved by incorporating a UUID into the key, which is changed each
time the program logic of this action changes).
Note the following exception: for actions that discover inputs, the key must change if any
input names change or else action validation may falsely validate.
Điều này loại trừ các thay đổi đối với nội dung của tệp đầu vào và không được nhầm lẫn với RemoteCacheClient#ActionKey.
Nội dung cập nhật
Đối với mọi vấn đề/yêu cầu về tính năng, vui lòng báo cáo vấn đề tại đây.