Quy tắc kho lưu trữ

Báo cáo sự cố Xem nguồn

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

Kho lưu trữ bên ngoài là một quy tắc chỉ có thể dùng trong tệp WORKSPACE và cho phép thực hiện thao tác không khép kín ở giai đoạn tải của Bazel. Mỗi quy tắc của kho lưu trữ bên ngoài sẽ tạo một không gian làm việc riêng, với các tệp và cấu phần phần mềm BUILD riêng. Các công cụ này có thể dùng để 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 để tạo các tệp BUILD dành riêng cho máy chủ lưu trữ Bazel đang chạy.

Tạo quy tắc kho lưu trữ

Trong tệp .bzl, hãy sử dụng hàm repository_rule để tạo một quy tắc mới cho kho lưu trữ và lưu trữ quy tắc đó trong biến toàn cục.

Bạn có thể sử dụng quy tắc kho lưu trữ tuỳ chỉnh giống như quy tắc kho lưu trữ gốc. Lớp này có thuộc tính name bắt buộc và mọi mục tiêu có trong tệp bản dựng có thể được gọi là @<name>//package:target, trong đó <name> là giá trị của thuộc tính name.

Quy tắc này sẽ được tải khi bạn tạo bản dựng một cách rõ ràng hoặc nếu quy tắc là một phần phụ thuộc của bản dựng. Trong trường hợp này, Bazel sẽ thực thi hàm implementation. Hàm này mô tả cách tạo kho lưu trữ, nội dung và tệp BUILD của kho lưu trữ đó.

Thuộc tính

Thuộc tính là các đối số quy tắc được truyền dưới dạng lệnh chính tả cho đối số quy tắc attrs. Các thuộc tính và loại thuộc tính được định nghĩa sẽ được liệt kê khi bạn xác định quy tắc kho lưu trữ. Ví dụ về việc xác định các thuộc tính urlsha256 dưới dạng chuỗi:

local_repository = repository_rule(
    implementation=_impl,
    local=True,
    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 đã ngầm xác định các thuộc tính (giống như quy tắc bản dựng). Hai thuộc tính ngầm ẩn là name (cũng giống như đối với các quy tắc xây dựng) và repo_mapping. Bạn có thể truy cập vào tên của quy tắc kho lưu trữ bằng repository_ctx.name. Ý nghĩa của repo_mapping giống như đối với các quy tắc kho lưu trữ gốc local_repositorynew_local_repository.

Nếu tên thuộc tính bắt đầu bằng _ thì thuộc tính đó là riêng tư và người dùng không đặt được.

Chức năng triển khai

Mỗi quy tắc kho lưu trữ đều cần có một hàm implementation. Giao diện 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 để biểu thị rằng quy tắc có thể tái tạo dựa trên các tham số được chỉ định, hoặc một lệnh với một tập hợp các tham số cho quy tắc đó để biến quy tắc đó thành 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, tức là trả về một giá trị nhận dạng cam kết cụ thể thay vì một nhánh nổi được chỉ định ban đầu.

Bạn có thể sử 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 gián đoạ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 thư viện để biết thêm ngữ cảnh. Ví dụ:

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

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

Khi nào hàm triển khai được thực thi?

Chức năng triển khai của một 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 kho lưu trữ đó hoặc khi được đề cập trên dòng lệnh. Sau đó, hàm triển khai dự kiến 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ữ.

Khác với các mục tiêu thông thường, kho lưu trữ không nhất thiết phải tìm nạp lại khi có nội dung nào đó thay đổi và dẫn đến sự khác biệt về kho lưu trữ. Lý do là 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 đó, các kho lưu trữ chỉ được tìm nạp lại nếu một trong những điều sau thay đổi:

  • Các tham số được truyền đến phần khai báo kho lưu trữ trong tệp WORKSPACE.
  • Mã Starlark bao gồm việc triển khai kho lưu trữ.
  • Giá trị của bất kỳ biến môi trường nào đượ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ờ --action_env (nhưng cờ này sẽ vô hiệu hoá mọi hành động của bản dựng).
  • Nội dung của mọi tệp được truyền đến read(), execute() và các phương thức tương tự của repository_ctx được tham chiếu bằng một nhãn (ví dụ: //mypkg:label.txt nhưng không phải mypkg/label.txt)
  • Khi bazel sync được thực thi.

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

  • Nếu bạn đặt cờ configure, kho lưu trữ chỉ được tìm nạp lại trên bazel sync khi tham số --configure được truyền vào kho lưu trữ đó (nếu bạn không đặt thuộc tính này, lệnh này sẽ không dẫn đến quá trình tìm nạp lại)
  • Nếu cờ local được thiết lập, thì 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 hoặc khi có bất kỳ tệp nào ảnh hưởng đến việc khai báo kho lưu trữ thay đổi (ví dụ: tệp WORKSPACE hoặc tệp được tải), bất kể các thay đổi đó có dẫn đến thay đổi đối với việc khai báo kho lưu trữ hay mã của kho lưu trữ hay không.

    Các kho lưu trữ không cục bộ sẽ không được tìm nạp lại trong những trường hợp này. Lý do là vì các kho lưu trữ này được giả định là sẽ giao tiếp với mạng hoặc sẽ tốn kém.

Khởi động lại hàm triển khai

Bạn có thể bắt đầu lại hàm triển khai trong khi tìm nạp kho lưu trữ nếu một phần phụ thuộc mà kho lưu trữ đó yêu cầu bị thiếu. Trong trường hợp đó, việc thực thi hàm triển khai sẽ dừng, phần phụ thuộc bị thiếu sẽ được giải quyết và hàm sẽ được thực thi lại sau khi phần phụ thuộc đã được phân giải. Để tránh việc khởi động lại không cần thiết (tốn kém, vì việc truy cập mạng có thể phải lặp lại), các đối số nhãn được tìm nạp trước, miễn là tất cả các đối số nhãn đều có thể được phân giải vào một tệp hiện có. Xin lưu ý rằng việc phân giải đường dẫn từ một chuỗi hoặc nhãn chỉ được tạo trong quá trình thực thi hàm vẫn có thể gây ra quá trình 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ó 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ụ: kho lưu trữ tìm nạp các nguồn có thể tuân 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 vô điều kiện tất cả các kho lưu trữ bên ngoài bằng cách gọi bazel sync.

Hơn nữa, một số quy tắc 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, hãy sử dụng bazel sync --configure.

Ví dụ

  • Chuỗi công cụ được tự động định cấu hình C++: hệ thống này sử dụng quy tắc kho lưu trữ để tự động tạo các 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 cho việc sử dụng quy tắc Go.

  • rules_jvm_external tạo kho lưu trữ bên ngoài có tên là @maven theo mặc định. Kho lưu trữ này 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ụ thuộc bắc cầu.