Trang này trình bày các nguyên tắc cơ bản về kiểu gốc của Starlark cũng như thông tin về macro và quy tắc.
Starlark là một ngôn ngữ xác định cách thức phát triển phần mềm, và do đó, đây vừa là một lập trình và ngôn ngữ cấu hình.
Bạn sẽ dùng Starlark để ghi tệp BUILD
, macro và quy tắc bản dựng. Macro và
Về cơ bản, quy tắc là ngôn ngữ siêu dữ liệu – các quy tắc này xác định cách viết tệp BUILD
.
Tệp BUILD
có thiết kế đơn giản và lặp lại.
Mọi phần mềm được đọc thường xuyên hơn so với được viết ra. Điều này đặc biệt đúng đối với
Starlark, khi các kỹ sư đọc các tệp BUILD
để hiểu các phần phụ thuộc của
mục tiêu và thông tin chi tiết về các bản dựng của chúng. Việc đọc này thường xảy ra trong lúc lướt qua,
vội vã hay song song để hoàn thành một số nhiệm vụ khác. Do đó,
tính đơn giản và dễ đọc là điều rất quan trọng
để người dùng có thể phân tích cú pháp và
nhanh chóng hiểu tệp BUILD
.
Khi người dùng mở tệp BUILD
, họ sẽ nhanh chóng muốn biết danh sách các mục tiêu trong
tệp; hoặc xem lại danh sách các nguồn của thư viện C++ đó; hoặc xóa một
phần phụ thuộc từ tệp nhị phân Java đó. Mỗi lần thêm một lớp trừu tượng, bạn
khiến người dùng khó thực hiện các tác vụ này hơn.
Các tệp BUILD
cũng được nhiều công cụ phân tích và cập nhật. Công cụ có thể không
có thể chỉnh sửa tệp BUILD
nếu tệp đó sử dụng các thành phần trừu tượng. Lưu giữ BUILD
của bạn
tệp đơn giản sẽ giúp bạn có công cụ tốt hơn. Khi cơ sở mã phát triển,
thực hiện các thay đổi trên nhiều tệp BUILD
ngày càng thường xuyên để
cập nhật thư viện hoặc dọn dẹp.
Lời khuyên chung
- Sử dụng Buildifier làm trình định dạng và công cụ tìm lỗi mã nguồn.
- Tuân thủ nguyên tắc kiểm thử.
Phong cách
Kiểu Python
Khi nghi ngờ, hãy làm theo Hướng dẫn quy tắc về PEP 8 nếu có thể. Cụ thể, hãy sử dụng 4 thay vì 2 khoảng trắng để thụt lề theo sau Quy ước Python.
Từ
Starlark không phải là Python,
không áp dụng một số khía cạnh của kiểu Python. Ví dụ: PEP 8 khuyên rằng
so sánh với các singleton được thực hiện bằng is
. Đây không phải là toán tử trong
Starlark.
Chuỗi tài liệu
Ghi lại các tệp và hàm bằng chuỗi tài liệu (docstrings).
Sử dụng một chuỗi tài liệu ở đầu mỗi tệp .bzl
và một chuỗi tài liệu cho mỗi tệp công khai
.
Các quy tắc và khía cạnh của tài liệu
Quy tắc và khía cạnh, cùng với thuộc tính của chúng, cũng như nhà cung cấp và
các trường, phải được ghi lại bằng đối số doc
.
Quy ước đặt tên
- Tên biến và hàm sử dụng chữ thường với các từ được phân tách bằng
dấu gạch dưới (
[a-z][a-z0-9_]*
), chẳng hạn nhưcc_library
. - Các giá trị riêng tư cấp cao nhất bắt đầu bằng một dấu gạch dưới. Bazel thực thi việc đó không thể sử dụng giá trị riêng tư từ các tệp khác. Biến cục bộ không được sử dụng tiền tố dấu gạch dưới.
Độ dài của đường kẻ
Như trong tệp BUILD
, không có giới hạn nghiêm ngặt về độ dài dòng vì nhãn có thể dài.
Khi có thể, hãy cố gắng sử dụng tối đa 79 ký tự mỗi dòng (theo
hướng dẫn quy tắc, PEP 8). Nguyên tắc này
không được thực thi nghiêm ngặt: trình chỉnh sửa phải hiển thị hơn 80 cột,
những thay đổi tự động sẽ thường đưa ra các dòng dài hơn và con người không nên
dành thời gian chia tách các dòng đã đọc được.
Đối số từ khoá
Trong đối số từ khoá, dấu cách xung quanh dấu bằng được ưu tiên:
def fct(name, srcs):
filtered_srcs = my_filter(source = srcs)
native.cc_library(
name = name,
srcs = filtered_srcs,
testonly = True,
)
Giá trị boolean
Ưu tiên các giá trị True
và False
(thay vì 1
và 0
) cho các giá trị boolean
(chẳng hạn như khi sử dụng thuộc tính boolean trong một quy tắc).
Chỉ sử dụng bản in để gỡ lỗi
Không sử dụng hàm print()
trong mã phát hành chính thức; nội dung chỉ dành cho
gỡ lỗi và sẽ gửi spam cho tất cả người dùng trực tiếp và gián tiếp của tệp .bzl
. Chiến lược phát hành đĩa đơn
ngoại lệ duy nhất là bạn có thể gửi mã sử dụng print()
nếu mã này bị tắt
theo mặc định và chỉ có thể được bật bằng cách chỉnh sửa nguồn -- ví dụ: nếu tất cả
việc sử dụng print()
được bảo vệ bằng if DEBUG:
, trong đó DEBUG
được cố định giá trị trong mã
False
. Cân nhắc xem những tuyên bố này có đủ hữu ích để biện minh hay không
tác động của chúng đến mức độ dễ đọc.
Macro
Macro là hàm tạo thực thể cho một hoặc nhiều quy tắc trong quá trình tải pha. Nói chung, sử dụng quy tắc bất cứ khi nào có thể thay vì macro. Bản dựng đồ thị mà người dùng nhìn thấy không giống với đồ thị mà Bazel sử dụng trong build – macro được mở rộng trước khi Bazel thực hiện bất kỳ phân tích biểu đồ tạo bản dựng nào.
Do đó, khi xảy ra sự cố, người dùng cần phải biết
triển khai macro của bạn để khắc phục sự cố bản dựng. Ngoài ra, kết quả bazel
query
có thể khó diễn giải vì các mục tiêu hiển thị trong kết quả
đến từ mở rộng macro. Cuối cùng, các khía cạnh không nhận biết được macro, vì vậy, việc sử dụng công cụ
tuỳ thuộc vào khía cạnh (IDE và các khía cạnh khác) có thể không thành công.
Việc sử dụng macro một cách an toàn là để xác định các mục tiêu bổ sung nhằm tham chiếu trực tiếp tại Bazel CLI hoặc trong tệp BUILD: Trong trường hợp đó, chỉ phần tử người dùng cuối của các mục tiêu đó cần phải biết về chúng và mọi sự cố bản dựng do macro giới thiệu.
Đối với macro xác định mục tiêu đã tạo (chi tiết triển khai của macro không được đề cập tại CLI hoặc phụ thuộc vào mục tiêu không được macro đó tạo thực thể), hãy làm theo các phương pháp hay nhất sau đây:
- Macro phải lấy đối số
name
và xác định một mục tiêu có tên đó. Mục tiêu đó trở thành mục tiêu chính của macro đó. - Các mục tiêu được tạo (tức là tất cả các mục tiêu khác do macro xác định) phải:
- Có tiền tố tên là
<name>
hoặc_<name>
. Ví dụ: sử dụngname = '%s_bar' % (name)
. - Bị hạn chế hiển thị (
//visibility:private
) và - Có một thẻ
manual
để tránh mở rộng trong các mục tiêu ký tự đại diện (:all
,...
,:*
, v.v.).
- Có tiền tố tên là
- Chỉ nên sử dụng
name
để lấy tên của mục tiêu được xác định bằng chứ không phải cho bất kỳ mục đích nào khác. Ví dụ: Đừng dùng tên này để gợi ý một tệp phụ thuộc hoặc tệp đầu vào không được tạo bởi chính macro. - Tất cả các mục tiêu được tạo trong macro phải được kết hợp theo cách nào đó với mục tiêu chính.
- Thông thường,
name
phải là đối số đầu tiên khi xác định macro. - Giữ cho tên tham số trong macro nhất quán. Nếu một thông số được truyền
làm giá trị thuộc tính cho mục tiêu chính, hãy giữ nguyên tên của thuộc tính đó. Nếu macro
có mục đích giống như thuộc tính quy tắc chung, chẳng hạn như
deps
, đặt tên giống với tên thuộc tính (xem bên dưới). - Khi gọi macro, chỉ sử dụng các đối số từ khoá. Điều này phù hợp với và cải thiện đáng kể mức độ dễ đọc.
Các kỹ sư thường viết macro khi Starlark API của các quy tắc có liên quan là không đủ cho trường hợp sử dụng cụ thể của họ, bất kể quy tắc đó có được xác định trong Bazel trong mã gốc hoặc trong Starlark. Nếu bạn đang gặp phải vấn đề này vấn đề, hãy hỏi người tạo quy tắc xem họ có thể mở rộng API để hoàn thành mục tiêu.
Theo quy tắc chung, càng nhiều macro giống với quy tắc càng tốt.
Bạn cũng có thể xem macro.
Quy tắc
- Quy tắc, khía cạnh và thuộc tính của quy tắc nên sử dụng tên viết thường ("postalt_case) trường hợp").
- Tên quy tắc là danh từ mô tả loại cấu phần phần mềm chính do
quy tắc này, từ góc độ các phần phụ thuộc của nó (hoặc đối với quy tắc lá, phương thức
người dùng). Đây không nhất thiết là hậu tố của tệp. Ví dụ: quy tắc
tạo ra cấu phần phần mềm C++ được dùng khi phần mở rộng Python có thể được gọi
py_extension
. Đối với hầu hết ngôn ngữ, các quy tắc thông thường bao gồm:*_library
– một đơn vị biên dịch hoặc "mô-đun".*_binary
– một mục tiêu tạo tệp thực thi hoặc đơn vị triển khai.*_test
– một mục tiêu thử nghiệm. Bạn có thể bao gồm nhiều bài kiểm thử. Dự kiến tất cả thử nghiệm trong mục tiêu*_test
là các biến thể trên cùng một chủ đề, cho chẳng hạn như kiểm thử một thư viện.*_import
: một mục tiêu đóng gói cấu phần phần mềm được biên dịch trước, chẳng hạn như.jar
hoặc.dll
dùng trong quá trình biên dịch.
- Sử dụng tên và loại nhất quán cho các thuộc tính. Một số trường hợp thường áp dụng
thuộc tính bao gồm:
srcs
:label_list
, cho phép các tệp: tệp nguồn, thường là do con người tạo ra.deps
:label_list
, thường không cho phép các tệp: biên dịch phần phụ thuộc.data
:label_list
, cho phép các tệp: tệp dữ liệu, chẳng hạn như dữ liệu kiểm thử, v.v.runtime_deps
:label_list
: các phần phụ thuộc thời gian chạy không cần thiết để biên dịch.
- Đối với mọi thuộc tính có hành vi không rõ ràng (ví dụ: mẫu chuỗi
bằng các tính năng thay thế đặc biệt hoặc các công cụ được gọi bằng các dịch vụ
cung cấp tài liệu sử dụng đối số từ khoá
doc
cho phần khai báo của thuộc tính (attr.label_list()
hoặc tương tự). - Hàm triển khai quy tắc hầu như luôn là hàm riêng tư
(được đặt tên bằng dấu gạch dưới ở đầu). Một phong cách phổ biến là đưa ra
hàm triển khai cho
myrule
tên là_myrule_impl
. - Chuyển thông tin giữa các quy tắc của bạn bằng cách sử dụng một Giao diện provider. Khai báo và cung cấp tài liệu mới.
- Thiết kế quy tắc chú trọng đến khả năng mở rộng. Lưu ý rằng các quy tắc khác có thể muốn tương tác với quy tắc của bạn, truy cập vào các nhà cung cấp và sử dụng lại mà bạn tạo.
- Tuân thủ nguyên tắc về hiệu suất trong quy tắc của bạn.