Triển khai quy tắc

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

Trang này dành cho những người viết quy tắc đang dự định cung cấp quy tắc của họ cho người khác.

Quy tắc lưu trữ và đặt tên

Các quy tắc mới sẽ nằm trong kho lưu trữ GitHub riêng trong tổ chức của bạn. Liên hệ với danh sách gửi thư của bazel-dev nếu bạn cảm thấy các quy tắc của mình thuộc về tổ chức bazelbuild.

Tên kho lưu trữ cho các quy tắc Bazel được chuẩn hoá theo định dạng sau: $ORGANIZATION/rules_$NAME. Xem ví dụ trên GitHub. Để đảm bảo tính nhất quán, bạn phải sử dụng cùng một định dạng này khi xuất bản các quy tắc Bazel của mình.

Hãy nhớ sử dụng phần mô tả mang tính mô tả về kho lưu trữ GitHub và tiêu đề README.md, ví dụ:

  • Tên kho lưu trữ: bazelbuild/rules_go
  • Nội dung mô tả về kho lưu trữ: Quy tắc Go cho Bazel
  • Thẻ kho lưu trữ: golang, bazel
  • Tiêu đề README.md: Bắt đầu quy tắc cho Bazel (lưu ý đường liên kết đến https://bazel.build để hướng dẫn những người dùng chưa biết về Bazel đến đúng nơi)

Bạn có thể nhóm các quy tắc theo ngôn ngữ (chẳng hạn như Scala) hoặc nền tảng (chẳng hạn như Android).

Nội dung trong kho lưu trữ

Mỗi kho lưu trữ quy tắc phải có một bố cục nhất định để người dùng có thể nhanh chóng hiểu được các quy tắc mới.

Ví dụ: khi viết các quy tắc mới cho ngôn ngữ (tạo tin tưởng) mockascript, kho lưu trữ quy tắc sẽ có cấu trúc như sau:

/
  LICENSE
  README
  WORKSPACE
  mockascript/
    constraints/
      BUILD
    runfiles/
      BUILD
      runfiles.mocs
    BUILD
    defs.bzl
  tests/
    BUILD
    some_test.sh
    another_test.py
  examples/
    BUILD
    bin.mocs
    lib.mocs
    test.mocs

KHÔNG GIAN LÀM VIỆC

Trong WORKSPACE của dự án, bạn nên xác định tên mà người dùng sẽ sử dụng để tham chiếu đến các quy tắc của bạn. Nếu các quy tắc của bạn thuộc về tổ chức bazelbuild, bạn phải sử dụng rules_<lang> (chẳng hạn như rules_mockascript). Nếu không, bạn nên đặt tên cho kho lưu trữ là <org>_rules_<lang> (chẳng hạn như build_stack_rules_proto). Vui lòng liên hệ với danh sách gửi thư của Bazel-dev nếu bạn cho rằng các quy tắc của mình nên tuân theo quy ước về các quy tắc trong tổ chức bazelbuild.

Trong các phần sau, giả định kho lưu trữ thuộc về tổ chức bazelbuild.

workspace(name = "rules_mockascript")

README

Ở cấp cao nhất, phải có một README chứa (ít nhất) những nội dung mà người dùng cần sao chép và dán vào tệp WORKSPACE để sử dụng quy tắc của bạn. Nhìn chung, đây sẽ là một http_archive trỏ đến bản phát hành GitHub và một lệnh gọi macro tải xuống/định cấu hình bất kỳ công cụ nào mà quy tắc của bạn cần. Ví dụ: đối với Quy tắc Go, mã sẽ có dạng như sau:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "rules_go",
    urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.18.5/rules_go-0.18.5.tar.gz"],
    sha256 = "a82a352bffae6bee4e95f68a8d80a70e87f42c4741e6a448bec11998fcc82329",
)
load("@rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")
go_rules_dependencies()
go_register_toolchains()

