Nội dung
gói hàng
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. Tệp này được dùng tối đa một lần trong gói (tệp BUILD).
Đối với phần đối chiếu 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 tệp REPO.bazel
ở gốc kho lưu trữ của bạn.
Hàm repo()
nhận chính xác các đối số tương tự như package()
.
Hàm package() phải được gọi ngay sau tất cả cá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 | Nội dung mô tả |
---|---|
default_applicable_licenses |
Bí danh của |
default_visibility |
Danh sách nhãn; mặc định là Chế độ hiển thị mặc định của các quy tắc trong gói này. Mọi quy tắc trong gói này đều có chế độ hiển thị được chỉ định trong thuộc tính này, trừ phi có quy định khác trong thuộc tí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 tiêu siêu dữ liệu mặc định áp dụng cho tất cả mục tiêu khác trong gói. Đây thường là các mục tiêu liên quan đến việc khai báo gói và giấy phép OSS. Hãy xem rules_license để biết ví dụ. |
default_testonly |
Boolean; mặc định là Đặt thuộc tính mặc định
Trong các gói trong |
features |
Chuỗi danh sách; mặc định là Đặt các cờ khác nhau ả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 xây dựng sử dụng để gắn thẻ các gói cần xử lý đặc biệt nào đó. Đừng sử dụng thuộc tính này trừ phi được người làm việc trên hệ thống xây dựng yêu cầu rõ ràng. |
Ví dụ
Phần 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
. Các nội dung khai báo riêng lẻ về chế độ hiển thị trên một quy tắc (nếu có) sẽ ghi đè quy cách 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 đó. Nhãn có thể được tham chiếu 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ị. Mục tiêu hiển thị công khai có thể được tham chiếu từ mọi gói trong cây nguồn. Mục tiêu hiển thị riêng tư chỉ có thể được tham chiếu trong gói riêng của nó (không phải các gói con). Ở giữa các trường hợp cực đoan này, mục tiêu có thể cho phép truy cập vào gói của chính nó 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 nội dung giải thích chi tiết hơn về hệ thống hiển thị, hãy xem thuộc tính mức 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 đã nằm trong một trong các nhóm gói khác được đề cập trong thuộc tính includes
.
Các nhóm gói là mục tiêu về mặt kỹ thuật, nhưng không phải được tạo theo quy tắc và không có bất kỳ biện pháp bảo vệ chế độ hiển thị nào.
Đối số
Thuộc tính | Nội dung mô tả |
---|---|
name |
Tên; bắt buộc Tên duy nhất cho mục tiêu này. |
packages |
Danh sách chuỗi; giá trị mặc định là Danh sách không có hoặc 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 thêm tiền tố Nhóm gói chứa bất kỳ gói nào khớp với ít nhất một trong các thông số kỹ thuật dương và không có thông số kỹ thuật phủ định nào tương ứng. Ví dụ: giá trị Ngoài chế độ hiển thị công khai, không có cách nào để trực tiếp chỉ định các gói bên ngoài kho lưu trữ hiện tại. Nếu thiếu thuộc tính này, thì việc đặt thuộc tính này thành một danh sách trống cũng giống như việc đặt thuộc tính đó thành một 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 chuyển đổi tuần tự dưới dạng 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 sẽ được đưa vào 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 thông số kỹ thuật của gói bị bỏ qua, lưu ý rằng tập hợp các gói cho mỗi nhóm trước tiên được tính toán độc lập, sau đó 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ị bỏ qua trong một nhóm sẽ không ảnh hưởng đến các thông số kỹ thuật trong nhóm khác. |
Ví dụ
Nội dung khai báo package_group
sau đây chỉ định một nhóm gói có tên là "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 nội dung 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 này đượ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.
Là một 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 lật. Tuy nhiên, bạn không nên dựa vào và chủ động di chuyển 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 một nội dung khai báo về chế độ hiển thị; trong trường hợp này, các tệp sẽ hiển thị với các mục tiêu đã chỉ định. Nếu bạn không chỉ định chế độ hiển thị nào, thì các tệp sẽ hiển thị cho mọi gói, ngay cả khi chế độ hiển thị mặc định của gói được chỉ định 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 kiểm thử.
# from //test_data/BUILD exports_files(["golden.txt"])
cụm cầu
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ề một danh sách đường dẫn mới, có thể thay đổi và được sắp xếp. Glob chỉ tìm kiếm các tệp trong gói riêng và chỉ tìm các tệp nguồn (không phải các tệp được tạo hoặc các mục tiêu khác).
Nhãn của tệp nguồn sẽ được đưa vào kết quả nếu đường dẫn tương đối của gói của tệp đó khớp với bất kỳ mẫu include
nào và không có 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. Phân đoạn có thể chứa ký tự đại diện *
: ký tự này khớp với bất kỳ chuỗi con nào trong phân đoạn đường dẫn (kể cả chuỗi con trống), ngoại trừ dấu phân cách thư mục /
. Bạn có thể 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 một phân đoạn đường dẫn độc lập.
foo/bar.txt
khớp chính xác với tệpfoo/bar.txt
trong gói này (trừ phifoo/
là một gói con)foo/*.txt
khớ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à một 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ó.htm
và kết thúc bằng một chuỗi tuỳ ý khác (trừ phifoo/
là một gói con); chẳng hạn nhưfoo/axx.htm
vàfoo/a.html
hoặcfoo/axxx.html
foo/*
khớp với mọi tệp trong thư mụcfoo/
, (trừ phifoo/
là một gói con); nó không khớp với chính thư mụcfoo
ngay cả khiexclude_directories
được đặt thành 0foo/**
khớp với mọi tệp trong mọi thư mục con không phải gói con thuộc thư mục con cấp đầu tiên của góifoo/
; nếuexclude_directories
được đặt thành 0, thì chính thư mụcfoo
cũng khớp với mẫu đó; trong trường hợp này,**
được coi là khớp với phân đoạn đường dẫn 0**/a.txt
khớp vớia.txt
tệp trong thư mục của gói này và các thư mục con không phải gói con.**/bar/**/*.txt
khớp với mọi tệp.txt
trong mọi thư mục con không phải của gói con của gói này, nếu ít nhất một thư mục trên đường dẫn kết quả được gọi làbar
, chẳng hạn nhưxxx/bar/yyy/zzz/a.txt
hoặcbar/a.txt
(hãy nhớ rằng**
cũng khớp với các phân đoạn 0) 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.txt
là 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), các tệp thuộc thư mục loại sẽ bị loại khỏi kết quả (mặc định là 1).
Nếu bạn đặt đối số allow_empty
thành False
, hàm glob
sẽ báo lỗi nếu kết quả là danh sách trống.
Có một số giới hạn và cảnh báo quan trọng:
-
Vì
glob()
chạy trong quá trình đánh giá tệp XÂY DỰNG, nênglob()
chỉ so khớp các tệp trong cây nguồn, chứ không so khớp các tệp không bao giờ được tạo. Nếu đ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 bổ sung một danh sách rõ ràng các tệp đã tạo vào toàn cầu. Hãy xem ví dụ ở bên dưới về:mylib
và:gen_java_srcs
. -
Nếu một quy tắc có cùng tên với tệp nguồn đã so khớp, thì quy tắc đó sẽ "tối ưu hoá" tệp đó.
Để hiểu rõ điều này, hãy nhớ rằng
glob()
trả về danh sách các đườ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 đã 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" (điều này đượ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" (kết quả của nó) thay vì quy tắc "Foo.java". Hãy xem vấn đề GitHub #10395 để biết thêm thông tin chi tiết. - Cụm sao cầu có thể khớp với các tệp trong thư mục con. Đồng thời, tên thư mục con có thể được ký tự đại diện. Tuy nhiên...
-
Nhãn không được phép vượt qua ranh giới của gói và toàn bộ gói không khớp với tệp trong các gói con.
Ví dụ: biểu thức toàn cầu
**/*.cc
trong góix
không bao gồmx/y/z.cc
nếux/y
tồn tại dưới dạng một gói (dưới dạngx/y/BUILD
hoặc một 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 toàn cầu 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 toàn cầu sẽ bao gồmx/y/z.cc
nếu không có gói nào được gọi làx/y
hoặc được đánh dấu là đã xoá bằng cách sử dụng cờ --deleted_packages. - Hạn chế nêu trên áp dụng cho mọi biểu thức toàn cầu, bất kể các biểu thức đó 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
.
sẽ hoàn toàn khớp với cả ký tự đại diện**
và*
. Nếu bạn muốn khớp một tệp ẩn với mẫu phức hợp, mẫu của bạn cần bắt đầu bằng.
. Ví dụ:*
và.*.txt
sẽ khớp với.foo.txt
, nhưng*.txt
sẽ 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 không cần thiết và mức sử dụng 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 "loại trừ". -
Ký tự đại diện "**" có một trường hợp góc: mẫu
"**"
không khớp với đường dẫn thư mục của gói. Điều này có nghĩa làglob(["**"], exclude_directories = 0)
khớp với mọi tệp và thư mục theo cách bắc cầu hoàn toàn trong thư mục của gói hiện tại (nhưng tất nhiên là không chuyển đến các thư mục của gói con – hãy xem ghi chú trước về điều đó).
Nói chung, bạn nên cố gắng cung cấp một tiện ích thích hợp (ví dụ: *.html) thay vì sử dụng một '*' trần cho mẫu toàn cầu. Tên rõ ràng hơn vừa là tự ghi lại tài liệu, vừa đảm bảo rằng bạn không vô tình so khớp các tệp sao lưu hoặc tệp emacs/vi/... tự động lưu.
Khi viết quy tắc xây dựng, bạn có thể liệt kê các thành phần của toàn cầu. Thao tác này cho phép tạo các quy tắc riêng lẻ cho mỗi giá trị đầu vào, chẳng hạn. Xem phần ví dụ về cụm cầu mở rộng bên dưới.
Ví dụ về hình cầu
Tạo thư viện Java được xây dựng từ mọi tệp Java trong thư mục này và tất cả tệp được tạo bằng 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", ], ... )
Đưa tất cả các tệp txt vào thư mục testdata, ngoại trừ thử nghiệm.txt. Xin lưu ý rằng các tệp trong thư mục con của dữ liệu kiểm thử 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 toàn cầu đệ quy (**).
sh_test( name = "mytest", srcs = ["mytest.sh"], data = glob( ["testdata/*.txt"], exclude = ["testdata/experimental.txt"], ), )
Ví dụ về hình cầu đệ quy
Thực hiện kiểm thử phụ thuộc vào tất cả các tệp txt trong thư mục testdata và bất kỳ thư mục con nào trong đó (và 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 giới hạn và cảnh báo ở trên.)
sh_test( name = "mytest", srcs = ["mytest.sh"], data = glob(["testdata/**/*.txt"]), )
Tạo một thư viện được tạo từ mọi 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 chứa thư mục có tên là kiểm thử. 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 khả năng gia tăng bản dựng, từ đó làm tăng thời gian xây dựng.
java_library( name = "mylib", srcs = glob( ["**/*.java"], exclude = ["**/testing/**"], ), )
Ví dụ về khối cầu mở rộng
Tạo một quy tắc gen riêng 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 ba tệp phù hợ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 tạo ra thuộc tính quy tắc có thể định cấu hình.
Thuộc tính này có thể thay thế phần bên phải của hầu hết bất kỳ thuộc tính nào được chỉ định để giá trị của thuộc tính đó phụ thuộc vào cờ Bazel dòng lệnh.
Ví dụ: bạn có thể sử dụng tính năng này để xác định các phần phụ thuộc riêng của 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 chế độ "phát hành".
Sau đây là cách sử dụng cơ bản:
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 bạn có thể định cấu hình thuộc tính srcs
của sh_binary
bằng cách thay thế việc chỉ định danh sách nhãn thông thường bằng lệnh gọi select
giúp ánh xạ các điều kiện cấu hình với các giá trị trùng khớp. Mỗi điều kiện là một tham chiếu nhãn đến config_setting
hoặc constraint_value
. Điều này sẽ "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 bất kỳ danh sách nhãn nào khớp với lệnh gọi hiện tại.
Lưu ý:
- Bạn chỉ cần chọn đúng một điều kiện cho bất kỳ lệnh gọi nào.
- Nếu có nhiều điều kiện trùng khớp và một điều kiện là chuyên môn của các điều kiện khác, thì chuyên môn đó sẽ được ưu tiên. Điều kiện B được coi là đặc điểm của điều kiện A nếu B có tất cả cờ và giá trị ràng buộc giống nhau là 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à độ phân giải chuyên môn không được thiết kế để tạo thứ tự như được minh hoạ trong Ví dụ 2 dưới đây.
- Nếu có nhiều điều kiện trùng khớp và một điều kiện không phải là chuyên môn của các điều kiện còn lại, thì Bazel sẽ không thành công với lỗi, trừ phi tất cả các điều kiện đều phân giải thành cùng một giá trị.
- Nhãn giả đặc biệt
//conditions:default
được xem là khớp nếu không có điều kiện nào khác khớp. Nếu bạn không đặt điều kiện này thì một số quy tắc khác cũng phải đáp ứng để tránh xảy ra lỗi. - Bạn có thể nhúng
select
bên trong một bài tập 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ệ. select
hoạ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ànonconfigurable
trong tài liệu tương thích.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. Tệp này sử dụng mẫu đường dẫn giống nhưglob()
và có thể khớp với mọi gói con là thành phần con trực tiếp của tệp BUILD đang tải. Vui lòng xem glob để biết nội dung giải thích chi tiết và ví dụ về các mẫu bao gồm và loại trừ.Danh sách kết quả các gói con được trả về được sắp xếp theo thứ tự 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 nhất định trong
include
chứ không phả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 của 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, thay vì gọi trực tiếp hàm này, người dùng nên sử dụng mô-đun "gói con" của skylib.