Quy tắc kho lưu trữ

Báo cáo vấn đề Xem nguồn Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Trang này trình bày cách xác định các quy tắc về kho lưu trữ và cung cấp ví dụ để bạn biết thêm chi tiết.

Kho lưu trữ bên ngoài là một cây thư mục, chứa các tệp nguồn có thể dùng trong bản dựng Bazel, được tạo theo yêu cầu bằng cách chạy quy tắc kho lưu trữ tương ứng. Bạn có thể xác định kho lưu trữ theo nhiều cách, nhưng về cơ bản, mỗi kho lưu trữ được xác định bằng cách gọi một quy tắc kho lưu trữ, giống như cách xác định mục tiêu bản dựng bằng cách gọi quy tắc bản dựng. Bạn có thể dùng các tệp này để phụ thuộc vào thư viện của bên thứ ba (chẳng hạn như thư viện đóng gói Maven) nhưng cũng có thể dùng để tạo tệp BUILD dành riêng cho máy chủ lưu trữ mà Bazel đang chạy.

Định nghĩa quy tắc của kho lưu trữ

Trong tệp .bzl, hãy sử dụng hàm repository_rule để xác định một quy tắc kho lưu trữ mới và lưu trữ quy tắc đó trong biến toàn cục. Sau khi xác định quy tắc kho lưu trữ, bạn có thể gọi quy tắc đó dưới dạng một hàm để xác định kho lưu trữ. Lệnh gọi này thường được thực hiện từ bên trong hàm triển khai tiện ích mô-đun.

Hai thành phần chính của định nghĩa quy tắc kho lưu trữ là giản đồ thuộc tính và hàm triển khai. Giản đồ thuộc tính xác định tên và loại thuộc tính được truyền đến lệnh gọi quy tắc kho lưu trữ, đồng thời hàm triển khai sẽ chạy khi cần tìm nạp kho lưu trữ.

Thuộc tính

Thuộc tính là các đối số được truyền đến lệnh gọi quy tắc kho lưu trữ. Giản đồ của các thuộc tính mà quy tắc kho lưu trữ chấp nhận được chỉ định bằng đối số attrs khi quy tắc kho lưu trữ được xác định bằng lệnh gọi đến repository_rule. Ví dụ về cách xác định thuộc tính urlsha256 dưới dạng chuỗi:

http_archive = repository_rule(
    implementation=_impl,
    attrs={
        "url": attr.string(mandatory=True),
        "sha256": attr.string(mandatory=True),
    }
)

Để truy cập vào một thuộc tính trong hàm triển khai, hãy sử dụng repository_ctx.attr.<attribute_name>:

def _impl(repository_ctx):
    url = repository_ctx.attr.url
    checksum = repository_ctx.attr.sha256

Tất cả repository_rule đều có thuộc tính name được xác định ngầm. Đây là một thuộc tính chuỗi hoạt động khá kỳ diệu: khi được chỉ định làm dữ liệu đầu vào cho lệnh gọi quy tắc kho lưu trữ, thuộc tính này sẽ lấy tên kho lưu trữ rõ ràng; nhưng khi đọc từ hàm triển khai của quy tắc kho lưu trữ bằng repository_ctx.attr.name, thuộc tính này sẽ trả về tên kho lưu trữ chuẩn.

Hàm triển khai

Mỗi quy tắc repo đòi hỏi một hàm implementation. Tệp này chứa logic thực tế của quy tắc và được thực thi nghiêm ngặt trong Giai đoạn tải.

Hàm này có đúng một tham số đầu vào là repository_ctx. Hàm này trả về None để cho biết quy tắc có thể tái tạo được với các tham số đã chỉ định hoặc một dict có một tập hợp tham số cho quy tắc đó sẽ biến quy tắc đó thành một quy tắc có thể tái tạo tạo ra cùng một kho lưu trữ. Ví dụ: đối với một quy tắc theo dõi kho lưu trữ git, điều đó có nghĩa là trả về một mã nhận dạng thay đổi cụ thể thay vì một nhánh nổi ban đầu được chỉ định.

Bạn có thể dùng tham số đầu vào repository_ctx để truy cập vào các giá trị thuộc tính và các hàm không kín (tìm tệp nhị phân, thực thi tệp nhị phân, tạo tệp trong kho lưu trữ hoặc tải tệp xuống từ Internet). Hãy xem tài liệu về API để biết thêm thông tin. Ví dụ:

def _impl(repository_ctx):
  repository_ctx.symlink(repository_ctx.attr.path, "")

