Trang này trình bày 2 hệ thống hiển thị của Bazel: khả năng hiển thị mục tiêu và khả năng hiển thị khi 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 chi tiết về việc 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 khả năng hiển thị khi không dùng nữa 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 đối tượng có thể phụ thuộc vào mục tiêu của bạn, tức là những đối tượng có thể sử dụng nhãn của mục tiêu trong một thuộc tính như deps
. Một mục tiêu sẽ không thể tạo trong giai đoạn phân tích nếu mục tiêu đó vi phạm khả năng hiển thị của một trong các phần phụ thuộc của mục tiêu.
Thông thường, A
sẽ thấy được B
nếu cả hai ở cùng một vị trí hoặc nếu A
cấp quyền xem vị trí của B
. Nếu không có macro tượng trưng, bạn có thể đơn giản hoá thuật ngữ "vị trí" thành "gói"; hãy xem bên dưới để biết thêm 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 Các khái niệm và thuật ngữ.
Để tạo mẫu, bạn có thể tắt chế độ thực thi khả năng 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 mục đích 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à dùng thuộc tính visibility
của quy tắc.
Các mục con 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à mối tương tác giữa hệ thống hiển thị và macro mang tính biểu tượng.
Quy cách về khả năng hiển thị
Tất cả mục tiêu của quy tắc đều có thuộc tính visibility
nhận danh sách nhãn. Mỗi nhãn có một trong các dạng sau. Ngoại trừ biểu mẫu cuối cùng, đây 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."//visibility:private"
: Không cấp thêm quyền truy cập nào; chỉ những 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 cấp quyền truy cập vào các gói con của//foo/bar
)."//foo/bar:__subpackages__"
: Cấp quyền truy cập//foo/bar
và tất cả các gói con trực tiếp và gián tiếp của gói này."//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 cú pháp khác để chỉ định các gói. Trong một nhóm gói, các biểu mẫu
"//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 cú pháp khác để chỉ định các gói. Trong một nhóm gói, các biểu mẫu
Ví dụ: nếu //some/package:mytarget
có visibility
được đặt thành [":__subpackages__", "//tests:__pkg__"]
, thì mọi mục tiêu thuộc cây nguồn //some/package/...
cũng như các mục tiêu được khai báo trong //tests/BUILD
đều có thể sử dụng mục tiêu này, nhưng các mục tiêu được xác định trong //tests/integration/BUILD
thì không.
Cách hay nhất: Để hiển thị một số mục tiêu cho cùng một nhóm 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 tình trạng thay đổi không cần thiết về khả năng hiển thị khi dự án đó phát triển và thêm các gói con mới.
Khả năng hiển thị mục tiêu của quy tắc
Khả năng hiển thị của đích đến của quy tắc được xác định bằng cách lấy thuộc tính visibility
của đích đến đó (hoặc giá trị mặc định phù hợp nếu không được chỉ định) và nối vị trí nơi đích đến đượ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. Điều này có thể thuận tiện cho việc tạo mẫu hoặc trong các cơ sở mã nhỏ, nhưng nguy cơ vô tình tạo ra 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 chỉ 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 của tệp được tạo
Mục tiêu của tệp được tạo có cùng chế độ hiển thị với mục tiêu của quy tắc tạo ra tệp đó.
# //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ị của tệp nguồn
Bạn có thể khai báo rõ ràng các mục tiêu của tệp nguồn bằng cách sử dụng exports_files
hoặc tạo ngầm bằng cách tham chiếu đến tên tệp 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ư mục tiêu của 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 khả năng hiển thị của tệp.
Bạn có thể đặt chế độ hiển thị cho các tệp do exports_files
khai báo bằng tham số visibility
cho hàm đó. Nếu bạn không cung cấp tham số này, thì chế độ hiển thị sẽ là công khai.
Đối với những tệp không xuất hiện trong lệnh gọi đến exports_files
, khả năng hiển thị phụ thuộc vào giá trị của cờ --incompatible_no_implicit_file_export
:
Nếu cờ này là true, thì 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 với
default_visibility
của tệpBUILD
hoặc ở chế độ riêng tư nếu bạn 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 đích của tệp nguồn cần có chế độ hiển thị không 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 của quy tắc thay vì tệp nguồn. Ví dụ: thay vì gọi exports_files
trên tệp .java
, hãy bao bọc tệp trong một mục tiêu java_library
không 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 khả năng hiển thị cho các mục tiêu config_setting
được tham chiếu trong khoá của select()
. Có 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ị cho các mục tiêu này. Để hỗ trợ việc di chuyển, thao tác này cũng khiến mọiconfig_setting
không chỉ địnhvisibility
đều đượ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
phải tuân theodefault_visibility
của gói và quay lại chế độ hiển thị riêng tư, giống như mọi mục tiêu quy tắc khác. Đây là một thao tác không có hiệu lực nếu--incompatible_enforce_config_setting_visibility
chưa được đặt.
Tránh dựa vào hành vi cũ. Mọi config_setting
dự định được 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 của nhóm gói
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 – những phần phụ thuộc không được nêu rõ trong tệp BUILD
nhưng vốn có trong mọi phiên bản 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++.
Khả năng hiển thị của phần phụ thuộc ngầm như vậy được kiểm tra liên quan đến gói chứa tệp .bzl
mà trong đó quy tắc (hoặc khía cạnh) được xác định. Trong ví dụ của chúng ta, 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
. Trong trường hợp dự phòng, nếu phần phụ thuộc ngầm không xuất hiện trong định nghĩa, thì phần phụ thuộc đó sẽ được kiểm tra liên quan đến 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 đối với một số gói nhất định, hãy sử dụng khả năng hiển thị khi tải.
Chế độ hiển thị và macro tượng trưng
Phần này mô tả cách hệ thống 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 hiển thị là cách chúng ta xác định vị trí của một khai báo. Đối với những mục tiêu không được khai báo trong một 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 một 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, thì định nghĩa về macro tượng trưng trong cùng luôn được sử dụng.
Hệ thống này cũng được dùng để xác định vị trí cần kiểm tra theo 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 xét định nghĩa của macro trong cùng thay vì gói mà mục tiêu sử dụng nằm trong đó.
Đ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 sẽ tự động là "bạn bè" với nhau. Mọi mục tiêu do một macro tạo trực tiếp được xác định trong //lib:defs.bzl
đều có thể được nhìn thấy từ bất kỳ macro nào khác được xác định trong //lib
, bất kể macro thực sự được khởi tạo trong gói nào. Tương tự, 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 đó có thể nhìn thấy và được nhìn thấy. Ngược lại, các mục tiêu nằm trong cùng một gói không nhất thiết phải nhìn thấy nhau nếu ít nhất một trong số chúng được tạo bằng 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 nối vị trí mà 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 đó cho 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)
. Những mục tiêu bỏ qua thuộc tính này sẽ không hiển thị cho phương thức gọi macro, trừ phi phương thức gọi nằm trong cùng một gói với định nghĩa macro. Hành vi này tạo thành, theo nghĩa là một chuỗi các lệnh gọi lồng nhau đến các macro con có thể truyền visibility = visibility
, xuất lại các mục tiêu đã xuất của macro bên trong cho người gọi ở mỗi cấp, mà không tiết lộ bất kỳ chi tiết triển khai nào của macro.
Uỷ quyền cho macro con
Mô hình hiển thị có một tính năng đặc biệt cho phép macro uỷ quyền của mình cho một macro con. Điều này rất quan trọng đối với việc phân tích và tạo macro.
Giả sử bạn có một macro my_macro
tạo một cạnh phần phụ thuộc bằng cách sử dụ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 cách sử dụ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
, nên việc sử dụng //pkg:foo_dependency
của vị trí này sẽ vi phạm khả năng hiển thị của phần phụ thuộc. Không thể yêu cầu tác giả của my_macro
truyền visibility = ["//lib"]
vào khai báo của phần phụ thuộc chỉ để giải quyết chi tiết 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 khả năng hiển thị của phần phụ thuộc dựa trên 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ể nhìn 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 một đầ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 khả năng 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 đệ quy, miễn là đích hoặc khai báo 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 nhập nhãn.
Finalizer
Các mục tiêu được khai báo trong một trình kết thúc quy tắc (một 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 thông thường về khả năng hiển thị macro tượng trưng, cũng có thể xem tất cả các mục tiêu mà gói của mục tiêu trình kết thúc có thể nhìn thấy.
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 một trình kết thúc, thì các mục tiêu do trình kết thúc 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 kết thúc có thể tự kiểm tra bằng cách sử dụng native.existing_rules()
, nhưng không thể sử dụng các mục tiêu đó làm phần phụ thuộc trong hệ thống 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 của mục tiêu đó hoặc cho định nghĩa macro của trình kết thúc và không được uỷ quyền cho trình kết thúc, thì trình kết thúc không thể nhìn thấy mục tiêu đó. Tuy nhiên, xin lưu ý rằng một macro cũ dựa trên native.existing_rules()
cũng sẽ không thể nhìn thấy mục tiêu như vậy.
Chế độ hiển thị tải
Khả năng hiển thị khi 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 đóng gói theo mục tiêu, chế độ hiển thị tải bảo vệ logic xây dựng được đóng gói theo các tệp .bzl
. Ví dụ: tác giả tệp BUILD
có thể muốn đưa một số khai báo mục tiêu lặp lại vào một macro trong tệp .bzl
. Nếu không có tính năng bảo vệ khả năng hiển thị tải, họ có thể thấy macro của mình được những người cộng tác khác sử dụng lại trong cùng một không gian làm việc, do đó, việc sửa đổi macro sẽ làm hỏng 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ó đích đến là tệp nguồn tương ứng.
Nếu có, thì không có gì đảm bảo rằng khả năng hiển thị tải và khả năng hiển thị mục tiêu sẽ 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 tệp .bzl
làm mã nguồn, chẳng hạn như để tạo tài liệu hoặc kiểm thử.
Để tạo mẫu, 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
. Tương tự như --check_visibility=false
, bạn không nên làm việc này đối với mã đã gửi.
Chế độ hiển thị tải có sẵn 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()
trong tệp.
Đối số cho visibility()
là danh sách các quy cách 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 quy cách gói âm.
Bạn chỉ được gọi visibility()
một lần cho mỗi tệp, ở cấp cao nhất (không nằm 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 ở chế độ công khai. Các tệp không gọi visibility()
luôn có thể tải được từ mọi nơi trong không gian làm việc. Bạn nên thêm visibility("private")
vào đầu mọi tệp .bzl
mới 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 hay nhất về khả năng hiển thị khi tải
Phần này mô tả các mẹo để quản lý khai báo khả năng hiển thị tải.
Phân tích khả năng hiển thị
Khi nhiều tệp .bzl
phải có cùng khả năng hiển thị, bạn có thể phân tích các quy cách gói của tệp đó 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 tình trạng lệch lạc vô tình giữa khả năng hiển thị của các tệp .bzl
. Danh sách clients
cũng dễ đọc hơn khi có kích thước lớn.
Chế độ hiển thị thành phần
Đôi khi, tệp .bzl
có thể cần hiển thị cho một 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 một 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 dùng rộng rãi. Bạn muốn chỉ những người dùng hiện tại và các gói thuộc quyền sở hữu của nhóm bạn mới nhìn thấy được. 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ỏ các mục trùng lặp bằng nhóm gói
Không giống như khả năng hiển thị mục tiêu, bạn không thể xác định khả năng hiển thị tải theo package_group
. Nếu muốn 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ị khi tải, tốt nhất là bạn nên di chuyển danh sách chỉ định gói vào một 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 Tính toán 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,
)
Đ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 nào về gói phủ định.
Bảo vệ các ký hiệu riêng lẻ
Bạn 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ừ 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 số ít 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 bất kỳ biểu tượng không có dấu gạch dưới nào được tải.
May mắn thay, bạn có thể kết hợp hai 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 đưa ra cảnh báo nếu người dùng tải một tệp 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 mà tệp .bzl
khai báo khả năng hiển thị.