Mô-đun Bazel là một dự án Bazel có thể có nhiều phiên bản, mỗi phiên bản sẽ xuất bản siêu dữ liệu về các mô-đun khác mà nó phụ thuộc vào. Điều này tương tự như các 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ư hiện vậtMaven, góinpm, mô-đunGohoặc thùngCargo.
Một mô-đun phải có tệp MODULE.bazel ở gốc kho lưu trữ. Tệp này là tệp kê khai của mô-đun, khai báo tên, phiên bản, danh sách các phần phụ thuộc trực tiếp và các thông tin khác. Ví dụ cơ bản:
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 chỉ thị có trong
MODULE.bazel tệp.
Để thực hiện phân giải mô-đun, Bazel bắt đầu bằng cách đọc tệp
MODULE.bazel của mô-đun gốc, sau đó liên tục yêu cầu tệp
MODULE.bazel của mọi phần phụ thuộc từ sổ đăng ký Bazel cho đến khi
phát hiện toàn bộ biểu đồ phần phụ thuộc.
Theo mặc định, Bazel sẽ chọn một phiên bản của từng mô-đun để sử dụng. Bazel biểu thị từng mô-đun bằng một kho lưu trữ và tham khảo lại sổ đă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 đồ kiểm soát phiên bản. SemVer
Vì lý do này, Bazel áp dụng một phiên bản thoải mái hơn của thông số kỹ thuật SemVer. Các điểm khác biệt bao gồm:
- SemVer quy định rằng phần "bản phát hành" của phiên bản phải bao gồm 3 phân đoạn:
MAJOR.MINOR.PATCH. Trong Bazel, yêu cầu này được nới lỏng để cho phép mọi số phân đoạn. - Trong SemVer, mỗi phân đoạn trong phần "bản phát hành" chỉ được chứa các chữ số. Trong Bazel, yêu cầu này được nới lỏng để cho phép cả chữ cái và ngữ nghĩa so sánh khớp với "mã nhận dạng" trong phần "bản phát hành trước".
- Ngoài ra, ngữ nghĩa của các phiên bản chính, phụ và bản vá tăng không được thực thi.
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
phiên bản SemVer a và b so sánh a < b nếu và chỉ khi điều tương tự xảy ra khi
chúng được so sánh dưới dạng phiên bản mô-đun Bazel.
Cuối cùng, để tìm hiểu thêm về việc kiểm soát phiên bản mô-đun, hãy xem phần MODULE.bazel
Câu hỏi thường gặp.
Chọn phiên bản
Hãy xem xét vấn đề về phần phụ thuộc hình kim cương, một vấn đề thường gặp trong không gian quản lý phần phụ thuộc theo phiên bản. 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
Bạn nên sử dụng phiên bản D nào? Để giải quyết câu hỏi này, Bazel sử dụng thuật toán
Chọn phiên bản tối thiểu
(MVS) được giới thiệu trong hệ thống mô-đun Go. MVS giả định rằng tất cả các phiên bản mới của một mô-đun đều tương thích ngược và do đó, chọn phiên bản cao nhất do bất kỳ phần phụ thuộc nào chỉ định (D 1.1 trong ví dụ của chúng tôi). Thuật toán này được gọi 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 có D 1.2 hoặc phiên bản mới hơn, chúng tôi cũng không chọn. Việc sử dụng MVS sẽ tạo ra một quy trình chọn phiên bản độ trung thực cao và có thể tái tạo.
Các phiên bản bị loại bỏ
Sổ đăng ký có thể khai báo một số phiên bản là bị loại bỏ nếu bạn nên tránh sử dụng các phiên bản đó (chẳng hạn như đối với các lỗ hổng bảo mật). Bazel sẽ gửi lỗi khi chọn một phiên bản bị loại bỏ của 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,
không bị loại bỏ hoặc sử dụng cờ
--allow_yanked_versions
để cho phép phiên bản bị loại bỏ một cách rõ ràng.
Chế độ ghi đè
Chỉ định chế độ ghi đè trong tệp MODULE.bazel để thay đổi hành vi của quá trình phân giải mô-đun Bazel. Chỉ chế độ ghi đè của mô-đun gốc mới có hiệu lực – nếu một mô-đun được dùng làm phần phụ thuộc, thì chế độ ghi đè của mô-đun đó sẽ bị bỏ qua.
Mỗi chế độ 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 của mô-đun đó trong biểu đồ phần phụ thuộc. Mặc dù chỉ chế độ ghi đè của mô-đun gốc mới có hiệu lực, nhưng chúng có thể dành cho các phần phụ thuộc chuyển đổi mà mô-đun gốc không trực tiếp phụ thuộc vào.
Ghi đè một phiên bản
The single_version_override
phục vụ nhiều mục đích:
- Với thuộc tính
version, bạn có thể ghim một phần phụ thuộc vào một phiên bản cụ thể, bất kể phiên bản nào của phần phụ thuộc đượ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 đến từ một sổ đăng ký cụ thể, thay vì tuân theo quy trình chọn sổ đăng ký thông thường registry. - Với các thuộc tính
patch*, bạn có thể chỉ định một tập hợp các bản vá để áp dụng cho mô-đun đã tải xuống.
Tất cả các thuộc tính này đều không bắt buộc và có thể kết hợp với nhau.
Ghi đè nhiều phiên bản
Bạn có thể chỉ định multiple_version_override
để 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.
Nếu có nhiều phiên bản của cùng một mô-đun còn lại trong biểu đồ phần phụ thuộc, Bazel sẽ chọn phiên bản cao hơn gần nhất được phép cho mỗi phần phụ thuộc.
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:
- Chế độ ghi đè nhiều phiên bản cho phép
1.3,1.7và2.0dẫn đến việc1.1được nâng cấp lên1.3,1.5được nâng cấp lên1.7và các phiên bản khác vẫn giữ nguyên. - Chế độ ghi đè nhiều phiên bản cho phép
1.9và2.0dẫn đến lỗi, vì1.9không có 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 thuộc tính registry, tương tự như chế độ ghi đè một phiên bản.
Ghi đè không phải sổ đăng ký
Chế độ ghi đè không phải sổ đăng ký sẽ xoá hoàn toàn một mô-đun khỏi quá trình phân giải phiên bản. Bazel 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 chế độ ghi đè không phải sổ đăng ký sau:
Xin lưu ý rằng việc đặt giá trị phiên bản trong tệp lưu trữ nguồn MODULE.bazel có thể gây ra nhược điểm khi mô-đun đang bị ghi đè bằng chế độ ghi đè không phải sổ đăng ký. Để
tìm hiểu thêm về vấn đề này, hãy xem phần MODULE.bazel
Câu hỏi thường gặp.
Xác định các kho lưu trữ không đại diện cho 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 mô-đun Bazel; ví dụ: một kho lưu trữ chứa tệp JSON thuần tuý để đọc dưới dạng dữ liệu.
Trong trường hợp này, bạn có thể sử dụng use_repo_rule
chỉ thị để trực tiếp xác định một kho lưu trữ
bằng cách gọi một quy tắc kho lưu trữ. Kho lưu trữ này sẽ chỉ hiển thị với mô-đun mà nó được xác định.
Trong trường hợp này, cơ chế này được triển khai bằng cơ chế tương tự như tiện ích mô-đun, cho phép bạn xác định các kho lưu trữ một cách linh hoạt hơn.
Tên kho lưu trữ và phần phụ thuộc nghiêm ngặt
Tên hiển thị của một kho lưu trữ sao lưu mô-đun cho các phần phụ thuộc trực tiếp của mô-đun đó mặc định là tên mô-đun, trừ phi thuộc tính repo_name của chỉ thị bazel_dep cho biết điều khác. Xin lưu ý rằng điều này có nghĩa là một mô-đun chỉ có thể tìm thấy các phần phụ thuộc trực tiếp của mô-đun đó. Điều này giúp ngăn chặn các sự cố vô tình do các thay đổi trong phần phụ thuộc chuyển đổi.
Tên chính tắc của một kho lưu trữ sao lưu mô-đun 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 hay không (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ào và có thể thay đổi bất cứ lúc nào. Thay vì mã hoá cứng tên chính tắc, hãy sử dụng một cách được hỗ trợ để lấy tên đó trực tiếp từ Bazel:
- Trong các tệp BUILD và
.bzl, hãy sử dụngLabel.repo_nametrên một thực thểLabelđược tạo từ chuỗi nhãn do tên hiển thị của kho lưu trữ cung cấp, ví dụ:Label("@bazel_skylib").repo_name. - Khi tra cứu tệp thực thi, hãy sử dụng
$(rlocationpath ...)hoặc một trong các thư viện tệp thực thi trong@bazel_tools//tools/{bash,cpp,java}/runfileshoặc đối với một bộ quy tắcrules_foo, trong@rules_foo//foo/runfiles. - Khi tương tác với Bazel từ một công cụ bên ngoài như IDE hoặc máy chủ ngôn ngữ, hãy sử dụng lệnh
bazel mod dump_repo_mappingđể lấy mối liên kết từ tên hiển thị đến tên chính tắc cho một tập hợp kho lưu trữ nhất định.
Tiện ích mô-đun cũng có thể đưa thêm các kho lưu trữ vào phạm vi hiển thị của mô-đun.