local_repository = repository_rule(
    implementation=_impl,
    ...)

Hàm triển khai được thực thi khi nào?

Chức năng triển khai của một quy tắc kho lưu trữ được thực thi khi Bazel cần một mục tiêu từ kho lưu trữ đó, chẳng hạn như khi một mục tiêu khác (trong một kho lưu trữ khác) phụ thuộc vào quy tắc đó hoặc được đề cập trên dòng lệnh. Sau đó, hàm triển khai sẽ tạo kho lưu trữ trong hệ thống tệp. Quá trình này được gọi là "tìm nạp" kho lưu trữ.

Ngược lại với các mục tiêu thông thường, kho lưu trữ không nhất thiết phải được tìm nạp lại khi có thay đổi nào đó khiến kho lưu trữ khác đi. Lý do là vì có những thứ mà Bazel không thể phát hiện các thay đổi hoặc sẽ gây ra quá nhiều chi phí trên mỗi bản dựng (ví dụ: những thứ được tìm nạp từ mạng). Do đó, kho lưu trữ chỉ được tìm nạp lại nếu một trong những điều sau đây thay đổi:

  • Các thuộc tính được truyền đến lệnh gọi quy tắc kho lưu trữ.
  • Mã Starlark bao gồm việc triển khai quy tắc repo.
  • Giá trị của bất kỳ biến môi trường nào được truyền đến phương thức getenv() của repository_ctx hoặc được khai báo bằng thuộc tính environ của repository_rule. Bạn có thể cố định giá trị của các biến môi trường này trên dòng lệnh bằng cờ --repo_env.
  • Sự tồn tại, nội dung và loại của mọi đường dẫn đang được watch trong hàm triển khai của quy tắc kho lưu trữ.
    • Một số phương thức khác của repository_ctx có tham số watch, chẳng hạn như read(), execute()extract(), cũng có thể khiến các đường dẫn được theo dõi.
    • Tương tự, repository_ctx.watch_treepath.readdir có thể khiến các đường dẫn được theo dõi theo những cách khác.
  • Khi bazel fetch --force được thực thi.

Có hai tham số của repository_rule kiểm soát thời điểm truy xuất lại kho lưu trữ:

  • Nếu bạn đặt cờ configure, kho lưu trữ sẽ được tìm nạp lại trên bazel fetch --force --configure (các kho lưu trữ không phải configure sẽ không được tìm nạp lại).
  • Nếu bạn đặt cờ local, ngoài các trường hợp trên, kho lưu trữ cũng được tìm nạp lại khi máy chủ Bazel khởi động lại.

Buộc tìm nạp lại kho lưu trữ bên ngoài

Đôi khi, một kho lưu trữ bên ngoài có thể trở nên lỗi thời mà không có bất kỳ thay đổi nào đối với định nghĩa hoặc phần phụ thuộc của kho lưu trữ đó. Ví dụ: một kho lưu trữ tìm nạp nguồn có thể theo một nhánh cụ thể của kho lưu trữ bên thứ ba và các thay đổi mới có sẵn trên nhánh đó. Trong trường hợp này, bạn có thể yêu cầu bazel tìm nạp lại tất cả các kho lưu trữ bên ngoài một cách vô điều kiện bằng cách gọi bazel fetch --force --all.

Hơn nữa, một số quy tắc kho lưu trữ sẽ kiểm tra máy cục bộ và có thể trở nên lỗi thời nếu máy cục bộ được nâng cấp. Tại đây, bạn có thể yêu cầu Bazel chỉ tìm nạp lại các kho lưu trữ bên ngoài đó, trong đó định nghĩa repository_rule có tập hợp thuộc tính configure, sử dụng bazel fetch --force --configure.

Ví dụ

  • Chuỗi công cụ C++ được tự động định cấu hình: Chuỗi công cụ này sử dụng quy tắc kho lưu trữ để tự động tạo tệp cấu hình C++ cho Bazel bằng cách tìm trình biên dịch C++ cục bộ, môi trường và cờ mà trình biên dịch C++ hỗ trợ.

  • Kho lưu trữ Go sử dụng một số repository_rule để xác định danh sách các phần phụ thuộc cần thiết để sử dụng quy tắc Go.

  • Theo mặc định, rules_jvm_external tạo một kho lưu trữ bên ngoài có tên là @maven. Kho lưu trữ này sẽ tạo các mục tiêu bản dựng cho mọi cấu phần phần mềm Maven trong cây phần phụ thuộc bắc cầu.