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

Báo cáo vấn đề Xem nguồn Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

Lệnh aquery cho phép bạn truy vấn các thao tác trong biểu đồ bản dựng. Nó hoạt động trên Đồ thị mục tiêu đã định cấu hình sau phân tích và hiển thị thông tin về Các thao tác, cấu phần phần mềm và mối quan hệ của chúng.

aquery sẽ hữu ích khi bạn quan tâm đến các thuộc tính của Hành động/Hiện vật đượ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/mã gợi nhớ của các lệnh đó.

Công cụ này chấp nhận một số lựa chọn dòng lệnh. Đáng chú ý là lệnh aquery chạy trên một 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 tạo bản dựng.

Thư viện này hỗ trợ cùng một nhóm hàm cũng có sẵn cho query truyền thống nhưng siblings, buildfilestests.

Ví dụ về đầu ra aquery (không có thông tin 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:

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 cho aquery. Xem thêm thông tin chi tiết bên dưới.
  • function(...): các hàm tiêu chuẩn dưới dạng query truyền thống.
  • //target là 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:

  • inputs: lọc các thao tác theo đầu vào.
  • outputs: lọc các thao tác theo đầu ra
  • mnemonic: lọc các thao tác theo từ khoá ghi nhớ

expr ::= inputs(word, expr)

Toán tử inputs trả về các thao tác được tạo từ việc tạo expr, tên tệp đầu vào của thao tác này khớp với biểu thức chính quy do word cung cấp.

$ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'

Hàm outputsmnemonic có cú pháp tương tự nhau.

Bạn cũng có thể kết hợp các hàm để thực hiện phép toán AND. Ví dụ:

  $ bazel aquery 'mnemonic("Cpp.*", (inputs(".*cpp", inputs("foo.*", //src/target_a))))'

Lệnh trên sẽ tìm tất cả các thao tác liên quan đến việc tạo //src/target_a, có mã gợi nhớ khớp với "Cpp.*" và đầu vào khớp với các mẫu ".*cpp""foo.*".

Ví dụ về lỗi cú pháp đã 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

Tuỳ chọn bản dựng

aquery chạy trên một 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 tạo bản dựng.

Các lựa chọn về aquery

--output=(text|summary|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 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.

--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 các đầu vào và đầu ra của thao tác trong đầu ra (có thể lớn).

--include_aspects, default=true

Có đưa các thao tác do Aspect tạo vào đầu ra hay không.

--include_param_files, default=false

Đưa nội dung của các tệp tham số được dùng trong lệnh (có thể có kích thước lớn).

--include_file_write_contents, default=false

Bao gồm nội dung tệp cho thao tác actions.write() và nội dung của tệp kê khai cho thao tác 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 cần thực hiện thêm phân tích, hãy kết xuất Action Graph 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à gia tăng của Bazel. Trên mỗi phiên bản của máy chủ Bazel, Skyframe sẽ 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. Ví dụ về trường hợp sử dụng:

  1. Chạy bazel build //target_a
  2. Chạy bazel build //target_b
  3. Tệp foo.out đã được tạo.

Là người dùng Bazel, tôi muốn xác định xem foo.out có được tạo từ việc xây dựng //target_a hay //target_b hay không.

Người dùng có thể chạy bazel aquery 'outputs("foo.out", //target_a)'bazel aquery 'outputs("foo.out", //target_b)' để tìm ra thao tác chịu trách nhiệm tạo foo.out và do đó là mục tiêu. Tuy nhiên, số lượng mục tiêu khác nhau được tạo trước đó có thể lớn hơn 2, điều này gây phiền toái khi chạy nhiều lệnh aquery.

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 sẽ lấy nội dung của Biểu đồ hành động mà Skyframe lưu giữ trên phiên bản Bazel, (không bắt buộc) thực hiện lọc nội dung đó 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ó trên --output=proto--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 có trên Skyframe, bất kể mục tiêu là gì. 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 các đầu ra của aquery

Bạn có thể so sánh đầu ra của hai 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ụ để làm việc đó.

Công cụ này có trong kho lưu trữ bazelbuild/bazel. Để sử dụng, hãy sao chép kho lưu trữ này 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 sẽ trả về sự khác biệt giữa đầu ra beforeafter của aquery: những thao tác có trong một đầu ra nhưng không có trong đầu ra còn lại, những thao tác có dòng lệnh/đầu vào khác nhau trong mỗi đầu ra 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/
    ...

Tuỳ 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 hỗ trợ đầu ra truy vấn prototextproto.

--attrs=(cmdline|inputs), default=cmdline: các thuộc tính của những thao tác cần so sánh.

Tỷ lệ khung hình gốc

Bạn có thể áp dụng Aspects (Khía cạnh) chồng lên nhau. Đầu ra aquery của thao tác do các Khía cạnh này tạo ra sau đó 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 ra thao tác.

Ví dụ về tính năng Aspect-on-Aspect:

  t0
  ^
  | <- a1
  t1
  ^
  | <- a2
  t2

Giả sử ti là mục tiêu của quy tắc ri, áp dụng một Khía cạnh ai cho các phần phụ thuộc của nó.

Giả sử a2 tạo ra một thao tác X khi được áp dụng cho mục tiêu t0. Đầu ra văn bản của bazel aquery --include_aspects 'deps(//t2)' cho thao tác 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à thao tác X được tạo bởi Khía cạnh a2 được áp dụng cho a1(t0), trong đó a1(t0) là kết quả của Khía cạnh a1 được áp dụng cho mục tiêu t0.

Mỗi AspectDescriptor đều có định dạng sau:

  AspectClass([param=value,...])

AspectClass có thể là tên của lớp Aspect (đối với Aspect gốc) hoặc bzl_file%aspect_name (đối với Aspect Starlark). AspectDescriptor được sắp xếp theo thứ tự liên kết của biểu đồ phần phụ thuộc.

Liên kết với hồ sơ JSON

Mặc dù aquery cung cấp thông tin về các thao tác đang chạy trong một bản dựng (lý do chúng đang chạy, đầu vào/đầu ra của chúng), nhưng hồ sơ JSON cho chúng ta biết thời gian và thời lượng thực thi của các thao tác đó. Bạn có thể kết hợp 2 nhóm thông tin này thông qua một mẫu số chung: đầu ra chính của một hành động.

Để đưa đầu ra của các thao tác vào hồ sơ JSON, hãy tạo hồ sơ bằng --experimental_include_primary_output --noslim_profile. Hồ sơ tinh gọn không tương thích với việc đưa các đầu ra chính vào. Đầu ra chính của một thao tác được aquery đưa vào theo mặc định.

Hiện tại, chúng tôi không cung cấp một công cụ chuẩn để 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 nêu trên.

Vấn đề đã biết

Xử lý các thao tác được chia sẻ

Đôi khi, các hành động được chia sẻ giữa các mục tiêu được định cấu hình.

Trong giai đoạn thực thi, những thao tác dùng chung đó 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 khi 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ùng execPath đầu ra. Do đó, các Cấu phần phần mềm tương đương sẽ xuất hiện trùng lặp.

Bạn có thể xem danh sách các vấn đề/tính năng dự kiến 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 ngữ 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 không bao gồm 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

Nếu bạn có yêu cầu về tính năng hoặc gặp phải sự cố, vui lòng báo cáo vấn đề tại đây.