Hàm

Báo cáo vấn đề Xem nguồn

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 tiếp theo trong gói. Tệp được sử dụng nhiều nhất một lần trong một gói (BUILD tệp).

Hàm package() phải được gọi 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 Nội dung mô tả
default_applicable_licenses

Bí danh của default_package_metadata.

default_visibility

List of labels; optional

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ỉ định chế độ hiển thị trong thuộc tính này, trừ trường hợp có quy định khác trong thuộc tính visibility của quy tắc. Để 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ề khả năng hiển thị. Chế độ hiển thị mặc định của gói không áp dụng cho exports_files. Những tệp này được công khai theo mặc định.

default_deprecation

String; optional

Đặt thông báo deprecation mặc định cho tất cả các quy tắc trong gói này.

default_package_metadata

List of labels; optional

Đặt danh sách mục tiêu siêu dữ liệu mặc định để áp dụng cho tất cả các mục tiêu khác trong gói. Đây thường là những mục tiêu liên quan đến việc khai báo gói và OSS. Xem rules_license để xem ví dụ.

default_testonly

Boolean; optional; default is False except as noted

Đặt thuộc tính testonly mặc định cho tất cả các quy tắc trong gói này.

Trong các gói bên dưới javatests, giá trị mặc định là 1.

features

List strings; optional

Đặ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 đó. Không sử dụng thuộc tính này trừ phi được một người làm việc trên hệ thống xây dựng yêu cầu rõ ràng.

Ví dụ

Nội dung 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. Khai báo từng chế độ hiển thị riêng lẻ về một quy tắc, nếu có, sẽ ghi đè thông số kỹ thuật này.
package(default_visibility = ["//foo:target"])

package_group [nhóm_gói]

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 hàng chủ yếu 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ột mục tiêu hiển thị riêng tư chỉ có thể được tham chiếu trong gói riêng (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. Để hiểu rõ hơn về hệ thống hiển thị, hãy xem thuộc tính chế độ 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 đưa vào một trong các nhóm gói khác được đề cập trong thuộc tính includes.

Nhóm gói là mục tiêu về mặt kỹ thuật, nhưng không được tạo bởi các quy tắc và không có bất kỳ biện pháp bảo vệ hiển thị nào.

Đối số

Thuộc tính Nội dung mô tả
name

Name; required

Tên duy nhất cho mục tiêu này.

packages

List of strings; optional

Danh sách từ 0 trở lên cho thông số kỹ thuật gói.

Mỗi chuỗi đặc tả gói có thể có một trong các dạng sau:

  1. Tên đầy đủ của một gói mà không có kho lưu trữ, bắt đầu bằng dấu gạch chéo đôi. Ví dụ: //foo/bar chỉ định gói có tên đó và nằm trong cùng một kho lưu trữ với nhóm gói.
  2. Như trên, nhưng có /... theo sau. Ví dụ: //foo/... chỉ định tập hợp //foo và tất cả các gói con. //... chỉ định tất cả các gói trong kho lưu trữ hiện tại.
  3. Các chuỗi public hoặc private lần lượt chỉ định mọi gói hoặc không có gói nào. (Biểu mẫu này yêu cầu thiết lập cờ --incompatible_package_group_has_public_syntax.)

Ngoài ra, hai loại thông số kỹ thuật gói đầu tiên cũng có thể được bắt đầu bằng - để cho biết chúng thuộc thể bị bỏ qua.

Nhóm gói chứa bất kỳ gói nào khớp với ít nhất một trong số các thông số dương và không có thông số phủ định nào. Ví dụ: giá trị [//foo/..., -//foo/tests/...] bao gồm tất cả các gói con của //foo cũng không phải là gói con của //foo/tests. (Bản thân //foo cũng được thêm vào, còn //foo/tests thì không được đưa vào.)

Ngoài khả năng hiển thị công khai, không có cách nào để chỉ định trực tiếp 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, thuộc tính này giống như khi đặt thành một danh sách trống và cũng giống như khi đặt thuộc tính này thành một danh sách chỉ chứa private.

Lưu ý: Trước Bazel 6.0, thông số kỹ thuật //... đã có hành vi cũ giống public. Hành vi này được khắc phục khi bạn bật --incompatible_fix_package_group_reporoot_syntax và đây là chế độ mặc định sau Bazel 6.0.

Lưu ý: Trước Bazel 6.0, khi thuộc tính này được chuyển đổi tuần tự như một phần của bazel query --output=proto (hoặc --output=xml), dấu gạch chéo ở đầu sẽ bị bỏ qua. Ví dụ: //pkg/foo/... sẽ xuất ra dưới dạng \"pkg/foo/...\". Hành vi này được khắc phục khi bạn bật --incompatible_package_group_includes_double_slash, đây là chế độ mặc định sau Bazel 6.0.

includes

List of labels; optional

Các nhóm gói khác có trong gói 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 các nhóm gói tham chiếu được đưa vào nhóm gói này. Đây là bắc cầu – nếu nhóm gói a bao gồm nhóm gói bb bao gồm nhóm gói c, thì mọi gói trong c cũng sẽ là thành viên của a.

Khi được sử dụng cùng với thông số kỹ thuật của gói bị bỏ qua, 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 và sau đó kết hợp với nhau. Điều này có nghĩa là quy cách bị từ chối trong một nhóm người dùng không ảnh hưởng đến thông số kỹ thuật trong một 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à "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 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"],
)

