Các phần trước đã mô tả các gói, mục tiêu và nhãn, đồng thời trừu tượng hoá biểu đồ phần phụ thuộc của bản dựng. Phần này mô tả cú pháp cụ thể được dùng để xác định một gói.
Theo định nghĩa, mọi gói đều chứa một tệp BUILD
, đây là một chương trình ngắn.
Các tệp BUILD
được đánh giá bằng cách sử dụng một ngôn ngữ mệnh lệnh, Starlark.
Chúng được diễn giải dưới dạng một danh sách tuần tự các câu lệnh.
Nói chung, thứ tự có vai trò quan trọng: các biến phải được xác định trước khi được sử dụng, chẳng hạn như. Tuy nhiên, hầu hết các tệp BUILD
chỉ bao gồm các khai báo về quy tắc xây dựng và thứ tự tương đối của các câu lệnh này là không quan trọng; tất cả những gì quan trọng là những quy tắc nào đã được khai báo và với những giá trị nào, vào thời điểm quá trình đánh giá gói hoàn tất.
Khi một hàm quy tắc bản dựng (chẳng hạn như cc_library
) được thực thi, hàm này sẽ tạo một mục tiêu mới trong biểu đồ. Sau này, bạn có thể tham chiếu mục tiêu này bằng nhãn.
Trong các tệp BUILD
đơn giản, bạn có thể tự do sắp xếp lại các khai báo quy tắc mà không cần thay đổi hành vi.
Để khuyến khích việc tách biệt rõ ràng giữa mã và dữ liệu, các tệp BUILD
không được chứa định nghĩa hàm, câu lệnh for
hoặc câu lệnh if
(nhưng bạn có thể sử dụng danh sách hiểu và biểu thức if
). Thay vào đó, bạn có thể khai báo các hàm trong tệp .bzl
. Ngoài ra, các đối số *args
và **kwargs
không được phép trong tệp BUILD
; thay vào đó, hãy liệt kê rõ ràng tất cả các đối số.
Điều quan trọng là các chương trình trong Starlark không thể thực hiện hoạt động I/O tuỳ ý. Bất biến này giúp việc diễn giải các tệp BUILD
trở nên khép kín – chỉ phụ thuộc vào một bộ đầu vào đã biết, điều này rất cần thiết để đảm bảo rằng các bản dựng có thể tái tạo.
Để biết thêm thông tin chi tiết, hãy xem phần Hermeticity.
Vì các tệp BUILD
cần được cập nhật bất cứ khi nào các phần phụ thuộc của mã cơ bản thay đổi, nên thường có nhiều người trong nhóm duy trì các tệp này. Tác giả tệp BUILD
nên bình luận một cách thoải mái để ghi lại vai trò của từng mục tiêu bản dựng, cho dù mục tiêu đó có dành cho mục đích sử dụng công khai hay không, đồng thời ghi lại vai trò của chính gói.
Tải tiện ích
Tiện ích Bazel là những tệp có đuôi .bzl
. Sử dụng câu lệnh load
để nhập một biểu tượng từ một tiện ích.
load("//foo/bar:file.bzl", "some_library")
Mã này tải tệp foo/bar/file.bzl
và thêm biểu tượng some_library
vào môi trường. Bạn có thể dùng hàm này để tải các quy tắc, hàm hoặc hằng số mới (ví dụ: một chuỗi hoặc danh sách). Bạn có thể nhập nhiều biểu tượng bằng cách sử dụng các đối số bổ sung cho lệnh gọi đến load
. Đối số phải là chuỗi ký tự (không có biến) và câu lệnh load
phải xuất hiện ở cấp cao nhất – chúng không thể nằm trong nội dung hàm.
Đối số đầu tiên của load
là một nhãn xác định tệp .bzl
. Nếu là nhãn tương đối, thì nhãn đó sẽ được phân giải liên quan đến gói (không phải thư mục) chứa tệp bzl
hiện tại. Nhãn tương đối trong câu lệnh load
phải sử dụng :
ở đầu.
load
cũng hỗ trợ bí danh, do đó, bạn có thể chỉ định các tên khác nhau cho các biểu tượng đã nhập.
load("//foo/bar:file.bzl", library_alias = "some_library")
Bạn có thể xác định nhiều biệt hiệu trong một câu lệnh load
. Ngoài ra, danh sách đối số có thể chứa cả bí danh và tên biểu tượng thông thường. Ví dụ sau đây hoàn toàn hợp pháp (vui lòng lưu ý thời điểm sử dụng dấu ngoặc kép).
load(":my_rules.bzl", "some_rule", nice_alias = "some_other_rule")
Trong tệp .bzl
, các biểu tượng bắt đầu bằng _
sẽ không được xuất và không thể tải từ một tệp khác.
Bạn có thể sử dụng khả năng hiển thị khi tải để hạn chế những người có thể tải tệp .bzl
.
Các loại quy tắc xây dựng
Phần lớn các quy tắc xây dựng đều thuộc các nhóm, được nhóm lại với nhau theo ngôn ngữ. Ví dụ: cc_binary
, cc_library
và cc_test
lần lượt là các quy tắc xây dựng cho các tệp nhị phân, thư viện và kiểm thử C++. Các ngôn ngữ khác sử dụng cùng một quy tắc đặt tên, với một tiền tố khác, chẳng hạn như java_*
cho Java. Một số hàm trong số này được ghi lại trong Bách khoa toàn thư về bản dựng, nhưng bất kỳ ai cũng có thể tạo quy tắc mới.
Các quy tắc
*_binary
tạo ra các chương trình có thể thực thi bằng một ngôn ngữ nhất định. Sau khi tạo, tệp thực thi sẽ nằm trong cây đầu ra nhị phân của công cụ tạo tại tên tương ứng cho nhãn của quy tắc, vì vậy//my:program
sẽ xuất hiện tại (ví dụ)$(BINDIR)/my/program
.Trong một số ngôn ngữ, các quy tắc như vậy cũng tạo ra một thư mục runfiles chứa tất cả các tệp được đề cập trong một thuộc tính
data
thuộc về quy tắc hoặc bất kỳ quy tắc nào trong bao đóng bắc cầu của các phần phụ thuộc; tập hợp tệp này được thu thập cùng nhau ở một nơi để dễ dàng triển khai cho sản xuất.Quy tắc
*_test
là một chuyên môn hoá của quy tắc*_binary
, được dùng để kiểm thử tự động. Các kiểm thử chỉ là những chương trình trả về 0 khi thành công.Giống như các tệp nhị phân, các kiểm thử cũng có cây runfile và các tệp bên dưới cây này là những tệp duy nhất mà một kiểm thử có thể mở một cách hợp pháp trong thời gian chạy. Ví dụ: chương trình
cc_test(name='x', data=['//foo:bar'])
có thể mở và đọc$TEST_SRCDIR/workspace/foo/bar
trong quá trình thực thi. (Mỗi ngôn ngữ lập trình đều có hàm tiện ích riêng để truy cập vào giá trị của$TEST_SRCDIR
, nhưng tất cả đều tương đương với việc sử dụng trực tiếp biến môi trường.) Nếu không tuân thủ quy tắc này, kiểm thử sẽ không thành công khi được thực thi trên một máy chủ kiểm thử từ xa.Các quy tắc
*_library
chỉ định các mô-đun được biên dịch riêng bằng ngôn ngữ lập trình đã cho. Các thư viện có thể phụ thuộc vào các thư viện khác, còn các tệp nhị phân và kiểm thử có thể phụ thuộc vào các thư viện, với hành vi biên dịch riêng biệt như dự kiến.
Nhãn | Phần phụ thuộc |
Mã hoá tệp
Tệp BUILD
và .bzl
phải được mã hoá bằng UTF-8, trong đó ASCII là một tập hợp con hợp lệ. Hiện tại, các chuỗi byte tuỳ ý được cho phép, nhưng có thể sẽ không được hỗ trợ trong tương lai.