Nếu quy tắc của bạn phụ thuộc vào quy tắc của một kho lưu trữ khác, hãy chỉ định điều đó trong tài liệu về quy tắc (ví dụ: xem quy tắc Skydoc, phụ thuộc vào các quy tắc Sass) và cung cấp macro WORKSPACE để tải tất cả phần phụ thuộc xuống (xem rules_go ở trên).

Quy tắc

Thông thường, kho lưu trữ của bạn sẽ cung cấp nhiều quy tắc. Tạo một thư mục theo ngôn ngữ mà bạn đặt tên và cung cấp điểm truy cập – tệp defs.bzl xuất tất cả quy tắc (cũng bao gồm một tệp BUILD để thư mục này là một gói). Đối với rules_mockascript, điều đó có nghĩa là sẽ có một thư mục có tên là mockascript, một tệp BUILD và một tệp defs.bzl bên trong:

/
  mockascript/
    BUILD
    defs.bzl

Giới hạn

Nếu quy tắc của bạn xác định các quy tắc chuỗi công cụ, thì có thể bạn sẽ cần xác định các constraint_setting và/hoặc constraint_value tuỳ chỉnh. Đặt các mục này vào gói //<LANG>/constraints. Cấu trúc thư mục của bạn sẽ có dạng như sau:

/
  mockascript/
    constraints/
      BUILD
    BUILD
    defs.bzl

Vui lòng đọc github.com/bazelbuild/platforms để biết các phương pháp hay nhất và xem các quy tắc ràng buộc hiện có, đồng thời cân nhắc đóng góp các quy tắc ràng buộc vào đó nếu các quy tắc đó độc lập về ngôn ngữ. Hãy lưu ý đến việc đưa ra các quy tắc ràng buộc tuỳ chỉnh, tất cả người dùng quy tắc của bạn sẽ sử dụng các quy tắc đó để thực hiện logic dành riêng cho nền tảng trong các tệp BUILD của họ (ví dụ: sử dụng các lựa chọn). Với các điều kiện ràng buộc tuỳ chỉnh, bạn xác định ngôn ngữ mà toàn bộ hệ sinh thái Bazel sẽ sử dụng.

Thư viện Runfiles

Nếu quy tắc của bạn cung cấp một thư viện chuẩn để truy cập vào các tệp runfile, thì quy tắc đó phải ở dạng mục tiêu thư viện nằm tại //<LANG>/runfiles (tên viết tắt của //<LANG>/runfiles:runfiles). Những mục tiêu người dùng cần truy cập vào các phần phụ thuộc dữ liệu của chúng thường sẽ thêm mục tiêu này vào thuộc tính deps.

Quy tắc kho lưu trữ

Phần phụ thuộc

Các quy tắc của bạn có thể có các phần phụ thuộc bên ngoài. Để đơn giản hoá quy tắc của bạn, vui lòng cung cấp macro WORKSPACE để khai báo các phần phụ thuộc trên các phần phụ thuộc bên ngoài đó. Không khai báo các phần phụ thuộc của kiểm thử ở đó, chỉ các phần phụ thuộc mà quy tắc yêu cầu để hoạt động. Đưa các phần phụ thuộc phát triển vào tệp WORKSPACE.

Tạo một tệp có tên <LANG>/repositories.bzl và cung cấp một macro điểm truy cập có tên rules_<LANG>_dependencies. Thư mục của chúng tôi sẽ có dạng như sau:

/
  mockascript/
    constraints/
      BUILD
    BUILD
    defs.bzl
    repositories.bzl

Đăng ký chuỗi công cụ

Các quy tắc của bạn cũng có thể đăng ký chuỗi công cụ. Vui lòng cung cấp một macro WORKSPACE riêng biệt giúp đăng ký các chuỗi công cụ này. Bằng cách này, người dùng có thể quyết định bỏ qua các phần phụ thuộc macro và điều khiển trước đó theo cách thủ công, trong khi vẫn được phép đăng ký chuỗi công cụ.

Do đó, hãy thêm macro WORKSPACE có tên rules_<LANG>_toolchains vào tệp <LANG>/repositories.bzl.

