Trang này trình bày về 2 hệ thống chế độ hiển thị của Bazel: chế độ hiển thị mục tiêu và chế độ hiển thị tải.
Cả hai loại chế độ hiển thị đề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 chi tiết về cách triển khai, đồng thời giúp thực thi cấu trúc khi không gian làm việc của bạn phát triển. Bạn cũng có thể sử dụng chế độ hiển thị khi ngừng sử dụng một API công khai để cho phép người dùng hiện tại trong khi từ chối người dùng mới.
Chế độ hiển thị mục tiêu
Chế độ hiển thị 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 của mục tiêu bên trong một thuộc tính như deps. Một mục tiêu sẽ không xây dựng được
trong giai đoạn phân tích nếu vi phạm chế độ hiển thị của một trong các phần phụ thuộc.
Thông thường, một mục tiêu A sẽ hiển thị cho mục tiêu B nếu chúng ở cùng một
vị trí hoặc nếu A cấp quyền hiển thị cho vị trí của B. Khi không có
macro tượng trưng, thuật ngữ "vị trí" có thể được đơn giản hoá
thành "gói"; hãy xem bên dưới để biết thêm thông tin về macro tượng trưng.
Chế độ hiển thị được chỉ định bằng cách liệt kê các gói được phép. Việc cho phép một gói không nhất thiết có nghĩa là các gói con của gói đó cũng được phép. Để biết thêm thông tin chi tiết về các gói và gói con, hãy xem phần Khái niệm và thuật ngữ.
Đối với việc tạo mẫu thử, bạn có thể tắt tính năng 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 cho việc sử dụng trong quá trình phát hành trong
mã đã gửi.
Cách chính để kiểm soát chế độ hiển thị là sử dụng thuộc tính
visibility của quy tắc.
Các tiểu mục sau đây mô tả định dạng của thuộc tính, cách áp dụng thuộc tính này cho
nhiều loại mục tiêu và sự tương tác giữa hệ thống chế độ hiển thị và
macro tượng trưng.
Thông số kỹ thuật về chế độ hiển thị
Tất cả các mục tiêu quy tắc đều có thuộc tính visibility lấy danh sách nhãn. Mỗi
nhãn có một trong các dạng sau. Ngoại trừ dạng cuối cùng, đây
chỉ là các trình 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 cho tất cả các gói."//visibility:private": Không cấp thêm quyền truy cập nào; chỉ các mục tiêu trong gói của vị trí này mới có thể sử dụng mục tiêu này."//foo/bar:__pkg__": Cấp quyền truy cập vào//foo/bar(nhưng không phải các gói con của gói đó)."//foo/bar:__subpackages__": Cấp quyền truy cập vào//foo/barvà tất cả các gói con trực tiếp và gián tiếp của gói đó."//some_pkg:my_package_group": Cấp quyền truy cập vào tất cả các gói thuộcpackage_groupđã cho.- Nhóm gói sử dụng một
cú pháp khác để
chỉ định các gói. Trong một nhóm gói, các dạng
"//foo/bar:__pkg__"và"//foo/bar:__subpackages__"lần lượt đượ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 một
cú pháp khác để
chỉ định các gói. Trong một nhóm gói, các dạng
Ví dụ: nếu //some/package:mytarget được đặt visibility thành
[":__subpackages__", "//tests:__pkg__"], thì mục tiêu này có thể được sử dụng bởi bất kỳ mục tiêu nào
thuộc cây nguồn //some/package/..., cũng như các mục tiêu
được khai báo 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ị một số mục tiêu cho cùng một tập hợp
gói, hãy sử dụng package_group thay vì lặp lại danh sách trong thuộc tính visibility của mỗi
mục tiêu. Điều này giúp tăng khả năng đọc và ngăn
danh sách bị lệch.
Phương pháp hay nhất: Khi cấp quyền hiển thị cho dự án của một nhóm khác, hãy ưu tiên
__subpackages__ hơn __pkg__ để tránh việc thay đổi chế độ hiển thị không cần thiết khi
dự án đó phát triển và thêm các gói con mới.
Chế độ hiển thị mục tiêu quy tắc
Chế độ hiển thị của mục tiêu quy tắc được xác định bằng cách lấy thuộc tính visibility của mục tiêu đó
(hoặc giá trị mặc định phù hợp nếu không được cung cấp) và thêm vị trí nơi
mục tiêu được khai báo. Đối với các mục tiêu không được khai báo trong macro tượng trưng, nếu gói chỉ định default_visibility, thì giá trị mặc định này sẽ được sử dụng; đối với tất cả các gói khác và đối với các mục tiêu được khai báo trong macro tượng trưng, giá trị mặc định chỉ là ["//visibility:private"].
# //mypkg/BUILD
package(default_visibility = ["//friend:__pkg__"])
cc_library(
name = "t1",
...
# No visibility explicitly specified.
# Effective visibility is ["//friend:__pkg__", "//mypkg:__pkg__"].
# If no default_visibility were given in package(...), the visibility would
# instead default to ["//visibility:private"], and the effective visibility
# would be ["//mypkg:__pkg__"].
)
cc_library(
name = "t2",
...
visibility = [":clients"],
# Effective visibility is ["//mypkg:clients, "//mypkg:__pkg__"], which will
# expand to ["//another_friend:__subpackages__", "//mypkg:__pkg__"].
)
cc_library(
name = "t3",
...
visibility = ["//visibility:private"],
# Effective visibility is ["//mypkg:__pkg__"]
)
package_group(
name = "clients",
packages = ["//another_friend/..."],
)
Phương pháp hay nhất: Tránh đặt default_visibility thành công khai. Việc này có thể
thuận tiện cho việc tạo mẫu thử hoặc trong các cơ sở mã nhỏ, nhưng nguy cơ vô tình
tạo các mục tiêu công khai sẽ tăng lên khi cơ sở mã phát triển. Bạn nên nêu rõ những mục tiêu nào thuộc giao diện công khai của một gói.
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 mục tiêu đó.
# //mypkg/BUILD
java_binary(
name = "foo",
...
visibility = ["//friend:__pkg__"],
)
# //friend/BUILD
some_rule(
name = "bar",
deps = [
# Allowed directly by visibility of foo.
"//mypkg:foo",
# Also allowed. The java_binary's "_deploy.jar" implicit output file
# target the same visibility as the rule target itself.
"//mypkg:foo_deploy.jar",
]
...
)
Chế độ hiển thị mục tiêu tệp nguồn
Các mục tiêu tệp nguồn có thể được khai báo rõ ràng bằng
exports_fileshoặc được tạo ngầm
bằng cách tham chiếu đến tên tệp của chúng trong thuộc tính nhãn của một quy tắc (bên ngoài
macro tượng trưng). Giống như các mục tiêu quy tắc, vị trí của lệnh gọi đến
exports_files, hoặc tệp BUILD tham chiếu đến tệp đầu vào luôn
được tự động thêm vào chế độ hiển thị của tệp.
Bạn có thể đặt chế độ hiển thị của các tệp do exports_files khai báo bằng tham số
visibility cho hàm đó. Nếu không cung cấp tham số này, chế độ hiển thị sẽ là công khai.
Đối với các tệp không xuất hiện trong lệnh gọi đến exports_files, chế độ hiển thị
sẽ phụ thuộc vào giá trị của cờ
--incompatible_no_implicit_file_export:
Nếu cờ là true, chế độ hiển thị sẽ là riêng tư.
Nếu không, hành vi cũ sẽ được áp dụng: Chế độ hiển thị giống như tệp
BUILDdefault_visibilityhoặc là riêng tư nếu không chỉ định chế độ hiển thị mặc định.
Tránh dựa vào hành vi cũ. Luôn viết một exports_files
khai báo bất cứ khi nào mục tiêu tệp nguồn cần chế độ hiển thị không phải là riêng tư.
Phương pháp hay nhất: Khi có thể, hãy ưu tiên 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,
hãy gói tệp đó trong mục tiêu java_library không phải là riêng tư. Thông thường, các mục tiêu quy tắc
chỉ nên tham chiếu trực tiếp đến 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ị cho
config_setting các mục tiêu được
tham chiếu trong các khoá của select(). Có
2 cờ để xoá hành vi cũ này:
--incompatible_enforce_config_setting_visibilitybật tính năng kiểm tra chế độ hiển thị cho các mục tiêu này. Để hỗ trợ quá trình di chuyển, cờ này cũng khiến mọiconfig_settingkhông chỉ địnhvisibilityđược coi là công khai (bất kểdefault_visibilityở cấp gói).--incompatible_config_setting_private_default_visibilitykhiến cácconfig_settingkhông chỉ địnhvisibilitytuân theodefault_visibilitycủa gói và quay lại chế độ hiển thị riêng tư, giống như bất kỳ mục tiêu quy tắc nào khác. Đây là một thao tác không có tác dụng nếu--incompatible_enforce_config_setting_visibilitybạn không đặt.
Tránh dựa vào hành vi cũ. Bất kỳ config_setting nào dự định
sử dụng bên ngoài gói hiện tại đều phải có visibility rõ ràng, nếu gói
chưa chỉ định default_visibility phù hợp.
Chế độ hiển thị mục tiêu 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.
Chế độ hiển thị của các phần phụ thuộc ngầm
Một số quy tắc có các phần phụ thuộc ngầm –
các phần phụ thuộc không được nêu rõ trong tệp BUILD nhưng vốn có trong
mọi thực thể của quy tắc đó. Ví dụ: quy tắc cc_library có thể tạo một
phần phụ thuộc ngầm từ mỗi mục tiêu quy tắc của nó đến một mục tiêu 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 như vậy được kiểm tra đối với gói chứa tệp .bzl trong đó quy tắc (hoặc khía cạnh) được xác định. Trong
ví dụ của chúng tôi, trình biên dịch C++ có thể là riêng tư miễn là trình biên dịch đó nằm trong cùng một
gói với định nghĩa của quy tắc cc_library. Nếu không tìm thấy phần phụ thuộc ngầm từ định nghĩa, thì phần phụ thuộc đó sẽ được kiểm tra đối với mục tiêu cc_library.
Nếu bạn muốn hạn chế việc sử dụng một quy tắc cho một số gói nhất định, hãy sử dụng chế độ hiển thị tải thay thế.
Chế độ hiển thị và macro tượng trưng
Phần này mô tả cách hệ thống chế độ hiển thị tương tác với macro tượng trưng.
Vị trí trong macro tượng trưng
Một chi tiết quan trọng của hệ thống chế độ hiển thị là cách chúng tôi xác định vị trí của một
khai báo. Đối với các mục tiêu không được khai báo trong macro tượng trưng, vị trí
chỉ là gói nơi mục tiêu tồn tại – gói của tệp BUILD.
Nhưng đối với các mục tiêu được tạo trong macro tượng trưng, vị trí là gói
chứa tệp .bzl nơi định nghĩa của macro (câu lệnh
my_macro = macro(...) xuất hiện. Khi một mục tiêu được tạo bên trong
nhiều mục tiêu lồng nhau, định nghĩa của macro tượng trưng trong cùng
luôn được sử dụng.
Hệ thống tương tự được dùng để xác định vị trí cần kiểm tra đối với chế độ hiển thị của một phần phụ thuộc nhất định. Nếu mục tiêu sử dụng được tạo bên trong một macro, chúng ta sẽ xem định nghĩa của macro trong cùng thay vì gói mà mục tiêu sử dụng tồn tại.
Điều này có nghĩa là tất cả các macro có mã được xác định trong cùng một gói đều
tự động "bạn bè" với nhau. Bạn có thể thấy bất kỳ mục tiêu nào được tạo trực tiếp bởi một macro
được xác định trong //lib:defs.bzl từ bất kỳ macro nào khác được xác định trong //lib,
bất kể các gói thực sự được thực thể hoá trong macro. Tương tự,
chúng có thể thấy và có thể được thấy bởi các mục tiêu được khai báo trực tiếp trong //lib/BUILD và
các macro cũ của mục tiêu đó. Ngược lại, các mục tiêu nằm trong cùng một gói không thể
nhất thiết thấy nhau nếu ít nhất một trong số đó được tạo bởi một macro
tượng trưng.
Trong hàm triển khai của macro tượng trưng, tham số visibility có giá trị hiệu quả của thuộc tính visibility của macro sau khi thêm vị trí nơi macro được gọi. Cách tiêu chuẩn để một macro xuất
một trong các mục tiêu của macro đó sang trình gọi là chuyển tiếp giá trị này cùng với khai báo của mục tiêu, như trong some_rule(..., visibility = visibility). Các mục tiêu bỏ qua
thuộc tính này sẽ không hiển thị cho trình gọi của macro trừ phi trình gọi đó
nằm trong cùng một gói với định nghĩa macro. Hành vi này
kết hợp theo nghĩa là một chuỗi các lệnh gọi lồng nhau đến các macro con có thể chuyển
visibility = visibility, xuất lại các mục tiêu đã xuất của macro bên trong cho
trình gọi ở mỗi cấp, mà không tiết lộ bất kỳ thông tin chi tiết nào về cách triển khai macro.
Uỷ quyền đặc quyền cho macro con
Mô hình chế độ hiển thị có một tính năng đặc biệt cho phép một macro uỷ quyền cho một macro con. Điều này rất quan trọng đối với việc phân tích và kết hợp các macro.
Giả sử bạn có một macro my_macro tạo một cạnh phần phụ thuộc bằng quy tắc
some_library từ một gói khác:
# //macro/defs.bzl
load("//lib:defs.bzl", "some_library")
def _impl(name, visibility, ...):
...
native.genrule(
name = name + "_dependency"
...
)
some_library(
name = name + "_consumer",
deps = [name + "_dependency"],
...
)
my_macro = macro(implementation = _impl, ...)
# //pkg/BUILD
load("//macro:defs.bzl", "my_macro")
my_macro(name = "foo", ...)
Mục tiêu //pkg:foo_dependency không có visibility được chỉ định, vì vậy, mục tiêu này chỉ
hiển thị trong //macro, hoạt động tốt cho mục tiêu sử dụng. Bây giờ, điều gì
sẽ xảy ra nếu tác giả của //lib tái cấu trúc some_library để thay vào đó được
triển khai bằng một macro?
# //lib:defs.bzl
def _impl(name, visibility, deps, ...):
some_rule(
# Main target, exported.
name = name,
visibility = visibility,
deps = deps,
...)
some_library = macro(implementation = _impl, ...)
Với thay đổi này, vị trí của //pkg:foo_consumer' hiện là //lib thay vì
//macro, vì vậy, việc sử dụng //pkg:foo_dependency vi phạm chế độ hiển thị của phần phụ thuộc. Bạn không thể yêu cầu tác giả của my_macro truyền
visibility = ["//lib"] đến khai báo của phần phụ thuộc chỉ để giải quyết
thông tin chi tiết về cách triển khai này.
Vì lý do này, khi một phần phụ thuộc của mục tiêu cũng là giá trị thuộc tính của macro đã khai báo mục tiêu, chúng ta sẽ kiểm tra chế độ hiển thị của phần phụ thuộc đối với vị trí của macro thay vì vị trí của mục tiêu sử dụng.
Trong ví dụ này, để xác thực xem //pkg:foo_consumer có thể thấy
//pkg:foo_dependency hay không, chúng ta thấy rằng //pkg:foo_dependency cũng được truyền dưới dạng
đầu vào cho lệnh gọi đến some_library bên trong my_macro và thay vào đó, hãy kiểm tra chế độ hiển thị của
phần phụ thuộc đối với vị trí của lệnh gọi này, //macro.
Quá trình này có thể lặp lại một cách đệ quy, miễn là khai báo mục tiêu hoặc macro nằm bên trong một macro tượng trưng khác lấy nhãn của phần phụ thuộc trong một trong các thuộc tính có kiểu nhãn.
Trình hoàn thiện
Các mục tiêu được khai báo trong trình hoàn thiện quy tắc (macro tượng trưng có finalizer = True),
ngoài việc xem các mục tiêu tuân theo các quy tắc hiển thị macro tượng trưng thông thường, còn có thể xem tất cả các mục tiêu hiển thị cho gói của mục tiêu trình hoàn thiện.
Nói cách khác, nếu bạn di chuyển một macro cũ dựa trên native.existing_rules() sang
trình hoàn thiện, thì các mục tiêu do trình hoàn thiện khai báo vẫn có thể thấy
các phần phụ thuộc cũ của chúng.
Bạn có thể xác định các mục tiêu mà trình hoàn thiện có thể kiểm tra bằng
native.existing_rules(), nhưng không thể sử dụng làm phần phụ thuộc trong hệ thống
chế độ hiển thị. Ví dụ: nếu một mục tiêu do macro xác định không hiển thị cho gói riêng
hoặc cho định nghĩa macro trình hoàn thiện và không được uỷ quyền cho trình hoàn thiện
, thì trình hoàn thiện không thể thấy mục tiêu đó. Tuy nhiên, xin lưu ý rằng macro cũ dựa trên
native.existing_rules() cũng sẽ không thể thấy mục tiêu
đó.
Chế độ hiển thị tải
Chế độ hiển thị tải kiểm soát việc có thể tải tệp .bzl từ các tệp
BUILD hoặc .bzl khác bên ngoài gói hiện tại hay không.
Tương tự như cách chế độ hiển thị mục tiêu bảo vệ mã nguồn được gói gọn
bởi các mục tiêu, chế độ hiển thị tải bảo vệ logic bản dựng được gói gọn bởi .bzl
tệp. Ví dụ: tác giả tệp BUILD có thể muốn phân tích một số khai báo mục tiêu lặp đi lặp lại
thành một macro trong tệp .bzl. Nếu không có sự bảo vệ của
chế độ hiển thị tải, họ có thể thấy macro của mình đượ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, để việc sửa đổi macro sẽ làm hỏng các bản dựng của các nhóm khác.
Xin lưu ý rằng tệp .bzl có thể có hoặc không có mục tiêu tệp nguồn tương ứng.
Nếu có, thì không có gì đảm bảo rằng chế độ hiển thị tải và chế độ hiển thị mục tiêu
trùng khớp. Tức là, cùng một tệp BUILD có thể tải tệp
.bzl nhưng không liệt kê tệp đó trong srcs của filegroup,
hoặc ngược lại. Đôi khi, điều này có thể gây ra vấn đề cho các quy tắc muốn sử dụng
.bzl tệp làm mã nguồn, chẳng hạn như để tạo tài liệu hoặc kiểm thử.
Đối với việc tạo mẫu thử, bạn có thể tắt tính năng thực thi chế độ hiển thị tải bằng cách đặt
--check_bzl_visibility=false. Giống như --check_visibility=false, bạn không nên thực hiện việc này cho 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 hàm
visibility() từ bên trong tệp.
Đối số cho visibility() là danh sách các thông số kỹ thuật về gói, giống như
thuộc tính packages của
package_group. Tuy nhiên, visibility() không chấp nhận các thông số kỹ thuật về gói phủ định.
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ác câu lệnh load().
Không giống như chế độ hiển thị mục tiêu, chế độ hiển thị tải mặc định luôn là công khai. Bạn luôn có thể tải các tệp
không gọi visibility() từ mọi nơi trong
không gian làm việc. Bạn nên thêm visibility("private") vào đầu bất kỳ
tệp .bzl mới nào không dành riêng cho việc sử dụng 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
...
Các phương pháp hiển thị tải
Phần này mô tả các mẹo để quản lý khai báo chế độ hiển thị tải.
Phân tích chế độ hiển thị
Khi nhiều tệp .bzl phải có cùng chế độ hiển thị, bạn có thể
phân tích các thông số kỹ thuật về gói của chúng thành 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 ngăn chặn sự sai lệch ngẫu nhiên giữa các chế độ hiển thị của tệp .bzl files'
khác nhau. Danh sách này cũng dễ đọc hơn khi danh sách clients lớn.
Kết hợp chế độ hiển thị
Đôi khi, tệp .bzl có thể cần hiển thị cho 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 a
package_group có thể kết hợp các package_group khác thông qua thuộc tính
includes.
Giả sử bạn đang ngừng sử dụng một macro được sử dụng rộng rãi. Bạn chỉ muốn macro đó hiển thị chỉ 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)
Khử trùng lặp bằng 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 a
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ả chế độ hiển thị mục tiêu
và chế độ hiển thị tải, thì tốt nhất là chuyển danh sách các thông số kỹ thuật về gói
vào tệp .bzl, nơi cả hai loại khai báo đều có thể tham chiếu đến
danh sách đó. Dựa trên ví dụ trong phần Phân tích chế độ 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,
)
Điều này chỉ hoạt động nếu danh sách không chứa bất kỳ thông số kỹ thuật về gói phủ định nào.
Bảo vệ các ký hiệu riêng lẻ
Bạn không thể tải bất kỳ ký hiệu Starlark nào có tên bắt đầu bằng dấu gạch dưới từ
một tệp khác. Điều này giúp bạn dễ dàng tạo các ký hiệu riêng tư, nhưng không cho phép
bạn chia sẻ các ký hiệu này với một tập hợp giới hạn các tệp đáng tin cậy. Mặt khác, chế độ hiển thị tải cho phép bạn kiểm soát những gói khác có thể thấy
.bzl file của bạn, nhưng không cho phép bạn ngăn tải bất kỳ ký hiệu nào không có dấu gạch dưới.
May mắn là bạn có thể kết hợp 2 tính năng này để kiểm soát chi tiết.
# //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
bzl-visibility Buildifier lint
Có một Buildifier lint
cung cấp cảnh báo nếu người dùng tải một tệp từ một thư mục có tên là internal
hoặc private, khi tệp của người dùng không nằm bên dưới thư mục mẹ của thư mục
đó. Lint này có trước tính năng hiển thị tải và không cần thiết trong
các không gian làm việc nơi các tệp .bzl khai báo chế độ hiển thị.