Trang này mô tả cách mở rộng ngôn ngữ BUILD bằng macro và quy tắc.
Tiện ích Bazel là các tệp có đuôi .bzl. Sử dụng câu lệnh tải để nhập một ký hiệu từ tiện ích.
Trước khi tìm hiểu các khái niệm nâng cao hơn, trước tiên:
Đọc về ngôn ngữ Starlark, được dùng trong cả tệp
BUILDvà.bzl.Tìm hiểu cách chia sẻ biến giữa hai tệp
BUILD.
Macro và quy tắc
Macro là một hàm tạo thực thể quy tắc. Macro có 2 loại:
macro tượng trưng (mới trong Bazel 8) và macro
cũ. Hai loại macro được xác định khác nhau, nhưng hoạt động gần như giống nhau theo quan điểm của người dùng. Macro rất hữu ích khi tệp BUILD trở nên quá lặp đi lặp lại hoặc quá phức tạp, vì macro cho phép bạn sử dụng lại một số mã. Hàm được đánh giá ngay khi tệp BUILD được đọc. Sau khi đánh giá tệp BUILD, Bazel có ít thông tin về macro. Nếu macro tạo ra genrule, Bazel sẽ hoạt động gần như khi bạn khai báo genrule đó trong tệp BUILD. (Một trường hợp ngoại lệ là các mục tiêu được khai báo trong macro tượng trưng có ngữ nghĩa về khả năng hiển thị đặc biệt: macro tượng trưng có thể ẩn các mục tiêu nội bộ của mình khỏi phần còn lại của gói.)
Một quy tắc mạnh hơn macro. Quy tắc có thể truy cập vào các thành phần bên trong của Bazel và có toàn quyền kiểm soát những gì đang diễn ra. Ví dụ: quy tắc có thể truyền thông tin cho các quy tắc khác.
Nếu bạn muốn sử dụng lại logic đơn giản, hãy bắt đầu bằng macro; chúng tôi khuyên bạn nên dùng macro tượng trưng, trừ phi bạn cần hỗ trợ các phiên bản Bazel cũ hơn. Nếu macro trở nên phức tạp, thì thường nên biến macro thành quy tắc. Tính năng hỗ trợ cho ngôn ngữ mới thường được thực hiện bằng quy tắc. Quy tắc dành cho người dùng nâng cao và hầu hết người dùng sẽ không bao giờ phải viết quy tắc; họ sẽ chỉ tải và gọi các quy tắc hiện có.
Mô hình đánh giá
Bản dựng bao gồm 3 giai đoạn.
Giai đoạn tải. Trước tiên, hãy tải và đánh giá tất cả tiện ích và tất cả tệp
BUILDcần thiết cho quá trình xây dựng. Việc thực thi các tệpBUILDchỉ đơn giản là tạo thực thể quy tắc (mỗi khi một quy tắc được gọi, quy tắc đó sẽ được thêm vào biểu đồ). Đây là nơi đánh giá macro.Giai đoạn phân tích. Mã của các quy tắc được thực thi (hàm
implementationcủa chúng) và các hành động được tạo thực thể. Một hành động mô tả cách tạo một tập hợp đầu ra từ một tập hợp đầu vào, chẳng hạn như "chạy gcc trên hello.c và nhận hello.o". Bạn phải liệt kê rõ ràng những tệp sẽ được tạo trước khi thực thi các lệnh thực tế. Nói cách khác, giai đoạn phân tích sẽ lấy biểu đồ do giai đoạn tải tạo ra và tạo biểu đồ hành động.Giai đoạn thực thi. Các hành động được thực thi khi cần ít nhất một trong các đầu ra của chúng. Nếu một tệp bị thiếu hoặc nếu một lệnh không tạo được một đầu ra, thì quá trình xây dựng sẽ không thành công. Các bài kiểm thử cũng được chạy trong giai đoạn này.
Bazel sử dụng tính năng song song để đọc, phân tích cú pháp và đánh giá các tệp .bzl và tệp BUILD. Một tệp được đọc tối đa một lần cho mỗi bản dựng và kết quả đánh giá được lưu vào bộ nhớ đệm và sử dụng lại. Một tệp chỉ được đánh giá sau khi tất cả các phần phụ thuộc của tệp đó (câu lệnh load()) đã được phân giải. Theo thiết kế, việc tải tệp .bzl không có tác dụng phụ hữu hình, mà chỉ xác định các giá trị và hàm.
Bazel cố gắng thông minh: Bazel sử dụng tính năng phân tích phần phụ thuộc để biết những tệp nào phải được tải, những quy tắc nào phải được phân tích và những hành động nào phải được thực thi. Ví dụ: nếu một quy tắc tạo ra các hành động mà bạn không cần cho bản dựng hiện tại, thì các hành động đó sẽ không được thực thi.
Tạo tiện ích
Tạo macro đầu tiên để sử dụng lại một số mã. Sau đó, tìm hiểu thêm về macro và cách sử dụng macro để tạo "động từ tuỳ chỉnh".
Làm theo hướng dẫn về quy tắc để bắt đầu sử dụng quy tắc. Tiếp theo, bạn có thể đọc thêm về các khái niệm quy tắc.
Hai đường liên kết bên dưới sẽ rất hữu ích khi bạn viết tiện ích của riêng mình. Hãy giữ chúng trong tầm tay:
Tìm hiểu thêm
Ngoài macro và quy tắc, bạn có thể muốn viết các khía cạnh và quy tắc kho lưu trữ.
Sử dụng Buildifier một cách nhất quán để định dạng và tìm lỗi mã nguồn cho mã của bạn.
Làm theo hướng dẫn về kiểu
.bzl.Kiểm thử mã.
Tạo tài liệu để giúp người dùng.
Tối ưu hoá hiệu suất của mã.
Triển khai tiện ích cho người khác.