Bạn có thể xem toàn bộ thông số kỹ thuật của Giao thức sự kiện bản dựng trong giao thức định nghĩa vùng đệm. Tuy nhiên, việc hình thành trực giác có thể cũng rất hữu ích trước khi xem thông số kỹ thuật.
Hãy cân nhắc một không gian làm việc Bazel đơn giản bao gồm 2 tập lệnh shell trống
foo.sh
và foo_test.sh
và tệp BUILD
sau:
sh_library(
name = "foo_lib",
srcs = ["foo.sh"],
)
sh_test(
name = "foo_test",
srcs = ["foo_test.sh"],
deps = [":foo_lib"],
)
Khi chạy bazel test ...
trên dự án này, biểu đồ bản dựng của
các sự kiện tạo sẽ giống như biểu đồ bên dưới. Các mũi tên biểu thị
mối quan hệ cha mẹ và con nêu trên. Xin lưu ý rằng một số sự kiện bản dựng và hầu hết các trường đã bị bỏ qua để đảm bảo tính ngắn gọn.
Hình 1. Biểu đồ BEP.
Ban đầu, một sự kiện BuildStarted
sẽ được phát hành. Sự kiện này cho chúng tôi biết rằng
Bản dựng đã được gọi thông qua lệnh bazel test
và thông báo các sự kiện con:
OptionsParsed
WorkspaceStatus
CommandLine
UnstructuredCommandLine
BuildMetadata
BuildFinished
PatternExpanded
Progress
Ba sự kiện đầu tiên cung cấp thông tin về cách Bazel được gọi.
Sự kiện tạo bản dựng PatternExpanded
cung cấp thông tin chi tiết
mà cụ thể nhắm mục tiêu mẫu ...
được mở rộng thành:
//foo:foo_lib
và //foo:foo_test
. Cách thực hiện là khai báo hai sự kiện TargetConfigured
làm con. Xin lưu ý rằng sự kiện TargetConfigured
khai báo sự kiện Configuration
là sự kiện con, mặc dù Configuration
đã được đăng trước sự kiện TargetConfigured
.
Ngoài mối quan hệ mẹ và con, các sự kiện cũng có thể tham chiếu đến nhau
bằng cách sử dụng mã nhận dạng sự kiện bản dựng. Ví dụ: trong biểu đồ trên, sự kiện TargetComplete
tham chiếu đến sự kiện NamedSetOfFiles
trong trường fileSets
.
Tạo các sự kiện tham chiếu đến tệp thường không nhúng tệp
tên và đường dẫn trong sự kiện. Thay vào đó, các tệp này chứa giá trị nhận dạng sự kiện bản dựng của một sự kiện NamedSetOfFiles
, sau đó sẽ chứa tên tệp và đường dẫn thực tế. Sự kiện NamedSetOfFiles
cho phép báo cáo một tập hợp tệp một lần và nhiều mục tiêu tham chiếu đến tập hợp tệp đó. Cấu trúc này là cần thiết vì nếu không, trong một số trường hợp, kích thước đầu ra của Giao thức sự kiện bản dựng sẽ tăng theo phương trình bậc hai theo số lượng tệp. Sự kiện NamedSetOfFiles
cũng có thể không nhúng tất cả các tệp, mà thay vào đó tham chiếu đến các sự kiện NamedSetOfFiles
khác thông qua giá trị nhận dạng sự kiện bản dựng.
Dưới đây là một bản sao của sự kiện TargetComplete
cho //foo:foo_lib
từ biểu đồ trên, được in trong cách biểu diễn JSON của vùng đệm giao thức.
Giá trị nhận dạng sự kiện bản dựng chứa mục tiêu dưới dạng một chuỗi mờ và tham chiếu đến
sự kiện Configuration
bằng cách sử dụng giá trị nhận dạng sự kiện bản dựng. Sự kiện này không thông báo bất kỳ sự kiện con nào. Trọng tải chứa thông tin về việc liệu mục tiêu có được tạo thành công hay không, tập hợp tệp đầu ra và loại mục tiêu được tạo.
{
"id": {
"targetCompleted": {
"label": "//foo:foo_lib",
"configuration": {
"id": "544e39a7f0abdb3efdd29d675a48bc6a"
}
}
},
"completed": {
"success": true,
"outputGroup": [{
"name": "default",
"fileSets": [{
"id": "0"
}]
}],
"targetKind": "sh_library rule"
}
}
Kết quả về tỷ lệ khung hình trong BEP
Các bản dựng thông thường sẽ đánh giá các hành động được liên kết với (target, configuration)
cặp. Khi toà nhà bật các phương diện, Bazel
đánh giá thêm các mục tiêu được liên kết với bộ ba (target, configuration,
aspect)
đối với mỗi mục tiêu chịu ảnh hưởng của một khía cạnh cụ thể đã bật.
Hiện đã có kết quả đánh giá cho các khía cạnh trong BEP mặc dù không có
loại sự kiện theo từng khía cạnh cụ thể. Đối với mỗi cặp (target, configuration)
có một khía cạnh áp dụng, Bazel sẽ phát hành thêm một sự kiện TargetConfigured
và TargetComplete
mang lại kết quả từ việc áp dụng khía cạnh đó cho mục tiêu. Ví dụ: nếu //:foo_lib
được tạo bằng
--aspects=aspects/myaspect.bzl%custom_aspect
, sự kiện này cũng sẽ xuất hiện trong
BEP:
{
"id": {
"targetCompleted": {
"label": "//foo:foo_lib",
"configuration": {
"id": "544e39a7f0abdb3efdd29d675a48bc6a"
},
"aspect": "aspects/myaspect.bzl%custom_aspect"
}
},
"completed": {
"success": true,
"outputGroup": [{
"name": "default",
"fileSets": [{
"id": "1"
}]
}]
}
}
Đang tiêu thụ NamedSetOfFiles
Xác định các cấu phần phần mềm do một mục tiêu (hoặc khía cạnh) nhất định tạo ra là một trường hợp sử dụng BEP phổ biến mà bạn có thể thực hiện một cách hiệu quả bằng một số biện pháp chuẩn bị. Phần này thảo luận về cấu trúc lồng nhau, được chia sẻ do sự kiện NamedSetOfFiles
cung cấp, khớp với cấu trúc của Depset Starlark.
Người dùng phải cẩn thận tránh các thuật toán bậc hai khi xử lý các sự kiện NamedSetOfFiles
vì các bản dựng lớn có thể chứa hàng chục nghìn sự kiện như vậy, đòi hỏi hàng trăm triệu thao tác trong một lượt truy cập có độ phức tạp bậc hai.
Hình 2. Biểu đồ BEP của NamedSetOfFiles
.
Sự kiện NamedSetOfFiles
luôn xuất hiện trong luồng BEP trước
Sự kiện TargetComplete
hoặc NamedSetOfFiles
tham chiếu đến sự kiện đó. Đây là
giá trị nghịch đảo của giá trị "parent-child" mối quan hệ sự kiện, trong đó tất cả trừ sự kiện đầu tiên
xuất hiện sau ít nhất một sự kiện công bố sự kiện đó. Sự kiện NamedSetOfFiles
được thông báo bằng sự kiện Progress
không có ngữ nghĩa.
Với những ràng buộc về thứ tự và chia sẻ này, người tiêu dùng thông thường phải lưu tất cả
NamedSetOfFiles
sự kiện cho đến khi luồng BEP hết. JSON sau
luồng sự kiện và mã Python minh hoạ cách điền bản đồ từ
nhắm mục tiêu/trên cấu phần phần mềm đã tạo ở chế độ "mặc định" nhóm đầu ra và cách
xử lý dữ liệu đầu ra cho một tập hợp con các mục tiêu/khía cạnh đã tạo:
named_sets = {} # type: dict[str, NamedSetOfFiles]
outputs = {} # type: dict[str, dict[str, set[str]]]
for event in stream:
kind = event.id.WhichOneof("id")
if kind == "named_set":
named_sets[event.id.named_set.id] = event.named_set_of_files
elif kind == "target_completed":
tc = event.id.target_completed
target_id = (tc.label, tc.configuration.id, tc.aspect)
outputs[target_id] = {}
for group in event.completed.output_group:
outputs[target_id][group.name] = {fs.id for fs in group.file_sets}
for result_id in relevant_subset(outputs.keys()):
visit = outputs[result_id].get("default", [])
seen_sets = set(visit)
while visit:
set_name = visit.pop()
s = named_sets[set_name]
for f in s.files:
process_file(result_id, f)
for fs in s.file_sets:
if fs.id not in seen_sets:
visit.add(fs.id)
seen_sets.add(fs.id)