Nội dung
gói
package(default_deprecation, default_package_metadata, default_testonly, default_visibility, features)
Hàm này khai báo siêu dữ liệu áp dụng cho mọi quy tắc trong gói. Hàm này được dùng tối đa một lần trong một gói (tệp BUILD).
Đối với đối tượng tương ứng khai báo siêu dữ liệu áp dụng cho mọi quy tắc trong toàn bộ
kho lưu trữ, hãy dùng hàm repo() trong
REPO.bazel tệp ở gốc kho lưu trữ.
Hàm repo() nhận chính xác các đối số giống như package().
Bạn nên gọi hàm package() ngay sau tất cả câu lệnh load() ở đầu tệp, trước bất kỳ quy tắc nào.
Đối số
| Thuộc tính | Mô tả |
|---|---|
default_applicable_licenses |
Bí danh cho |
default_visibility |
Danh sách nhãn; mặc định là Chế độ hiển thị mặc định của các mục tiêu quy tắc cấp cao nhất và macro tượng trưng
trong gói này – tức là các mục tiêu và macro tượng trưng
không được khai báo bên trong một macro tượng trưng. Thuộc tính này
sẽ bị bỏ qua nếu mục tiêu hoặc macro chỉ định giá trị Để biết thông tin chi tiết về cú pháp của thuộc tính này, hãy xem tài liệu về visibility. Chế độ hiển thị mặc định của gói không áp dụng cho exports_files, vốn là công khai theo mặc định. |
default_deprecation |
Chuỗi; mặc định là Đặt thông báo
|
default_package_metadata |
Danh sách nhãn; mặc định là Đặt danh sách mặc định các mục tiêu siêu dữ liệu áp dụng cho tất cả các mục tiêu khác trong gói. Đây thường là các mục tiêu liên quan đến gói OSS và các khai báo giấy phép. Hãy xem rules_license để biết ví dụ. |
default_testonly |
Boolean; mặc định là Đặt thuộc tính
Trong các gói thuộc |
features |
Chuỗi danh sách; mặc định là Đặt nhiều cờ ảnh hưởng đến ngữ nghĩa của tệp BUILD này. Tính năng này chủ yếu được những người làm việc trên hệ thống bản dựng dùng để gắn thẻ các gói cần xử lý đặc biệt. Đừng sử dụng tính năng này trừ phi có người làm việc trên hệ thống bản dựng yêu cầu bạn làm như vậy. |
Ví dụ
Khai báo bên dưới khai báo rằng các quy tắc trong gói này chỉ hiển thị cho các thành viên của nhóm gói//foo:target. Nếu có, các khai báo riêng lẻ về chế độ hiển thị trên một quy tắc sẽ ghi đè thông số kỹ thuật này.
package(default_visibility = ["//foo:target"])
package_group
package_group(name, packages, includes)
Hàm này xác định một tập hợp các gói
và liên kết một nhãn với tập hợp đó. Bạn có thể tham chiếu nhãn trong các thuộc tính visibility.
Nhóm gói chủ yếu được dùng để kiểm soát chế độ hiển thị. Bạn có thể tham chiếu một mục tiêu hiển thị công khai từ mọi gói trong cây nguồn. Bạn chỉ có thể tham chiếu một mục tiêu hiển thị riêng tư trong gói riêng của mục tiêu đó (không phải gói con). Ở giữa các trường hợp cực đoan này, một mục tiêu có thể cho phép truy cập vào gói riêng của mục tiêu đó cùng với bất kỳ gói nào được mô tả bởi một hoặc nhiều nhóm gói. Để biết giải thích chi tiết hơn về hệ thống hiển thị, hãy xem thuộc tính hiển thị.
Một gói nhất định được coi là nằm trong nhóm nếu gói đó khớp với thuộc tính packages hoặc đã có trong một trong các nhóm gói khác được đề cập trong thuộc tính includes.
Về mặt kỹ thuật, nhóm gói là các mục tiêu, nhưng không được tạo theo quy tắc và bản thân nhóm gói không có biện pháp bảo vệ chế độ hiển thị nào.
Đối số
| Thuộc tính | Mô tả |
|---|---|
name |
Tên; bắt buộc Tên riêng biệt cho mục tiêu này. |
packages |
Danh sách chuỗi; mặc định là Danh sách gồm 0 hoặc nhiều thông số kỹ thuật của gói. Mỗi chuỗi thông số kỹ thuật của gói có thể có một trong các dạng sau:
Ngoài ra, hai loại thông số kỹ thuật đầu tiên của gói cũng có thể
có tiền tố là Nhóm gói chứa mọi gói khớp với ít nhất một trong số
các thông số kỹ thuật dương tính và không có thông số kỹ thuật âm tính nào.
Ví dụ: giá trị Ngoài chế độ hiển thị công khai, bạn không thể chỉ định trực tiếp các gói bên ngoài kho lưu trữ hiện tại. Nếu thuộc tính này bị thiếu, thì thuộc tính này giống như việc đặt thành danh sách trống, cũng giống như việc đặt thành danh sách chỉ chứa Lưu ý: Trước Bazel 6.0, thông số kỹ thuật Lưu ý: Trước Bazel 6.0, khi thuộc tính này được tuần tự hoá như một phần của |
includes |
Danh sách nhãn; mặc định là Các nhóm gói khác có trong nhóm này. Các nhãn trong thuộc tính này phải tham chiếu đến các nhóm gói khác.
Các gói trong nhóm gói được tham chiếu được coi là một phần của nhóm gói này. Đây là tính chất bắc cầu – nếu nhóm gói
Khi được dùng cùng với các thông số kỹ thuật của gói bị phủ nhận, hãy lưu ý rằng tập hợp các gói cho mỗi nhóm được tính toán độc lập trước tiên, sau đó các kết quả sẽ được hợp nhất với nhau. Điều này có nghĩa là các thông số kỹ thuật bị phủ nhận trong một nhóm không ảnh hưởng đến các thông số kỹ thuật trong một nhóm khác. |
Ví dụ
Khai báo package_group sau đây chỉ định một nhóm gói có tên là "tropical" (nhiệt đới) chứa các loại trái cây nhiệt đới.
package_group(
name = "tropical",
packages = [
"//fruits/mango",
"//fruits/orange",
"//fruits/papaya/...",
],
)
Các khai báo sau đây chỉ định các nhóm gói của một ứng dụng hư cấu:
package_group(
name = "fooapp",
includes = [
":controller",
":model",
":view",
],
)
package_group(
name = "model",
packages = ["//fooapp/database"],
)
package_group(
name = "view",
packages = [
"//fooapp/swingui",
"//fooapp/webui",
],
)
package_group(
name = "controller",
packages = ["//fooapp/algorithm"],
)
exports_files
exports_files([label, ...], visibility, licenses)
exports_files() chỉ định danh sách các tệp thuộc
gói này được xuất sang các gói khác.
Tệp BUILD cho một gói chỉ có thể tham chiếu trực tiếp đến các tệp nguồn thuộc
một gói khác nếu các tệp đó được xuất rõ ràng bằng câu lệnh
exports_files(). Đọc thêm về
chế độ hiển thị của tệp.
Theo hành vi cũ, các tệp được đề cập làm dữ liệu đầu vào cho một quy tắc cũng được xuất
với chế độ hiển thị mặc định cho đến khi cờ
--incompatible_no_implicit_file_export
được chuyển. Tuy nhiên, bạn không nên dựa vào hành vi này và chủ động
di chuyển khỏi hành vi này.
Đối số
Đối số là danh sách tên của các tệp trong gói hiện tại. Bạn cũng có thể chỉ định khai báo về chế độ hiển thị; trong trường hợp này, các tệp sẽ hiển thị cho những mục tiêu được chỉ định. Nếu bạn không chỉ định chế độ hiển thị, thì mọi gói đều có thể nhìn thấy các tệp, ngay cả khi bạn đã chỉ định chế độ hiển thị mặc định của gói
trong hàm package. Bạn cũng có thể chỉ định giấy phép.
Ví dụ
Ví dụ sau đây xuất golden.txt, một tệp văn bản từ gói test_data, để các gói khác có thể sử dụng tệp này, chẳng hạn như trong thuộc tính data của các kiểm thử.
# from //test_data/BUILD exports_files(["golden.txt"])
glob
glob(include, exclude=[], exclude_directories=1, allow_empty=True)
Glob là một hàm trợ giúp tìm tất cả các tệp khớp với một số mẫu đường dẫn nhất định và trả về danh sách mới, có thể thay đổi và được sắp xếp theo đường dẫn của các tệp đó. Glob chỉ tìm kiếm các tệp trong gói riêng của mình và chỉ tìm các tệp nguồn (không phải tệp được tạo cũng như các mục tiêu khác).
Nhãn của tệp nguồn được đưa vào kết quả nếu đường dẫn tương ứng với gói của tệp khớp với bất kỳ mẫu include nào và không khớp với mẫu exclude nào.
Danh sách include và exclude chứa các mẫu đường dẫn tương ứng với gói hiện tại. Mỗi mẫu có thể bao gồm một hoặc nhiều phân đoạn đường dẫn. Như thường lệ với đường dẫn Unix, các phân đoạn này được phân tách bằng /. Các phân đoạn trong mẫu được so khớp với các phân đoạn của đường dẫn. Các phân đoạn có thể chứa ký tự đại diện *: ký tự này khớp với
mọi chuỗi con trong phân đoạn đường dẫn (ngay cả chuỗi con trống), ngoại trừ dấu phân cách thư mục /. Bạn có thể sử dụng ký tự đại diện này nhiều lần trong một phân đoạn đường dẫn. Ngoài ra, ký tự đại diện ** có thể khớp với 0 hoặc nhiều phân đoạn đường dẫn hoàn chỉnh, nhưng bạn phải khai báo ký tự này dưới dạng phân đoạn đường dẫn độc lập.
foo/bar.txtkhớp chính xác với tệpfoo/bar.txttrong gói này (trừ phifoo/là gói con)foo/*.txtkhớp với mọi tệp trong thư mụcfoo/nếu tệp đó kết thúc bằng.txt(trừ phifoo/là gói con)foo/a*.htm*khớp với mọi tệp trong thư mụcfoo/bắt đầu bằnga, sau đó có một chuỗi tuỳ ý (có thể trống), sau đó có.htmvà kết thúc bằng một chuỗi tuỳ ý khác (trừ phifoo/là gói con); chẳng hạn nhưfoo/axx.htmvàfoo/a.htmlhoặcfoo/axxx.htmlfoo/*khớp với mọi tệp trong thư mụcfoo/(trừ phifoo/là gói con); tệp này không khớp với thư mụcfoongay cả khi bạn đặtexclude_directoriesthành 0foo/**khớp với mọi tệp trong mọi thư mục con không phải gói con trong thư mục con cấp đầu tiên của góifoo/; nếuexclude_directoriesđược đặt thành 0,foothì thư mục đó cũng khớp với mẫu này; trong trường hợp này,**được coi là khớp với 0 phân đoạn đường dẫn**/a.txtkhớp với các tệpa.txttrong thư mục của gói này cùng với các thư mục con không phải gói con.**/bar/**/*.txtkhớp với mọi tệp.txttrong mọi thư mục con không phải gói con của gói này, nếu có ít nhất một thư mục trên đường dẫn kết quả có tên làbar, chẳng hạn nhưxxx/bar/yyy/zzz/a.txthoặcbar/a.txt(hãy nhớ rằng**cũng khớp với 0 phân đoạn) hoặcbar/zzz/a.txt**khớp với mọi tệp trong mọi thư mục con không phải gói con của gói nàyfoo**/a.txtlà mẫu không hợp lệ, vì**phải đứng riêng dưới dạng một phân đoạnfoo/là mẫu không hợp lệ, vì phân đoạn thứ hai được xác định sau/là một chuỗi trống
Nếu đối số exclude_directories được bật (đặt thành 1), thì các tệp thuộc loại thư mục sẽ bị bỏ qua trong kết quả (mặc định là 1).
Nếu bạn đặt đối số allow_empty thành False, thì hàm glob sẽ báo lỗi nếu kết quả là danh sách trống.
Có một số hạn chế và lưu ý quan trọng:
-
Vì
glob()chạy trong quá trình đánh giá tệp BUILD,glob()chỉ khớp với các tệp trong cây nguồn của bạn, không bao giờ khớp với các tệp được tạo. Nếu bạn đang tạo một mục tiêu yêu cầu cả tệp nguồn và tệp được tạo, thì bạn phải thêm danh sách tệp được tạo rõ ràng vào glob. Hãy xem ví dụ bên dưới với:mylibvà:gen_java_srcs. -
Nếu một quy tắc có cùng tên với tệp nguồn được so khớp, thì quy tắc đó sẽ "che khuất" tệp.
Để hiểu điều này, hãy nhớ rằng
glob()trả về danh sách đường dẫn, vì vậy, việc sử dụngglob()trong thuộc tính của các quy tắc khác (ví dụ:srcs = glob(["*.cc"])) có tác dụng tương tự như việc liệt kê rõ ràng các đường dẫn được so khớp. Ví dụ: nếuglob()tạo ra["Foo.java", "bar/Baz.java"]nhưng cũng có một quy tắc trong gói có tên là "Foo.java" (được phép, mặc dù Bazel cảnh báo về điều này), thì người dùngglob()sẽ sử dụng quy tắc "Foo.java" (các đầu ra của quy tắc đó) thay vì tệp "Foo.java". Hãy xem vấn đề #10395 trên GitHub để biết thêm chi tiết. - Glob có thể khớp với các tệp trong thư mục con. Và bạn có thể sử dụng ký tự đại diện cho tên thư mục con. Tuy nhiên...
-
Nhãn không được phép vượt qua ranh giới gói và glob does không khớp với các tệp trong gói con.
Ví dụ: biểu thức glob
**/*.cctrong góixkhông bao gồmx/y/z.ccnếux/ytồn tại dưới dạng một gói (dưới dạngx/y/BUILD, hoặc ở nơi khác trên đường dẫn gói). Điều này có nghĩa là kết quả của biểu thức glob thực sự phụ thuộc vào sự tồn tại của các tệp BUILD – tức là cùng một biểu thức glob sẽ bao gồmx/y/z.ccnếu không có gói nào có tên làx/yhoặc gói đó được đánh dấu là đã xoá bằng cờ --deleted_packages flag. - Quy định hạn chế ở trên áp dụng cho tất cả các biểu thức glob, bất kể chúng sử dụng ký tự đại diện nào.
-
Một tệp ẩn có tên tệp bắt đầu bằng
.hoàn toàn được so khớp bởi cả ký tự đại diện**và*. Nếu bạn muốn khớp với một tệp ẩn bằng mẫu phức hợp, thì mẫu của bạn cần bắt đầu bằng.. Ví dụ:*và.*.txtsẽ khớp với.foo.txt, nhưng*.txtsẽ không khớp. Các thư mục ẩn cũng được so khớp theo cách tương tự. Các thư mục ẩn có thể bao gồm các tệp không bắt buộc làm dữ liệu đầu vào và có thể làm tăng số lượng tệp được glob không cần thiết và mức tiêu thụ bộ nhớ. Để loại trừ các thư mục ẩn, hãy thêm các thư mục đó vào đối số danh sách "exclude". -
Ký tự đại diện "**" có một trường hợp đặc biệt: mẫu
"**"không khớp với đường dẫn thư mục của gói. Tức làglob(["**"], exclude_directories = 0)khớp với tất cả các tệp và thư mục một cách bắc cầu một cách nghiêm ngặt trong thư mục của gói hiện tại (nhưng tất nhiên là không đi vào các thư mục của gói con – hãy xem lưu ý trước đó về điều đó).
Nói chung, bạn nên cố gắng cung cấp một đuôi tệp thích hợp (ví dụ: *.html) thay vì sử dụng '*' trần cho mẫu glob. Tên rõ ràng hơn vừa tự ghi lại vừa đảm bảo rằng bạn không vô tình khớp với các tệp sao lưu hoặc tệp tự động lưu của emacs/vi/....
Khi viết quy tắc bản dựng, bạn có thể liệt kê các phần tử của glob. Điều này cho phép tạo các quy tắc riêng lẻ cho mọi dữ liệu đầu vào, chẳng hạn như. Hãy xem phần ví dụ về glob mở rộng bên dưới.
Ví dụ về glob
Tạo thư viện Java được xây dựng từ tất cả các tệp java trong thư mục này và tất cả các tệp được tạo theo quy tắc :gen_java_srcs.
java_library(
name = "mylib",
srcs = glob(["*.java"]) + [":gen_java_srcs"],
deps = "...",
)
genrule(
name = "gen_java_srcs",
outs = [
"Foo.java",
"Bar.java",
],
...
)
Bao gồm tất cả các tệp txt trong thư mục testdata ngoại trừ experimental.txt. Xin lưu ý rằng các tệp trong thư mục con của testdata sẽ không được đưa vào. Nếu bạn muốn đưa các tệp đó vào, hãy sử dụng glob đệ quy (**).
sh_test(
name = "mytest",
srcs = ["mytest.sh"],
data = glob(
["testdata/*.txt"],
exclude = ["testdata/experimental.txt"],
),
)
Ví dụ về glob đệ quy
Yêu cầu kiểm thử phụ thuộc vào tất cả các tệp txt trong thư mục testdata và mọi thư mục con của thư mục đó (cũng như thư mục con của các thư mục con đó, v.v.). Các thư mục con chứa tệp BUILD sẽ bị bỏ qua. (Xem các hạn chế và lưu ý ở trên.)
sh_test(
name = "mytest",
srcs = ["mytest.sh"],
data = glob(["testdata/**/*.txt"]),
)
Tạo thư viện được xây dựng từ tất cả các tệp java trong thư mục này và tất cả các thư mục con ngoại trừ những thư mục có đường dẫn bao gồm thư mục có tên là testing. Bạn nên tránh mẫu này nếu có thể, vì mẫu này có thể làm giảm tính tăng dần của bản dựng và do đó làm tăng thời gian xây dựng.
java_library(
name = "mylib",
srcs = glob(
["**/*.java"],
exclude = ["**/testing/**"],
),
)
Ví dụ về glob mở rộng
Tạo một genrule riêng lẻ cho *_test.cc trong thư mục hiện tại để đếm số dòng trong tệp.
# Conveniently, the build language supports list comprehensions.
[genrule(
name = "count_lines_" + f[:-3], # strip ".cc"
srcs = [f],
outs = ["%s-linecount.txt" % f[:-3]],
cmd = "wc -l $< >$@",
) for f in glob(["*_test.cc"])]
Nếu tệp BUILD ở trên nằm trong gói //foo và gói đó chứa 3 tệp khớp, a_test.cc, b_test.cc và c_test.cc, thì việc chạy bazel query '//foo:all' sẽ liệt kê tất cả các quy tắc đã được tạo:
$ bazel query '//foo:all' | sort //foo:count_lines_a_test //foo:count_lines_b_test //foo:count_lines_c_test
chọn
select(
{conditionA: valuesA, conditionB: valuesB, ...},
no_match_error = "custom message"
)
select() là hàm trợ giúp giúp định cấu hình thuộc tính quy tắc
có thể định cấu hình.
Hàm này có thể thay thế phía bên phải của
hầu hết
mọi phép gán thuộc tính để giá trị của thuộc tính đó phụ thuộc vào các cờ Bazel trên dòng lệnh.
Ví dụ: bạn có thể sử dụng hàm này để xác định các phần phụ thuộc dành riêng cho nền tảng hoặc để
nhúng các tài nguyên khác nhau tuỳ thuộc vào việc một quy tắc được xây dựng ở chế độ "nhà phát triển"
hay "phát hành".
Cách sử dụng cơ bản như sau:
sh_binary(
name = "mytarget",
srcs = select({
":conditionA": ["mytarget_a.sh"],
":conditionB": ["mytarget_b.sh"],
"//conditions:default": ["mytarget_default.sh"]
})
)
Điều này giúp định cấu hình thuộc tính srcs của
một sh_binary bằng cách thay thế phép gán danh sách nhãn
thông thường bằng lệnh gọi select ánh xạ
các điều kiện cấu hình với các giá trị tương ứng. Mỗi điều kiện là một tham chiếu nhãn đến config_setting hoặc constraint_value, "khớp" nếu cấu hình của mục tiêu khớp với một tập hợp giá trị dự kiến. Sau đó, giá trị của mytarget#srcs sẽ trở thành danh sách nhãn khớp với lệnh gọi hiện tại.
Lưu ý:
- Chỉ một điều kiện được chọn trên mọi lệnh gọi.
- Nếu nhiều điều kiện khớp và một điều kiện là chuyên môn hoá của các điều kiện khác, điều kiện chuyên môn hoá sẽ được ưu tiên. Điều kiện B được coi là a chuyên môn hoá của điều kiện A nếu B có tất cả các cờ và giá trị ràng buộc giống như A cộng với một số cờ hoặc giá trị ràng buộc bổ sung. Điều này cũng có nghĩa là giải pháp chuyên môn hoá không được thiết kế để tạo thứ tự như minh hoạ trong Ví dụ 2 bên dưới.
- Nếu nhiều điều kiện khớp và một điều kiện không phải là chuyên môn hoá của tất cả các điều kiện khác, thì Bazel sẽ báo lỗi, trừ phi tất cả các điều kiện đều giải quyết thành cùng một giá trị.
- Nhãn giả đặc biệt
//conditions:defaultđược coi là khớp nếu không có điều kiện nào khác khớp. Nếu bạn bỏ qua điều kiện này, thì một quy tắc khác phải khớp để tránh lỗi. selectcó thể được nhúng bên trong phép gán thuộc tính lớn hơn. Vì vậy,srcs = ["common.sh"] + select({ ":conditionA": ["myrule_a.sh"], ...})vàsrcs = select({ ":conditionA": ["a.sh"]}) + select({ ":conditionB": ["b.sh"]})là các biểu thức hợp lệ.selecthoạt động với hầu hết, nhưng không phải tất cả các thuộc tính. Các thuộc tính không tương thích được đánh dấu lànonconfigurabletrong tài liệu của chúng.gói con
subpackages(include, exclude=[], allow_empty=True)
subpackages()là một hàm trợ giúp, tương tự nhưglob()liệt kê các gói con thay vì tệp và thư mục. Hàm này sử dụng các mẫu đường dẫn giống nhưglob()và có thể khớp với mọi gói con là phần tử con trực tiếp của tệp BUILD đang tải. Hãy xem glob để biết giải thích chi tiết và các ví dụ về mẫu bao gồm và loại trừ.Danh sách gói con kết quả được trả về theo thứ tự đã sắp xếp và chứa các đường dẫn tương ứng với gói tải hiện tại khớp với các mẫu đã cho trong
includevà không khớp với các mẫu trongexclude.Ví dụ
Ví dụ sau đây liệt kê tất cả các gói con trực tiếp cho gói
foo/BUILD# The following BUILD files exist: # foo/BUILD # foo/bar/baz/BUILD # foo/bar/but/bad/BUILD # foo/sub/BUILD # foo/sub/deeper/BUILD # # In foo/BUILD a call to subs1 = subpackages(include = ["**"]) # results in subs1 == ["sub", "bar/baz", "bar/but/bad"] # # 'sub/deeper' is not included because it is a subpackage of 'foo/sub' not of # 'foo' subs2 = subpackages(include = ["bar/*"]) # results in subs2 = ["bar/baz"] # # Since 'bar' is not a subpackage itself, this looks for any subpackages under # all first level subdirectories of 'bar'. subs3 = subpackages(include = ["bar/**"]) # results in subs3 = ["bar/baz", "bar/but/bad"] # # Since bar is not a subpackage itself, this looks for any subpackages which are # (1) under all subdirectories of 'bar' which can be at any level, (2) not a # subpackage of another subpackages. subs4 = subpackages(include = ["sub"]) subs5 = subpackages(include = ["sub/*"]) subs6 = subpackages(include = ["sub/**"]) # results in subs4 and subs6 being ["sub"] # results in subs5 = []. # # In subs4, expression "sub" checks whether 'foo/sub' is a package (i.e. is a # subpackage of 'foo'). # In subs5, "sub/*" looks for subpackages under directory 'foo/sub'. Since # 'foo/sub' is already a subpackage itself, the subdirectories will not be # traversed anymore. # In subs6, 'foo/sub' is a subpackage itself and matches pattern "sub/**", so it # is returned. But the subdirectories of 'foo/sub' will not be traversed # anymore.
Nói chung, bạn nên sử dụng mô-đun "subpackages" của skylib thay vì gọi trực tiếp hàm này.