Nhãn

Báo cáo sự cố Xem nguồn

Nhãn là giá trị nhận dạng của một mục tiêu. Một nhãn thông thường ở dạng chính tắc đầy đủ sẽ có dạng như sau:

@@myrepo//my/app/main:app_binary

Phần đầu tiên của nhãn là tên kho lưu trữ, @@myrepo. Cú pháp @ kép cho biết đây là tên kho lưu trữ chính tắc, tên duy nhất trong không gian làm việc. Các nhãn có tên kho lưu trữ chuẩn sẽ xác định mục tiêu một cách rõ ràng, bất kể mục tiêu đó xuất hiện trong ngữ cảnh nào.

Thông thường, tên kho lưu trữ chính tắc là một chuỗi arcane có dạng như @@rules_java~7.1.0~toolchains~local_jdk. Điều phổ biến hơn là các nhãn có apparent tên kho lưu trữ, giống như:

@myrepo//my/app/main:app_binary

Điểm khác biệt duy nhất là tên kho lưu trữ có tiền tố là một @ thay vì hai. Đây là một kho lưu trữ có tên rõ ràng myrepo, có thể khác nhau tuỳ theo ngữ cảnh mà nhãn này xuất hiện.

Trong trường hợp thông thường, nhãn tham chiếu đến cùng một kho lưu trữ mà từ đó nhãn được sử dụng, thì phần tên kho lưu trữ có thể bị bỏ qua. Vì vậy, bên trong @@myrepo nhãn đầu tiên thường được viết là

//my/app/main:app_binary

Phần thứ hai của nhãn là tên gói my/app/main chưa đủ điều kiện. Đường dẫn đến gói tương ứng với thư mục gốc kho lưu trữ. Tên gói lưu trữ và tên gói không đủ điều kiện sẽ cùng với tên gói đủ điều kiện @@myrepo//my/app/main. Khi nhãn đề cập đến cùng một gói được sử dụng, tên gói (và dấu hai chấm) có thể bị bỏ qua (không bắt buộc). Vì vậy, bên trong @@myrepo//my/app/main, nhãn này có thể được viết theo một trong những cách sau:

app_binary
:app_binary

Theo quy ước, dấu hai chấm bị bỏ qua đối với các tệp, nhưng được giữ lại cho các quy tắc. Tuy nhiên, giá trị này không có ý nghĩa quan trọng.

Phần của nhãn sau dấu hai chấm, app_binary là tên mục tiêu không đủ điều kiện. Khi khớp với thành phần cuối cùng của đường dẫn gói, thuộc tính này và dấu hai chấm có thể bị bỏ qua. Vì vậy, hai nhãn này tương đương với nhau:

//my/app/lib
//my/app/lib:lib

Tên của mục tiêu tệp trong thư mục con của gói là đường dẫn của tệp tương ứng với thư mục gốc của gói (thư mục chứa tệp BUILD). Vì vậy, tệp này nằm trong thư mục con my/app/main/testdata của kho lưu trữ:

//my/app/main:testdata/input.txt

Các chuỗi như //my/app@@some_repo//my/app có hai ý nghĩa tuỳ thuộc vào ngữ cảnh sử dụng: khi Bazel yêu cầu một nhãn, thì các chuỗi đó có nghĩa là //my/app:app@@some_repo//my/app:app tương ứng. Tuy nhiên, khi Bazel mong đợi một gói (ví dụ: trong thông số kỹ thuật của package_group), họ sẽ tham chiếu đến gói chứa nhãn đó.

Một lỗi phổ biến trong các tệp BUILD là sử dụng //my/app để tham chiếu đến một gói hoặc đến tất cả mục tiêu trong một gói – điều này không thực hiện được. Hãy nhớ rằng, đối tượng này tương đương với //my/app:app, vì vậy, thành phần này đặt tên cho mục tiêu app trong gói my/app của kho lưu trữ hiện tại.

Tuy nhiên, bạn nên sử dụng //my/app để tham chiếu đến một gói trong thông số kỹ thuật của các tệp package_group hoặc trong .bzl, vì gói này thông báo rõ ràng rằng tên gói là tuyệt đối và được can thiệp vào hệ thống trong thư mục cấp cao nhất của không gian làm việc.

