Mô-đun Bazel

Báo cáo vấn đề Xem nguồn Nightly/3}

Mô-đun Bazel là một dự án Bazel có thể có nhiều phiên bản, mỗi phiên bản phát hành siêu dữ liệu về các mô-đun khác mà nó phụ thuộc. Thuộc tính này tương đồng với 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, gói npm, mô-đun Go hoặc kho hàng Cargo.

Một mô-đun phải có tệp MODULE.bazel ở gốc kho lưu trữ (bên cạnh tệp WORKSPACE). 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à 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 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 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 bất kỳ phần phụ thuộc nào từ Sổ đăng ký Bazel cho đến khi phát hiện thấy 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 từng mô-đun bằng một kho lưu trữ và tham khảo thông tin đăng ký một lần nữa để 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. Phổ biến nhất cho đến nay là SemVer, nhưng cũng có những dự án nổi bật sử dụng nhiều giao thức như Abseil có phiên bản 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. Có những điểm khác biệt như sau:

  • SemVer quy định rằng phầ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 để số lượng phân đoạn bất kỳ được phép.
  • Trong SemVer, mỗi phân đoạn trong phần "phát hành" chỉ được là chữ số. Trong Bazel, thuộc tính này được nới lỏng để cho phép các chữ cái và ngữ nghĩa so sánh khớp với "giá trị nhận dạng" trong phần "phát hành trước".
  • Ngoài ra, ngữ nghĩa của việc tăng phiên bản lớn, nhỏ và bản vá không được thực thi. Tuy nhiên, hãy xem mức độ tương thích để biết 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 phiên bản SemVer ab sẽ so sánh a < b khi và chỉ khi có cùng một phiên bản khi được so sánh với 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 không gian quản lý phần phụ thuộc được tạo 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

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 thuật toán Lựa 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 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 tôi là D 1.1). Đâ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 D 1.2 trở lên, chúng tôi cũng không chọn phiên bản đó. Việc sử dụng MVS tạo ra một quy trình lựa chọn phiên bản có độ chân thực caocó 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 (chẳng hạn như đối với các lỗ hổng bảo mật). Bazel sẽ báo lỗi khi chọn một phiên bản được kéo cho mô-đun. Để khắc phục lỗi này, hãy nâng cấp lên một phiên bản mới hơn, không bị kéo, hoặc sử dụng cờ --allow_yanked_versions để 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ì giả định này coi các phiên bản không tương thích ngược của một mô-đun là một mô-đun riêng. Về khía cạnh SemVer, điều đó có nghĩa là A 1.xA 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 đã được phân giải. Điều này có thể được thực hiện bằng cách mã hoá phiên bản lớn trong đường dẫn gói trong Go, nhờ đó sẽ không có bất kỳ xung đột thời gian biên dịch hoặc thời gian liên kết nào.

Tuy nhiên, Bazel không thể đưa ra các đảm bảo như vậy nên cần có số "phiên bản chính" để phát hiện các phiên bản không tương thích ngược. Số này được gọi là mức độ tương thích và được từng phiên bản mô-đun chỉ định trong lệnh module(). Với thông tin này, Bazel có thể báo lỗi khi phát hiện thấy các phiên bản của cùng một mô-đun có nhiều mức độ tương thích tồn tại trong biểu đồ phần phụ thuộc đã được phân giải.

Ghi đè

Chỉ định cơ chế ghi đè trong tệp MODULE.bazel để thay đổi hành vi của độ 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ì các lượt ghi đè của mô-đun đó sẽ bị bỏ qua.

Mỗi cơ chế ghi đè được chỉ định cho một tên mô-đun nhất định, ảnh hưởng đến tất cả phiên bản của mô-đun đó trong biểu đồ phần phụ thuộc. Mặc dù chỉ các chế độ ghi đè của mô-đun gốc mới có hiệu lực, nhưng các chế độ đó có thể dành cho các phần phụ thuộc bắc cầu mà mô-đun gốc không 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 một phần phụ thuộc vào một 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 đến từ một sổ đăng ký cụ thể, thay vì làm theo quy trình lựa chọn cơ quan đăng ký thông thường.
  • 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

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 đã đượ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 (tất cả phiên bản này phải có trong biểu đồ phần phụ thuộc trước khi phân giải) – phải tồn tại 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 khi phân giải, chỉ các phiên bản được phép của mô-đun còn lại, 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 được phép cao hơn gần nhất ở cùng mức độ tương thích. Nếu không có phiên bản nào được phép cao hơn ở cùng mức độ tương thích, Bazel sẽ hiển thị lỗi.

Ví dụ: nếu các phiên bản 1.1, 1.3, 1.5, 1.72.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à mức độ tương thích:

  • Việc ghi đè nhiều phiên bản cho phép 1.3, 1.72.0 dẫn đến việc 1.1 được nâng cấp lên 1.3, 1.5 sẽ được nâng cấp lên 1.7 và các phiên bản khác vẫn giữ nguyên.
  • Cơ chế ghi đè nhiều phiên bản cho phép 1.52.0 dẫn đến lỗi, vì 1.7 không có phiên bản cao hơn ở cùng mức độ tương thích để nâng cấp.
  • Việc ghi đè nhiều phiên bản cho phép 1.92.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 thuộc tính registry, tương tự như cơ chế 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 không yêu cầu các tệp MODULE.bazel này từ một sổ đăng ký mà yêu cầu 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ý:

Tên kho lưu trữ và phần phụ thuộc nghiêm ngặt

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). Đối với các mô-đun có cơ chế ghi đè không phải chế độ đăng ký, hãy thay thế phần version bằng chuỗi 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.

Tên rõ ràng của một kho lưu trữ sao lưu một mô-đun cho các phần phụ thuộc trực tiếp của mô-đun đó sẽ mặc định là tên mô-đun, trừ phi thuộc tính repo_name của lệnh bazel_dep có thông tin 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 nó. Điều này giúp ngăn chặn sự cố vô tình do những thay đổi về các phần phụ thuộc bắc cầu.

Tiện ích mô-đun cũng có thể đưa các kho lưu trữ bổ sung vào phạm vi hiển thị của một mô-đun.