Xin lưu ý rằng để phân giải các chuỗi công cụ trong giai đoạn phân tích, Bazel cần phân tích tất cả các mục tiêu toolchain đã đăng ký. Bazel sẽ không cần phân tích mọi mục tiêu được tham chiếu bởi thuộc tính toolchain.toolchain. Nếu để đăng ký chuỗi công cụ, bạn cần thực hiện phép tính phức tạp trong kho lưu trữ, hãy cân nhắc việc chia tách kho lưu trữ với các mục tiêu toolchain từ kho lưu trữ có đích <LANG>_toolchain. Đối tượng Đối tượng cũ sẽ luôn được tìm nạp, còn đối tượng trước sẽ chỉ được tìm nạp khi người dùng thực sự cần tạo mã <LANG>.

Đoạn mã của bản phát hành

Trong thông báo phát hành, hãy cung cấp một đoạn mã mà người dùng có thể sao chép và dán vào tệp WORKSPACE. Đoạn mã này nhìn chung sẽ có dạng như sau:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "rules_<LANG>",
    urls = ["<url_to_the_release.zip"],
    sha256 = "4242424242",
)
load("@rules_<LANG>//<LANG>:repositories.bzl", "rules_<LANG>_dependencies", "rules_<LANG>_toolchains")
rules_<LANG>_dependencies()
rules_<LANG>_toolchains()

Kiểm thử

Cần có các bài kiểm thử xác minh rằng các quy tắc đang hoạt động như mong đợi. Tệp này có thể nằm ở vị trí chuẩn cho ngôn ngữ áp dụng quy tắc hoặc thư mục tests/ ở cấp cao nhất.

Ví dụ (không bắt buộc)

Bạn nên có một thư mục examples/ cho người dùng biết một số cách cơ bản để sử dụng các quy tắc này.

Kiểm thử

Thiết lập Travis như mô tả trong tài liệu bắt đầu sử dụng. Sau đó, hãy thêm tệp .travis.yml vào kho lưu trữ của bạn với nội dung sau:

dist: xenial  # Ubuntu 16.04

# On trusty (or later) images, the Bazel apt repository can be used.
addons:
  apt:
    sources:
    - sourceline: 'deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8'
      key_url: 'https://bazel.build/bazel-release.pub.gpg'
    packages:
    - bazel

script:
  - bazel build //...
  - bazel test //...

Nếu kho lưu trữ của bạn thuộc tổ chức Bazelbuild, bạn có thể yêu cầu thêm kho lưu trữ đó vào ci.bazel.build.

Tài liệu

Hãy xem tài liệu Stardoc để biết hướng dẫn về cách nhận xét các quy tắc của bạn để tài liệu có thể được tạo tự động.

Câu hỏi thường gặp

Tại sao chúng ta không thể thêm quy tắc của mình vào kho lưu trữ Bazel chính trên GitHub?

Chúng tôi muốn tách biệt các quy tắc trong bản phát hành Bazel nhiều nhất có thể. Việc ai sở hữu các quy tắc riêng lẻ sẽ rõ ràng hơn, giúp giảm tải cho các nhà phát triển Bazel. Đối với người dùng, việc phân tách giúp việc sửa đổi, nâng cấp, hạ cấp và thay thế các quy tắc dễ dàng hơn. Việc đóng góp cho các quy tắc có thể nhẹ hơn so với việc đóng góp cho Bazel (tuỳ thuộc vào quy tắc), bao gồm cả quyền gửi đầy đủ vào kho lưu trữ GitHub tương ứng. Việc gửi quyền truy cập vào chính Bazel là một quy trình phức tạp hơn nhiều.

Nhược điểm là quy trình cài đặt một lần phức tạp hơn dành cho người dùng: họ phải sao chép và dán quy tắc vào tệp WORKSPACE, như thể hiện trong phần README.md ở trên.

Chúng tôi từng có tất cả các quy tắc trong kho lưu trữ Bazel (trong //tools/build_rules hoặc //tools/build_defs). Chúng tôi vẫn còn một vài quy tắc ở đó, nhưng chúng tôi đang nỗ lực di chuyển các quy tắc còn lại.