Không thể dùng các nhãn tương đối để tham chiếu đến các mục tiêu trong các gói khác. Trong trường hợp này, bạn phải luôn chỉ định giá trị nhận dạng kho lưu trữ và tên gói. Ví dụ: nếu cây nguồn chứa cả gói my/app và gói my/app/testdata (mỗi thư mục trong hai thư mục này có tệp BUILD riêng), gói sau sẽ chứa một tệp có tên testdepot.zip. Dưới đây là 2 cách (một sai, một cách đúng) để tham chiếu đến tệp này trong //my/app:BUILD:

Saitestdata là một gói khác, vì vậy, bạn không thể sử dụng đường dẫn tương đối

testdata/testdepot.zip

Đúng – tham chiếu đến testdata kèm theo đường dẫn đầy đủ

//my/app/testdata:testdepot.zip

Các nhãn bắt đầu bằng @@// là thông tin tham chiếu đến kho lưu trữ chính. Kho lưu trữ chính vẫn sẽ hoạt động ngay cả từ kho lưu trữ bên ngoài. Do đó, @@//a/b/c khác với //a/b/c khi được tham chiếu từ một kho lưu trữ bên ngoài. Kho lưu trữ trước tham chiếu trở lại kho lưu trữ chính, trong khi kho lưu trữ thứ hai tìm //a/b/c trong chính kho lưu trữ bên ngoài. Điều này đặc biệt cần thiết khi viết các quy tắc trong kho lưu trữ chính tham chiếu đến các mục tiêu trong kho lưu trữ chính, đồng thời sẽ được dùng từ các kho lưu trữ bên ngoài.

Để biết thông tin về các cách tham chiếu đến mục tiêu, hãy xem các mẫu mục tiêu.

Quy cách từ vựng của nhãn

Cú pháp nhãn không khuyến khích sử dụng siêu ký tự có ý nghĩa đặc biệt đối với shell. Điều này giúp tránh việc vô tình trích dẫn các vấn đề và giúp bạn dễ dàng xây dựng các công cụ và tập lệnh thao tác với nhãn, chẳng hạn như Ngôn ngữ truy vấn Bazel.

Dưới đây là thông tin chi tiết chính xác về các tên mục tiêu được phép.

Tên mục tiêu – package-name:target-name

target-name là tên của mục tiêu trong gói. Tên của một quy tắc là giá trị của thuộc tính name trong phần khai báo của quy tắc trong một tệp BUILD; tên của một tệp là tên đường dẫn tương ứng với thư mục chứa tệp BUILD.

Tên mục tiêu phải bao gồm toàn bộ các ký tự được lấy từ tập hợp az, AZ, 09 và các ký hiệu dấu câu !%-@^_"#$&'()*-+,;<=>?[]{|}~/..

