Trang này đề cập đến hai hệ thống hiển thị của Bazel: mức độ hiển thị mục tiêu và mức độ hiển thị tải.
Cả hai loại chế độ hiển thị này đều giúp các nhà phát triển khác phân biệt giữa API công khai của thư viện và thông tin triển khai chi tiết, đồng thời giúp thực thi cấu trúc khi không gian làm việc của bạn tăng lên. Bạn cũng có thể sử dụng chế độ hiển thị khi ngừng sử dụng một video công khai API để cho phép người dùng hiện tại trong khi từ chối người dùng mới.
Khả năng hiển thị mục tiêu
Chế độ hiển thị của mục tiêu kiểm soát những người có thể phụ thuộc vào mục tiêu của bạn, tức là những người có thể
sử dụng nhãn mục tiêu bên trong một thuộc tính như deps
.
A
mục tiêu sẽ hiển thị cho B
mục tiêu nếu chúng ở trong cùng một gói, hoặc nếu
A
cấp chế độ hiển thị cho gói của B
. Do đó, gói là đơn vị của
mức độ chi tiết để quyết định có cho phép truy cập hay không. Nếu B
phụ thuộc vào A
nhưng A
không hiển thị với B
, thì mọi nỗ lực tạo B
sẽ không thành công trong khoảng thời gian
phân tích.
Lưu ý rằng việc cấp chế độ hiển thị cho một gói không tự cấp chế độ hiển thị vào các gói con của nó. Để biết thêm thông tin chi tiết về gói và các gói con, hãy xem Khái niệm và thuật ngữ.
Đối với hoạt động tạo nguyên mẫu, bạn có thể tắt chế độ thực thi chế độ hiển thị mục tiêu bằng cách đặt
cờ --check_visibility=false
. Bạn không nên thực hiện việc này khi sử dụng phiên bản phát hành công khai trong
đã gửi mã.
Cách chính để kiểm soát chế độ hiển thị là thông qua
Thuộc tính visibility
đang bật
mục tiêu quy tắc. Phần này mô tả định dạng của thuộc tính này và cách
xác định khả năng hiển thị của mục tiêu.
Thông số kỹ thuật về chế độ hiển thị
Tất cả mục tiêu quy tắc đều có thuộc tính visibility
nhận danh sách các nhãn. Một
nhãn có một trong các biểu mẫu sau. Ngoại trừ biểu mẫu cuối cùng,
chỉ là các phần giữ chỗ cú pháp không tương ứng với bất kỳ mục tiêu thực tế nào.
"//visibility:public"
: Cấp quyền truy cập vào tất cả các gói. (Có thể không kết hợp được với bất kỳ quy cách nào khác)."//visibility:private"
: Không cấp thêm quyền truy cập nào khác; chỉ mục tiêu trong gói này có thể sử dụng mục tiêu này. (Không thể kết hợp với bất kỳ sản phẩm nào khác specification.)"//foo/bar:__pkg__"
: Cấp quyền truy cập vào//foo/bar
(nhưng không cấp quyền truy cập vào tài khoản này) gói con)."//foo/bar:__subpackages__"
: Cấp quyền truy cập//foo/bar
và tất cả gói con trực tiếp và gián tiếp."//some_pkg:my_package_group"
: Cấp quyền truy cập vào tất cả các gói đều thuộcpackage_group
đã cho.- Nhóm gói sử dụng
cú pháp khác cho
chỉ định các gói. Trong một nhóm gói, biểu mẫu
"//foo/bar:__pkg__"
và"//foo/bar:__subpackages__"
lần lượt là được thay thế bằng"//foo/bar"
và"//foo/bar/..."
. Tương tự,"//visibility:public"
và"//visibility:private"
chỉ là"public"
và"private"
.
- Nhóm gói sử dụng
cú pháp khác cho
chỉ định các gói. Trong một nhóm gói, biểu mẫu
Ví dụ: nếu //some/package:mytarget
có visibility
được đặt thành
[":__subpackages__", "//tests:__pkg__"]
, thì đối tượng này có thể dùng đối tượng này
là một phần của cây nguồn //some/package/...
, cũng như các mục tiêu được xác định
trong //tests/BUILD
, nhưng không phải bởi các mục tiêu được xác định trong //tests/integration/BUILD
.
Phương pháp hay nhất: Để hiển thị nhiều mục tiêu cho cùng một nhóm
hãy sử dụng package_group
thay vì lặp lại danh sách trong mỗi gói
thuộc tính visibility
của mục tiêu. Điều này làm tăng khả năng đọc và ngăn
danh sách không được đồng bộ hoá.
Chế độ hiển thị mục tiêu của quy tắc
Chế độ hiển thị của mục tiêu quy tắc là:
Giá trị của thuộc tính
visibility
, nếu được đặt; hoặc khácGiá trị của thuộc tính
default_visibility
đối số của câu lệnhpackage
trong tệpBUILD
của mục tiêu, nếu có thông tin khai báo như vậy; hoặc khác//visibility:private
.
Phương pháp hay nhất: Tránh đặt default_visibility
ở chế độ công khai. Có thể
thuận tiện cho việc tạo nguyên mẫu hoặc trong các cơ sở mã nhỏ, nhưng có nguy cơ vô tình
việc tạo mục tiêu công khai sẽ tăng lên khi cơ sở mã phát triển. Tốt hơn là nên
nêu rõ mục tiêu nào là một phần của giao diện công khai của gói.
Ví dụ:
Tệp //frobber/bin/BUILD
:
# This target is visible to everyone
cc_binary(
name = "executable",
visibility = ["//visibility:public"],
deps = [":library"],
)
# This target is visible only to targets declared in the same package
cc_library(
name = "library",
# No visibility -- defaults to private since no
# package(default_visibility = ...) was used.
)
# This target is visible to targets in package //object and //noun
cc_library(
name = "subject",
visibility = [
"//noun:__pkg__",
"//object:__pkg__",
],
)
# See package group "//frobber:friends" (below) for who can
# access this target.
cc_library(
name = "thingy",
visibility = ["//frobber:friends"],
)
Tệp //frobber/BUILD
:
# This is the package group declaration to which target
# //frobber/bin:thingy refers.
#
# Our friends are packages //frobber, //fribber and any
# subpackage of //fribber.
package_group(
name = "friends",
packages = [
"//fribber/...",
"//frobber",
],
)
Chế độ hiển thị mục tiêu tệp đã tạo
Mục tiêu tệp đã tạo có cùng chế độ hiển thị với mục tiêu quy tắc tạo ra nó.
Chế độ hiển thị đích đến của tệp nguồn
Bạn có thể đặt rõ chế độ hiển thị của mục tiêu tệp nguồn bằng cách gọi
exports_files
. Khi không có visibility
được truyền đến exports_files
, nó sẽ làm cho chế độ hiển thị công khai.
Không được dùng exports_files
để ghi đè chế độ hiển thị của tệp đã tạo.
Đối với các mục tiêu tệp nguồn không xuất hiện trong lệnh gọi đến exports_files
, phương thức
chế độ hiển thị phụ thuộc vào giá trị của cờ
--incompatible_no_implicit_file_export
:
Nếu bạn đặt cờ này, chế độ hiển thị sẽ ở chế độ riêng tư.
Nếu không, hành vi cũ sẽ được áp dụng: Chế độ hiển thị giống với
default_visibility
của tệpBUILD
hoặc ở chế độ riêng tư nếu chế độ hiển thị mặc định là chưa được chỉ định.
Tránh dựa vào hành vi cũ. Luôn viết một exports_files
bất cứ khi nào đích tệp nguồn cần chế độ hiển thị không ở chế độ riêng tư.
Phương pháp hay nhất: Khi có thể, hãy hiển thị mục tiêu quy tắc thay vì
tệp nguồn. Ví dụ: thay vì gọi exports_files
trên tệp .java
,
gói tệp này trong một mục tiêu java_library
không riêng tư. Mục tiêu chung của quy tắc
chỉ nên tham chiếu trực tiếp các tệp nguồn nằm trong cùng một gói.
Ví dụ:
Tệp //frobber/data/BUILD
:
exports_files(["readme.txt"])
Tệp //frobber/bin/BUILD
:
cc_binary(
name = "my-program",
data = ["//frobber/data:readme.txt"],
)
Chế độ hiển thị chế độ cài đặt cấu hình
Trước đây, Bazel không thực thi chế độ hiển thị đối với
Các mục tiêu config_setting
được tham chiếu trong các khoá của select()
. Có
là 2 cờ để xoá hành vi cũ này:
--incompatible_enforce_config_setting_visibility
cho phép kiểm tra khả năng hiển thị của các mục tiêu này. Để hỗ trợ quá trình di chuyển, cũng khiến mọiconfig_setting
không chỉ địnhvisibility
trở thành được coi là công khai (bất kểdefault_visibility
ở cấp gói).--incompatible_config_setting_private_default_visibility
khiếnconfig_setting
không chỉ địnhvisibility
tuân theodefault_visibility
của gói và để dự phòng chế độ hiển thị riêng tư, chỉ giống như mọi mục tiêu quy tắc khác. Trang web này sẽ không hoạt động nếu Bạn chưa đặt--incompatible_enforce_config_setting_visibility
.
Tránh dựa vào hành vi cũ. Mọi config_setting
nhằm mục đích
được dùng bên ngoài gói hiện tại sẽ có visibility
rõ ràng, nếu giá trị
gói chưa chỉ định default_visibility
phù hợp.
Chế độ hiển thị mục tiêu của nhóm gói
Các mục tiêu package_group
không có thuộc tính visibility
. Chúng luôn
hiển thị công khai.
Mức độ hiển thị của các phần phụ thuộc ngầm ẩn
Một số quy tắc có phần phụ thuộc ngầm ẩn –
các phần phụ thuộc không được nêu trong tệp BUILD
nhưng vốn có
mỗi lần thực hiện quy tắc đó. Ví dụ: quy tắc cc_library
có thể tạo một
sự phụ thuộc ngầm ẩn từ mỗi quy tắc nhắm mục tiêu đến một mục tiêu có thể thực thi
đại diện cho trình biên dịch C++.
Chế độ hiển thị của phần phụ thuộc ngầm ẩn đó được kiểm tra theo
gói chứa tệp .bzl
mà trong đó quy tắc (hoặc khung hình) được xác định. Trong
ví dụ của chúng ta, trình biên dịch C++ có thể ở chế độ riêng tư miễn là nó tồn tại trong cùng một
gói làm định nghĩa của quy tắc cc_library
. Dự phòng, nếu
phần phụ thuộc ngầm ẩn không hiển thị trong định nghĩa, nó sẽ được kiểm tra bằng
đối với mục tiêu cc_library
.
Bạn có thể thay đổi hành vi này bằng cách tắt
--incompatible_visibility_private_attributes_at_definition
.
Khi bạn tắt chính sách này, các phần phụ thuộc ngầm ẩn sẽ được xử lý giống như mọi phần phụ thuộc khác.
Điều này có nghĩa là mục tiêu cần phụ thuộc vào (chẳng hạn như trình biên dịch C++) phải
hiển thị cho mọi lần thực hiện quy tắc. Trong thực tế, điều này thường có nghĩa là mục tiêu
phải có chế độ hiển thị công khai.
Nếu bạn muốn hạn chế việc sử dụng quy tắc cho các gói nhất định, hãy sử dụng load visibility (chế độ hiển thị tải).
Chế độ hiển thị khi tải
Chế độ hiển thị tải kiểm soát việc tệp .bzl
có thể được tải từ các
Tệp BUILD
hoặc .bzl
bên ngoài gói hiện tại.
Giống như cách chế độ hiển thị mục tiêu bảo vệ mã nguồn được đóng gói
theo mục tiêu, chế độ hiển thị của nội dung tải sẽ bảo vệ logic bản dựng được đóng gói bởi .bzl
tệp. Ví dụ: tác giả tệp BUILD
có thể muốn tính đến một số yếu tố lặp lại
định nghĩa mục tiêu thành macro trong tệp .bzl
. Không bảo vệ tải
chế độ hiển thị, họ có thể thấy macro được các cộng tác viên khác sử dụng lại trong
cùng một không gian làm việc, để sửa đổi macro, bản dựng.
Xin lưu ý rằng tệp .bzl
có thể có hoặc không có đích tệp nguồn tương ứng.
Nếu có thì không thể đảm bảo rằng khả năng hiển thị tải và mục tiêu
sẽ có mức độ hiển thị trùng khớp. Tức là cùng một tệp BUILD
có thể tải
.bzl
nhưng không liệt kê tệp này trong srcs
của filegroup
,
hoặc ngược lại. Điều này đôi khi có thể gây ra sự cố cho các quy tắc muốn sử dụng
.bzl
làm mã nguồn, chẳng hạn như để tạo hoặc kiểm thử tài liệu.
Để tạo nguyên mẫu, bạn có thể tắt chế độ thực thi chế độ hiển thị tải bằng cách đặt
--check_bzl_visibility=false
. Giống như với --check_visibility=false
, thao tác này sẽ
chưa thể thực hiện đối với mã đã gửi.
Chế độ hiển thị tải có sẵn kể từ Bazel 6.0.
Khai báo chế độ hiển thị tải
Để đặt chế độ hiển thị tải của tệp .bzl
, hãy gọi phương thức
visibility()
từ trong tệp.
Đối số cho visibility()
là một danh sách thông số kỹ thuật của gói, giống như
thuộc tính packages
của
package_group
. Tuy nhiên, visibility()
không chấp nhận gói phủ định
thông số kỹ thuật.
Lệnh gọi đến visibility()
chỉ được thực hiện một lần cho mỗi tệp, ở cấp cao nhất (không phải
bên trong một hàm) và tốt nhất là ngay sau câu lệnh load()
.
Không giống như chế độ hiển thị mục tiêu, chế độ hiển thị của tệp tải mặc định luôn là công khai. Tệp
không gọi visibility()
luôn có thể tải từ bất cứ đâu trong
Workspace. Bạn nên thêm visibility("private")
vào đầu bất kỳ
tệp .bzl
mới không nhằm mục đích sử dụng cụ thể bên ngoài gói.
Ví dụ:
# //mylib/internal_defs.bzl
# Available to subpackages and to mylib's tests.
visibility(["//mylib/...", "//tests/mylib/..."])
def helper(...):
...
# //mylib/rules.bzl
load(":internal_defs.bzl", "helper")
# Set visibility explicitly, even though public is the default.
# Note the [] can be omitted when there's only one entry.
visibility("public")
myrule = rule(
...
)
# //someclient/BUILD
load("//mylib:rules.bzl", "myrule") # ok
load("//mylib:internal_defs.bzl", "helper") # error
...
Phương pháp hiển thị tải
Phần này mô tả các mẹo để quản lý thông tin khai báo về chế độ hiển thị tải.
Phân tích khả năng hiển thị
Khi nhiều tệp .bzl
có cùng chế độ hiển thị, có thể bạn nên
đưa thông số kỹ thuật của gói vào một danh sách chung. Ví dụ:
# //mylib/internal_defs.bzl
visibility("private")
clients = [
"//foo",
"//bar/baz/...",
...
]
# //mylib/feature_A.bzl
load(":internal_defs.bzl", "clients")
visibility(clients)
...
# //mylib/feature_B.bzl
load(":internal_defs.bzl", "clients")
visibility(clients)
...
Điều này giúp tránh tình trạng sai lệch vô tình giữa các tệp .bzl
khác nhau
hiển thị. Việc này cũng dễ đọc hơn khi danh sách clients
lớn.
Soạn thảo hiển thị
Đôi khi, tệp .bzl
có thể cần hiển thị với danh sách cho phép
bao gồm nhiều danh sách cho phép nhỏ hơn. Điều này tương tự như cách
package_group
có thể kết hợp các package_group
khác thông qua
includes
.
Giả sử bạn không dùng macro được sử dụng rộng rãi. Bạn muốn phòng trưng bày chỉ hiển thị cho người dùng hiện tại và cho các gói do nhóm của bạn sở hữu. Bạn có thể viết:
# //mylib/macros.bzl
load(":internal_defs.bzl", "our_packages")
load("//some_big_client:defs.bzl", "their_remaining_uses")
# List concatenation. Duplicates are fine.
visibility(our_packages + their_remaining_uses)
Loại bỏ trùng lặp bằng các nhóm gói
Không giống như chế độ hiển thị mục tiêu, bạn không thể xác định chế độ hiển thị tải theo
package_group
. Nếu bạn muốn sử dụng lại cùng một danh sách cho phép cho cả hai mục tiêu
khả năng hiển thị và khả năng hiển thị tải, tốt nhất bạn nên di chuyển danh sách gói
vào tệp .bzl, trong đó cả hai loại nội dung khai báo đều có thể tham chiếu đến
nó. Xây dựng dựa trên ví dụ này trong nội dung Phân tích khả năng hiển thị
ở trên, bạn có thể viết:
# //mylib/BUILD
load(":internal_defs", "clients")
package_group(
name = "my_pkg_grp",
packages = clients,
)
Phương thức này chỉ hiệu quả nếu danh sách không chứa gói phủ định nào thông số kỹ thuật.
Bảo vệ các biểu tượng riêng lẻ
Không thể tải bất kỳ biểu tượng Starlark nào có tên bắt đầu bằng dấu gạch dưới
tệp khác. Điều này giúp dễ dàng tạo các biểu tượng riêng tư, nhưng không cho phép
bạn chia sẻ các biểu tượng này với một nhóm giới hạn các tệp đáng tin cậy. Mặt khác
thì chế độ hiển thị tải cho phép bạn kiểm soát xem gói nào khác có thể xem
.bzl file
, nhưng không cho phép bạn ngăn chặn mọi biểu tượng không bị gạch dưới
đang được tải.
May mắn là bạn có thể kết hợp hai tính năng này để kiểm soát chi tiết hơn.
# //mylib/internal_defs.bzl
# Can't be public, because internal_helper shouldn't be exposed to the world.
visibility("private")
# Can't be underscore-prefixed, because this is
# needed by other .bzl files in mylib.
def internal_helper(...):
...
def public_util(...):
...
# //mylib/defs.bzl
load(":internal_defs", "internal_helper", _public_util="public_util")
visibility("public")
# internal_helper, as a loaded symbol, is available for use in this file but
# can't be imported by clients who load this file.
...
# Re-export public_util from this file by assigning it to a global variable.
# We needed to import it under a different name ("_public_util") in order for
# this assignment to be legal.
public_util = _public_util
Tìm lỗi mã nguồn của trình tạo bản dựng bzl- visibility
Có một công cụ tìm lỗi mã nguồn của trình tạo bản dựng
đưa ra cảnh báo nếu người dùng tải tệp từ thư mục có tên internal
hoặc private
, khi tệp của người dùng không nằm ở bên dưới tệp mẹ của tệp đó
thư mục. Công cụ tìm lỗi mã nguồn này ra mắt trước tính năng hiển thị tải và không cần thiết trong
không gian làm việc nơi các tệp .bzl
khai báo chế độ hiển thị.