xuất_tệp

exports_files([label, ...], visibility, licenses)

exports_files() chỉ định danh sách các tệp thuộc gói này và đượ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ị tệp.

Là một hành vi cũ, các tệp được đề cập đến dưới dạng đầu vào của một quy tắc sẽ đượ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, hành vi này không nên dựa vào mà chủ động di chuyển khỏi.

Đối số

Đối số là một 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 phần khai báo về khả năng hiển thị. Trong trường hợp này, tệp sẽ hiển thị theo 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ẽ xuất hiện trong 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 licenses.

Ví dụ:

Ví dụ sau đây sẽ 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 trong tệp thuộc tính data của quy trình kiểm thử.

# from //test_data/BUILD

exports_files(["golden.txt"])

hình 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 phù hợp với một số mẫu đường dẫn nhất định và trả về 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 tệp nguồn (không phải 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 gói của tệp khớp với bất kỳ mẫu include nào và không mẫu nào trong số các mẫu exclude.

Danh sách includeexclude chứa các mẫu đường dẫn liên quan đến 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 có thể chứa ký tự đại diện *: thuộc tính này khớp với mọi chuỗi con trong phân đoạn đường dẫn (kể cả chuỗi con trống), ngoại trừ dấu phân tá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 hơn, nhưng bạn phải khai báo ký tự đại diện này dưới dạng một phân đoạn đường dẫn độc lập.

Ví dụ:
  • foo/bar.txt khớp chính xác với tệp foo/bar.txt trong gói này
  • foo/*.txt khớp với mọi tệp trong thư mục foo/ nếu tệp kết thúc bằng .txt (trừ khi foo/ là một gói con)
  • foo/a*.htm* khớp với mọi tệp trong thư mục foo/ bắt đầu bằng a, 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; chẳng hạn như foo/axx.htmfoo/a.html hoặc foo/axxx.html
  • **/a.txt khớp với mọi tệp a.txt trong mọi thư mục con của gói này
  • **/bar/**/*.txt khớp với mọi tệp .txt trong mọi thư mục 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ặc bar/a.txt (hãy nhớ rằng ** cũng khớp với 0 phân đoạn) hoặc bar/zzz/a.txt
  • ** khớp với mọi tệp trong mọi thư mục con của gói này
  • foo**/a.txt là một mẫu không hợp lệ vì ** phải tự đứng một phân đoạn

Nếu đối số exclude_directories được bật (được đặt thành 1), các tệp của thư mục kiểu sẽ bị bỏ qua trong kết quả (mặc định 1).

Nếu đối số allow_empty được đặt thành False, hàm glob sẽ bị lỗi nếu kết quả lại là danh sách trống.

Có một số giới hạn và cảnh báo quan trọng:

  1. glob() chạy trong quá trình đánh giá tệp BUILD nên glob() chỉ khớp các tệp trong cây nguồn và không bao giờ tạo tệp. 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, bạn phải thêm danh sách rõ ràng các tệp được tạo vào hình cầu. Hãy xem ví dụ bên dưới về :mylib:gen_java_srcs.

  2. Nếu một quy tắc có cùng tên với tệp nguồn trùng khớp, thì quy tắc đó sẽ "bóng" tệp đó.

    Để hiểu điều này, hãy nhớ rằng glob() sẽ trả về danh sách các đường dẫn, vì vậy, việc sử dụng glob() 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ê các đường dẫn phù hợp một cách rõ ràng. Ví dụ: nếu glob() trả về ["Foo.java", "bar/Baz.java"] nhưng cũng có một quy tắc trong gói có tên "Foo.java" (được phép, mặc dù Bazel đã cảnh báo về việc này), thì trình sử dụng glob() sẽ sử dụng quy tắc "Foo.java" (kết quả của quy tắc này) thay vì tệp "Foo.java". Hãy xem Vấn đề GitHub #10395 để biết thêm thông tin chi tiết.

  3. Glob có thể khớp các tệp trong thư mục con. Tên thư mục con có thể được dùng ký tự đại diện. Tuy nhiên...
  4. Nhãn không được phép vượt quá ranh giới gói và hình cầu không khớp với tệp trong gói con.

    Ví dụ: biểu thức hình cầu **/*.cc trong gói x không bao gồm x/y/z.cc nếu x/y tồn tại dưới dạng một gói (dưới dạng x/y/BUILD hoặc một nơi nào 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 hình 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 hình cầu sẽ bao gồm x/y/z.cc nếu không có gói nào được gọi là x/y hoặc gói này được đánh dấu là đã xoá bằng cờ --deleted_packages.

  5. Hạn chế trên áp dụng cho mọi biểu thức hình cầu, bất kể biểu thức đó sử dụng ký tự đại diện nào.
  6. Một tệp ẩn có tên tệp bắt đầu bằng . sẽ hoàn toàn khớp với ký tự đại diện ***. Nếu muốn khớp tệp ẩn với mẫu ghép, bạn cần bắt đầu bằng .. Ví dụ: *.*.txt sẽ khớp với .foo.txt, còn *.txt thì không. Các thư mục ẩn cũng được so khớp theo cùng cách. 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 mức sử dụng bộ nhớ cũng như số lượng tệp không hợp lệ. Để 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ừ".
  7. 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. Tức là glob(["**"], exclude_directories = 0) khớp hoàn toàn với tất cả tệp và thư mục trong thư mục của gói hiện tại (nhưng tất nhiên là không đi vào thư mục của gói con – hãy xem lưu ý trước).

Nói chung, bạn nên cố gắng cung cấp một phần mở rộng thích hợp (ví dụ: *.html) thay vì sử dụng '*' trần cho mẫu hình cầu. 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 tệp dự phòng 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 phần tử của hình cầu. Điều này cho phép tạo các quy tắc riêng lẻ cho mọi thông tin đầu vào chẳng hạn. Hãy xem phần ví dụ về hình cầu mở rộng bên dưới.

Ví dụ về Glob

Tạo một 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 do quy tắc :gen_java_srcs tạo ra.

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 dữ liệu kiểm tra thư mục ngoại trừ tệp CSV thử nghiệm. Lưu ý rằng các tệp trong thư mục con của dữ liệu thử nghiệm sẽ không được bao gồm. Nếu bạn muốn đưa các tệp đó vào, hãy sử dụng một hình cầu đệ quy (**).

sh_test(
    name = "mytest",
    srcs = ["mytest.sh"],
    data = glob(
        ["testdata/*.txt"],
        exclude = ["testdata/experimental.txt"],
    ),
)

Ví dụ về Glob lặp lại

Yêu cầu kiểm thử phụ thuộc vào tất cả tệp txt trong thư mục dữ liệu kiểm thử và mọi thư mục con của thư mục đó (và các thư mục con của thư mục đó, v.v.). Các thư mục con chứa tệp BUILD bị bỏ qua. (Xem các giới hạn và lưu ý ở trên.)

sh_test(
    name = "mytest",
    srcs = ["mytest.sh"],
    data = glob(["testdata/**/*.txt"]),
)