Tên tệp phải là tên đường dẫn tương đối ở dạng thông thường, nghĩa là không được bắt đầu cũng như kết thúc bằng dấu gạch chéo (ví dụ: /foofoo/) và cũng không được chứa nhiều dấu gạch chéo liên tiếp làm dấu phân tách đường dẫn (ví dụ: foo//bar). Tương tự như vậy, các tệp tham chiếu cấp cao (..) và tham chiếu thư mục hiện tại (./) đều bị cấm.

Sai – Không sử dụng .. để tham chiếu đến các tệp trong các gói khác

Đúng – Sử dụng //package-name:filename

Mặc dù bạn thường dùng / trong tên của mục tiêu tệp, nhưng hãy tránh dùng / trong tên quy tắc. Đặc biệt, khi sử dụng dạng viết tắt của nhãn, nhãn này có thể khiến người đọc nhầm lẫn. Nhãn //foo/bar/wiz luôn là chữ viết tắt của //foo/bar/wiz:wiz, ngay cả khi không có gói nào như vậy foo/bar/wiz; nhãn này không bao giờ tham chiếu đến //foo:bar/wiz, ngay cả khi mục tiêu đó tồn tại.

Tuy nhiên, có một số trường hợp việc sử dụng dấu gạch chéo rất thuận tiện hoặc đôi khi cần thiết. Ví dụ: tên của một số quy tắc nhất định phải khớp với tệp nguồn chính của các quy tắc đó. Tệp này có thể nằm trong thư mục con của gói.

Tên gói – //package-name:target-name

Tên của một gói là tên của thư mục chứa tệp BUILD, tương ứng với thư mục cấp cao nhất của kho lưu trữ chứa. Ví dụ: my/app.

Ở cấp độ kỹ thuật, Bazel thực thi những điều sau:

  • Ký tự được phép trong tên gói là chữ cái viết thường a đến z, chữ hoa A đến Z, chữ số 0 đến 9, ký tự ! \"#$%&'()*+,-.;<=>?@[]^_`{|} (vâng, có một ký tự dấu cách!) và tất nhiên là dấu gạch chéo lên / (vì đó là dấu phân cách thư mục).
  • Tên gói không được bắt đầu hoặc kết thúc bằng dấu gạch chéo lên /.
  • Tên gói không được chứa chuỗi con //. Việc này không hợp lý ---đường dẫn thư mục tương ứng sẽ là gì?
  • Tên gói không được chứa chuỗi con /./ hoặc /../ hoặc /.../, v.v. Việc thực thi này được thực hiện để tránh nhầm lẫn khi dịch giữa tên gói logic và tên thư mục thực tế, dựa trên ý nghĩa ngữ nghĩa của ký tự dấu chấm trong chuỗi đường dẫn.

Trên thực tế:

  • Đối với ngôn ngữ có cấu trúc thư mục quan trọng đối với hệ thống mô-đun (ví dụ: Java), bạn phải chọn tên thư mục là giá trị nhận dạng hợp lệ trong ngôn ngữ đó. Ví dụ: đừng bắt đầu bằng chữ số ở đầu và tránh các ký tự đặc biệt, đặc biệt là dấu gạch dưới và dấu gạch nối.
  • Mặc dù Bazel hỗ trợ các mục tiêu trong gói gốc của không gian làm việc (ví dụ: //:foo), nhưng bạn nên để trống gói đó để tất cả các gói có ý nghĩa đều có tên mang tính mô tả.

Quy tắc

Quy tắc chỉ định mối quan hệ giữa dữ liệu đầu vào và đầu ra, cũng như các bước tạo dữ liệu đầu ra. Quy tắc có thể thuộc một trong nhiều loại (đôi khi được gọi là lớp quy tắc) để tạo ra các tệp thực thi và thư viện được biên dịch, tệp thực thi kiểm thử và các đầu ra được hỗ trợ khác như mô tả trong phần Xây dựng bách khoa toàn thư.

Các tệp BUILD khai báo mục tiêu bằng cách gọi quy tắc.

Trong ví dụ bên dưới, chúng ta thấy phần khai báo của mục tiêu my_app bằng cách sử dụng quy tắc cc_binary.

cc_binary(
    name = "my_app",
    srcs = ["my_app.cc"],
    deps = [
        "//absl/base",
        "//absl/strings",
    ],
)

Mỗi lệnh gọi quy tắc đều có một thuộc tính name (phải là tên mục tiêu hợp lệ) khai báo mục tiêu trong gói của tệp BUILD.

Mỗi quy tắc có một tập hợp thuộc tính; các thuộc tính áp dụng cho một quy tắc nhất định và ý nghĩa cũng như ngữ nghĩa của mỗi thuộc tính là một chức năng của loại quy tắc đó; hãy xem phần Tạo bách khoa toàn thư để biết danh sách các quy tắc và thuộc tính tương ứng. Mỗi thuộc tính có một tên và một loại. Một số loại phổ biến mà một thuộc tính có thể có là số nguyên, nhãn, danh sách nhãn, chuỗi, danh sách chuỗi, nhãn đầu ra, danh sách nhãn đầu ra. Không phải quy tắc nào cũng cần chỉ định tất cả các thuộc tính. Do đó, các thuộc tính tạo thành một từ điển từ khoá (tên) đến các giá trị được nhập không bắt buộc.

Thuộc tính srcs có trong nhiều quy tắc có loại "danh sách nhãn"; giá trị của thuộc tính này (nếu có) là một danh sách các nhãn, mỗi nhãn là tên của một mục tiêu sẽ là dữ liệu đầu vào của quy tắc này.

Trong một số trường hợp, tên của loại quy tắc có phần tuỳ ý và điều thú vị hơn là tên của các tệp do quy tắc tạo ra và điều này đúng với quy tắc. Để biết thêm thông tin, hãy xem phần Quy tắc chung: gen thống.

Trong các trường hợp khác, tên rất quan trọng: đối với các quy tắc *_binary*_test, chẳng hạn như tên quy tắc sẽ xác định tên của tệp thực thi do bản dựng tạo ra.

Biểu đồ không chu kỳ có định hướng trên các mục tiêu được gọi là biểu đồ mục tiêu hoặc biểu đồ phần phụ thuộc của bản dựng và là miền mà Công cụ truy vấn Bazel hoạt động trên đó.

Mục tiêu XÂY DỰNG tệp