Mô-đun Bazel là một dự án Bazel có thể có nhiều phiên bản, mỗi phiên bản Công cụ này phát hành siêu dữ liệu về các mô-đun khác mà nó phụ thuộc. Đây là tương tự như những khái niệm quen thuộc trong các hệ thống quản lý phần phụ thuộc khác, chẳng hạn như Cấu phần phần mềm Maven, một gói npm, một mô-đun Go hoặc kho hàng vận chuyển hàng hoá.
Một mô-đun phải có tệp MODULE.bazel
ở gốc kho lưu trữ (bên cạnh
WORKSPACE
). Tệp này là tệp kê khai của mô-đun, khai báo tên của mô-đun,
phiên bản, danh sách các phần phụ thuộc trực tiếp và thông tin khác. Để chơi cơ bản
ví dụ:
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "protobuf", version = "3.19.0")
Xem danh sách đầy đủ các lệnh có trong tệp MODULE.bazel
.
Để thực hiện quá trình phân giải mô-đun, Bazel bắt đầu bằng cách đọc
MODULE.bazel
rồi liên tục yêu cầu bất kỳ phần phụ thuộc nào
Tệp MODULE.bazel
từ sổ đăng ký Bazel cho đến khi
khám phá toàn bộ biểu đồ phần phụ thuộc.
Theo mặc định, Bazel sau đó chọn một phiên bản của mỗi mô-đun để sử dụng. Bazel đại diện cho mỗi mô-đun bằng một kho lưu trữ và tham khảo ý kiến đăng ký để tìm hiểu cách xác định từng kho lưu trữ.
Định dạng phiên bản
Bazel có một hệ sinh thái đa dạng và các dự án sử dụng nhiều lược đồ tạo phiên bản. Chiến lược phát hành đĩa đơn
phổ biến nhất cho đến nay là SemVer, nhưng có
cũng có các dự án nổi bật áp dụng các phương thức khác nhau như
Abseil, có
các phiên bản đều dựa trên ngày, ví dụ: 20210324.2
).
Vì lý do này, Bzlmod sử dụng một phiên bản thoải mái hơn của thông số SemVer. Chiến lược phát hành đĩa đơn bao gồm:
- SemVer quy định rằng "bản phát hành" Một phần của phiên bản phải bao gồm 3 ký tự
phân khúc:
MAJOR.MINOR.PATCH
. Trong Bazel, yêu cầu này được nới lỏng để không giới hạn số lượng phân đoạn. - Trong SemVer, mỗi phân đoạn trong "bản phát hành" chỉ được phép là chữ số. Trong Bazel, chế độ này được nới lỏng để cho phép chữ cái cũng như phép so sánh ngữ nghĩa khớp với "mã nhận dạng" trong "bản thử nghiệm" phần.
- Ngoài ra, ngữ nghĩa của việc tăng các phiên bản lớn, nhỏ và bản vá cũng không được thực thi. Tuy nhiên, hãy xem mức độ tương thích để thông tin chi tiết về cách chúng tôi biểu thị khả năng tương thích ngược.
Mọi phiên bản SemVer hợp lệ đều là phiên bản mô-đun Bazel hợp lệ. Ngoài ra, hai
Các phiên bản SemVer a
và b
so sánh a < b
khi và chỉ khi cùng một giữ nguyên khi
chúng được so sánh dưới dạng các phiên bản mô-đun Bazel.
Chọn phiên bản
Hãy xem xét vấn đề phần phụ thuộc kim cương, một yếu tố chính trong phần phụ thuộc được tạo phiên bản không gian quản lý. Giả sử bạn có biểu đồ phần phụ thuộc:
A 1.0
/ \
B 1.0 C 1.1
| |
D 1.0 D 1.1
Họ nên dùng phiên bản nào của D
? Để giải quyết câu hỏi này, Bzlmod sử dụng
Lựa chọn phiên bản tối thiểu
Thuật toán (MVS) ra mắt trong hệ thống mô-đun Go. MVS giả định rằng tất cả
các phiên bản của một mô-đun có khả năng tương thích ngược, vì vậy hãy chọn phiên bản cao nhất
do bất kỳ phần phụ thuộc nào chỉ định (trong ví dụ của chúng ta là D 1.1
). Đó là "tối thiểu"
vì D 1.1
là phiên bản sớm nhất có thể đáp ứng các yêu cầu của chúng tôi —
ngay cả khi D 1.2
hoặc phiên bản mới hơn tồn tại, chúng ta cũng không chọn biến thể đó. Khi sử dụng MVS,
quy trình lựa chọn phiên bản có độ chân thực cao và có thể tái tạo.
Phiên bản đã Yanked
Sổ đăng ký có thể khai báo một số phiên bản là được kéo nếu cần tránh các phiên bản đó
(chẳng hạn như đối với các lỗ hổng bảo mật). Bazel đưa ra lỗi khi chọn một
phiên bản được trích dẫn của một mô-đun. Để khắc phục lỗi này, hãy nâng cấp lên phiên bản mới hơn,
phiên bản không được kéo hoặc sử dụng
--allow_yanked_versions
gắn cờ để cho phép phiên bản được kéo một cách rõ ràng.
Mức độ tương thích
Trong Go, giả định của MVS về khả năng tương thích ngược có tác dụng vì nó xử lý
các phiên bản tương thích ngược của một mô-đun dưới dạng một mô-đun riêng biệt. Xét về khía cạnh
SemVer, tức là A 1.x
và A 2.x
được xem là những mô-đun riêng biệt và có thể
cùng tồn tại trong biểu đồ phần phụ thuộc đã phân giải. Điều này có thể thực hiện được bằng cách
mã hoá phiên bản lớn trong đường dẫn gói trong Go, do đó không có bất kỳ
thời gian biên dịch hoặc xung đột thời gian liên kết.
Tuy nhiên, Bazel không thể đưa ra đảm bảo như vậy, vì vậy, Bazel cần có "phiên bản chính"
số để phát hiện các phiên bản không tương thích ngược. Số này được gọi
mức độ tương thích và được chỉ định bởi từng phiên bản mô-đun trong
lệnh module()
. Với thông tin này, Bazel có thể gửi lỗi khi
phát hiện các phiên bản của cùng một mô-đun có mức độ tương thích khác nhau
tồn tại trong biểu đồ phần phụ thuộc đã phân giải.
Ghi đè
Chỉ định cơ chế ghi đè trong tệp MODULE.bazel
để thay đổi hành vi của Bazel
độ phân giải mô-đun. Chỉ chế độ ghi đè của mô-đun gốc mới có hiệu lực – nếu mô-đun là
được dùng làm phần phụ thuộc thì các lượt ghi đè sẽ bị bỏ qua.
Mỗi lượt ghi đè được chỉ định cho một tên mô-đun nhất định, ảnh hưởng đến tất cả các phiên bản trong biểu đồ phần phụ thuộc. Mặc dù chỉ có phần ghi đè của mô-đun gốc chiếm chúng có thể là các phần phụ thuộc bắc cầu mà mô-đun gốc không có phụ thuộc trực tiếp.
Ghi đè cho một phiên bản
single_version_override
phục vụ nhiều mục đích:
- Với thuộc tính
version
, bạn có thể ghim phần phụ thuộc vào một phần tử cụ thể phiên bản cụ thể, bất kể phiên bản của phần phụ thuộc nào được yêu cầu trong biểu đồ phần phụ thuộc. - Với thuộc tính
registry
, bạn có thể buộc phần phụ thuộc này bắt nguồn từ một sổ đăng ký cụ thể, thay vì tuân theo cơ quan quản lý thông thường chọn lọc. - Với các thuộc tính
patch*
, bạn có thể chỉ định một tập hợp bản vá để áp dụng cho mô-đun đã tải xuống.
Các thuộc tính này đều không bắt buộc và có thể kết hợp và so khớp với nhau.
Ghi đè nhiều phiên bản
multiple_version_override
có thể được chỉ định để cho phép nhiều phiên bản của cùng một mô-đun cùng tồn tại trong
biểu đồ phần phụ thuộc đã phân giải.
Bạn có thể chỉ định danh sách rõ ràng các phiên bản được phép cho mô-đun. Danh sách này phải đều có trong biểu đồ phần phụ thuộc trước khi phân giải – phải có sẵn một số phần phụ thuộc bắc cầu tuỳ thuộc vào từng phiên bản được phép. Sau độ phân giải, chỉ còn lại các phiên bản được cho phép của mô-đun, trong khi Bazel nâng cấp các phiên bản khác của mô-đun lên phiên bản gần nhất được cho phép cùng lúc tương thích. Nếu không có phiên bản nào được phép cao hơn có cùng khả năng tương thích cấp độ tồn tại, Bazel đưa ra lỗi.
Ví dụ: nếu các phiên bản 1.1
, 1.3
, 1.5
, 1.7
và 2.0
tồn tại trong
biểu đồ phần phụ thuộc trước khi phân giải và phiên bản chính là khả năng tương thích
cấp độ:
- Chế độ ghi đè nhiều phiên bản cho phép
1.3
,1.7
và2.0
dẫn đến kết quả1.1
đang được nâng cấp lên1.3
,1.5
đang được nâng cấp lên1.7
và các phiên bản khác các phiên bản vẫn giữ nguyên. - Việc ghi đè nhiều phiên bản cho phép
1.5
và2.0
dẫn đến lỗi, vì1.7
không có phiên bản cao hơn có cùng mức độ tương thích để nâng cấp lên. - Việc ghi đè nhiều phiên bản cho phép
1.9
và2.0
dẫn đến lỗi, vì1.9
không xuất hiện trong biểu đồ phần phụ thuộc trước khi phân giải.
Ngoài ra, người dùng cũng có thể ghi đè sổ đăng ký bằng cách sử dụng registry
tương tự như ghi đè một phiên bản.
Thông tin thay thế không phải của tổ chức quản lý tên miền
Các cơ chế ghi đè không phải hệ thống đăng ký sẽ xoá hoàn toàn mô-đun khỏi độ phân giải phiên bản. Bazel sản xuất
không yêu cầu các tệp MODULE.bazel
này từ sổ đăng ký, mà từ
chính kho lưu trữ đó.
Bazel hỗ trợ các cơ chế ghi đè sau đây không theo hệ thống đăng ký:
Xác định các kho lưu trữ không đại diện cho các mô-đun Bazel
Với bazel_dep
, bạn có thể xác định các kho lưu trữ đại diện cho các mô-đun Bazel khác.
Đôi khi, bạn cần xác định một kho lưu trữ không đại diện cho Bazel
module; ví dụ: một tệp chứa một tệp JSON thuần tuý sẽ được đọc dưới dạng dữ liệu.
Trong trường hợp này, bạn có thể sử dụng phương thức use_repo_rule
lệnh để trực tiếp xác định một kho lưu trữ
bằng cách gọi quy tắc repo. Kho lưu trữ này sẽ chỉ hiển thị với mô-đun mà nó
được xác định trong.
Về sau, việc này được triển khai bằng cơ chế tương tự như mô-đun tiện ích mở rộng, cho phép bạn xác định repos với nhiều linh hoạt hơn.
Tên kho lưu trữ và phần phụ thuộc nghiêm ngặt
Tên rõ ràng của kho lưu trữ sao lưu
mặc định là tên mô-đun, trừ phi các phần phụ thuộc trực tiếp
Thuộc tính repo_name
của bazel_dep
thì lệnh khác. Lưu ý rằng điều này nghĩa là một mô-đun chỉ có thể tìm thấy
phần phụ thuộc. Điều này giúp ngăn chặn tình trạng vỡ nhầm do những thay đổi trong
phần phụ thuộc bắc cầu.
Tên chính tắc của một kho lưu trữ sao lưu
là module_name~version
(ví dụ: bazel_skylib~1.0.3
) hoặc module_name~
(ví dụ: bazel_features~
), tuỳ thuộc vào việc có
nhiều phiên bản của mô-đun trong toàn bộ biểu đồ phần phụ thuộc (xem
multiple_version_override
).
Xin lưu ý rằng định dạng tên chính tắc không phải là API mà bạn nên phụ thuộc và
có thể thay đổi bất cứ lúc nào. Thay vì mã hoá cứng tên chuẩn,
sử dụng cách được hỗ trợ để lấy trực tiếp từ Bazel:
* Trong các tệp BUILD và .bzl
, hãy sử dụng
Label.repo_name
trên thực thể Label
được tạo từ một chuỗi nhãn được cung cấp theo tên biểu kiến của kho lưu trữ, ví dụ:
Label("@bazel_skylib").repo_name
.
* Khi tra cứu các tệp run, hãy sử dụng
$(rlocationpath ...)
hoặc một trong những thư viện runfile trong
@bazel_tools//tools/{bash,cpp,java}/runfiles
hoặc đối với bộ quy tắc rules_foo
,
trong @rules_foo//foo/runfiles
.
* Khi tương tác với Bazel qua một công cụ bên ngoài, chẳng hạn như IDE hoặc ngôn ngữ
máy chủ, hãy sử dụng lệnh bazel mod dump_repo_mapping
để lấy bản đồ từ
tên rõ ràng thành tên chuẩn cho một tập hợp kho lưu trữ nhất định.
Phần mở rộng về mô-đun cũng có thể giới thiệu các kho lưu trữ bổ sung vào phạm vi hiển thị của một mô-đun.