Tạo một 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ả thư mục con, ngoại trừ những thư mục có đường dẫn bao gồm một thư mục có tên là kiểm thử. Bạn nên tránh sử dụng mẫu này nếu có thể vì điều này có thể làm giảm mức độ tăng dần của bản dựng, từ đó tăng thời gian tạo bản 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 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 là 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ả quy tắ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 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ía bên phải của gần như bất kỳ thuộc tính nào được gán, vì vậy 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 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" so với "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 thuộc tính srcs của sh_binary có thể định cấu hình bằng cách thay thế việc gán danh sách nhãn thông thường bằng lệnh gọi select liên kết các điều kiện cấu hình với các giá trị phù hợp. 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 nhóm 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 ý:

  • Chọn một điều kiện cho bất kỳ lệnh gọi nào.
  • Nếu nhiều điều kiện 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 xem là chuyên môn về điều kiện A nếu B có tất cả cờ và giá trị ràng buộc giống với A cộng với một số cờ hoặc giá trị ràng buộc khác. Điều này cũng có nghĩa là tính năng phân giải chuyên môn không được thiết kế để tạo thứ tự như ví dụ 2 dưới đây.
  • Nếu nhiều điều kiện khớp với nhau và một điều kiện không phải là chuyên môn của tất cả các điều kiện khác, thì Bazel sẽ gặp lỗi, trừ khi tất cả các điều kiện có cùng 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 điều kiện này bị bỏ qua, một số quy tắc khác phải khớp để tránh lỗi.
  • Bạn có thể nhúng select bên trong một thuộc tính lớn hơn được gán. Vì vậy, srcs = ["common.sh"] + select({ ":conditionA": ["myrule_a.sh"], ...}) 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ả, thuộc tính. Các thuộc tính không tương thích được đánh dấu nonconfigurable trong tài liệu.

    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 các mẫu đường dẫn giống như glob() và có thể khớp với bất kỳ gói con nào là thành phần con trực tiếp của tệp BUILD hiện đang tải. Hãy xem nội dung 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 các gói con trả về được sắp xếp theo thứ tự được sắp xếp và chứa các đường dẫn liên quan đến gói tải hiện tại khớp với các mẫu đã cho trong include chứ không phải trong các mẫu trong exclude.

    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/sub/BUILD
    # foo/sub/deeper/BUILD
    #
    # In foo/BUILD a call to
    subs = subpackages(include = ["**"])
    
    # results in subs == ["sub", "bar/baz"]
    #
    # 'sub/deeper' is not included because it is a subpackage of 'foo/sub' not of
    # 'foo'
    

    Nhìn chung, thay vì trực tiếp gọi hàm này, người dùng nên sử dụng mô-đun 'subpackages' của skylib.