Halaman ini membahas dua sistem visibilitas Bazel: visibilitas target dan visibilitas pemuatan.
Kedua jenis visibilitas ini membantu developer lain membedakan antara API publik library dan detail implementasinya, serta membantu menegakkan struktur seiring dengan berkembangnya ruang kerja Anda. Anda juga dapat menggunakan visibilitas saat menghentikan penggunaan API untuk memungkinkan pengguna saat ini dan menolak pengguna baru.
Visibilitas target
Visibilitas target mengontrol siapa yang mungkin bergantung pada target Anda — yaitu, siapa yang mungkin
gunakan label target di dalam atribut seperti deps
.
A
target terlihat oleh target B
jika berada dalam paket yang sama, atau jika
A
memberikan visibilitas ke paket B
. Jadi, paket adalah unit dari
perincian untuk memutuskan apakah
mengizinkan akses atau tidak. Jika B
bergantung pada A
tetapi A
tidak terlihat oleh B
, maka segala upaya untuk membangun B
akan gagal selama
analisis.
Perhatikan bahwa memberikan visibilitas ke paket tidak dengan sendirinya memberikan visibilitas pada sub-paketnya. Untuk detail selengkapnya tentang paket dan sub-paket, lihat Konsep dan terminologi.
Untuk pembuatan prototipe, Anda dapat menonaktifkan penerapan visibilitas target dengan menyetel atribut
tandai --check_visibility=false
. Hal ini tidak boleh dilakukan untuk penggunaan produksi di
kode yang dikirimkan.
Cara utama untuk mengontrol visibilitas adalah dengan
Atribut visibility
aktif
target aturan. Bagian ini menjelaskan format atribut ini, dan cara
menentukan visibilitas target.
Spesifikasi visibilitas
Semua target aturan memiliki atribut visibility
yang menggunakan daftar label. Masing-masing
label memiliki salah satu bentuk berikut. Dengan pengecualian dalam bentuk yang terakhir,
hanyalah placeholder sintaksis yang tidak sesuai dengan target aktual.
"//visibility:public"
: Memberikan akses ke semua paket. (Tidak dapat digabungkan dengan spesifikasi lainnya.)"//visibility:private"
: Tidak memberikan akses tambahan apa pun; target saja dalam paket ini dapat menggunakan target tersebut. (Tidak dapat digabungkan dengan specification.)"//foo/bar:__pkg__"
: Memberikan akses ke//foo/bar
(tetapi tidak sub-paket)."//foo/bar:__subpackages__"
: Memberikan akses//foo/bar
dan semua aksesnya sub-paket langsung dan tidak langsung."//some_pkg:my_package_group"
: Memberikan akses ke semua paket yang adalah bagian daripackage_group
yang ditentukan.- Grup paket menggunakan
sintaksis yang berbeda untuk
menentukan paket. Di dalam grup paket, formulir
"//foo/bar:__pkg__"
dan"//foo/bar:__subpackages__"
masing-masing diganti dengan"//foo/bar"
dan"//foo/bar/..."
. Demikian juga,"//visibility:public"
dan"//visibility:private"
hanya"public"
dan"private"
.
- Grup paket menggunakan
sintaksis yang berbeda untuk
menentukan paket. Di dalam grup paket, formulir
Misalnya, jika //some/package:mytarget
menetapkan visibility
-nya ke
[":__subpackages__", "//tests:__pkg__"]
, maka dapat digunakan oleh target mana pun
yang merupakan bagian dari hierarki sumber //some/package/...
, serta target yang ditentukan
di //tests/BUILD
, tetapi bukan berdasarkan target yang ditentukan dalam //tests/integration/BUILD
.
Praktik terbaik: Untuk membuat beberapa target terlihat oleh kumpulan yang sama
paket, gunakan package_group
daripada mengulangi daftar di setiap
atribut visibility
target. Hal ini meningkatkan keterbacaan dan mencegah
daftar agar tidak sinkron.
Visibilitas target aturan
Visibilitas target aturan:
Nilai atribut
visibility
, jika ditetapkan; atau yang lainNilai atribut
default_visibility
argumen pernyataanpackage
di kolom fileBUILD
target, jika deklarasi tersebut ada; atau yang lain//visibility:private
.
Praktik terbaik: Hindari menyetel default_visibility
ke publik. Mungkin
sangat mudah digunakan untuk pembuatan prototipe atau
codebase kecil, tetapi risiko
membuat target publik akan meningkat seiring pertumbuhan codebase. Lebih baik menjadi
eksplisit tentang target mana yang merupakan
bagian dari antarmuka publik paket.
Contoh
File //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"],
)
File //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",
],
)
Visibilitas target file yang dihasilkan
Target file yang dihasilkan memiliki visibilitas yang sama dengan target aturan yang yang akan menghasilkannya.
Visibilitas target file sumber
Anda dapat secara eksplisit menetapkan visibilitas target file sumber dengan memanggil
exports_files
Saat tidak ada visibility
diteruskan ke exports_files
, sehingga visibilitas menjadi publik.
exports_files
tidak boleh digunakan untuk mengganti visibilitas file yang dihasilkan.
Untuk target file sumber yang tidak muncul dalam panggilan ke exports_files
,
visibilitas yang bergantung pada nilai flag
--incompatible_no_implicit_file_export
:
Jika tanda ini disetel, visibilitas akan disetel ke pribadi.
Selain itu, perilaku lama akan berlaku: Visibilitasnya sama dengan
default_visibility
fileBUILD
, atau pribadi jika visibilitas default adalah tidak ditentukan.
Hindari mengandalkan perilaku lama. Selalu tulis exports_files
setiap kali target file sumber memerlukan visibilitas non-pribadi.
Praktik terbaik: Jika memungkinkan, lebih memilih untuk mengekspos target aturan, bukan
file sumbernya. Misalnya, sebagai ganti memanggil exports_files
di file .java
,
gabungkan file dalam target java_library
non pribadi. Secara umum, target aturan
sebaiknya hanya merujuk ke file sumber
yang ada di dalam paket yang sama.
Contoh
File //frobber/data/BUILD
:
exports_files(["readme.txt"])
File //frobber/bin/BUILD
:
cc_binary(
name = "my-program",
data = ["//frobber/data:readme.txt"],
)
Visibilitas setelan konfigurasi
Sebelumnya, Bazel tidak
menerapkan visibilitas untuk
config_setting
target yang
yang direferensikan dalam kunci select()
. Ada
adalah dua tanda untuk menghapus perilaku lama ini:
--incompatible_enforce_config_setting_visibility
memungkinkan pemeriksaan visibilitas untuk target tersebut. Untuk membantu migrasi, juga menyebabkanconfig_setting
yang tidak menentukanvisibility
dianggap publik (terlepas daridefault_visibility
level paket).--incompatible_config_setting_private_default_visibility
menyebabkanconfig_setting
yang tidak menentukanvisibility
untuk mematuhidefault_visibility
paket dan untuk penggantian pada visibilitas pribadi, cukup seperti target aturan lainnya. Tanpa pengoperasian jika--incompatible_enforce_config_setting_visibility
belum disetel.
Hindari mengandalkan perilaku lama. Setiap config_setting
yang ditujukan untuk
digunakan di luar paket saat ini harus memiliki visibility
eksplisit, jika
paket belum menentukan default_visibility
yang cocok.
Visibilitas target grup paket
Target package_group
tidak memiliki atribut visibility
. Mereka selalu
terlihat oleh publik.
Visibilitas dependensi implisit
Beberapa aturan memiliki dependensi implisit —
dependensi yang tidak dieja dalam file BUILD
tetapi melekat pada
setiap kejadian dari aturan itu. Misalnya, aturan cc_library
mungkin membuat
dependensi implisit dari setiap target aturannya ke target yang dapat dieksekusi
yang merepresentasikan compiler C++.
Visibilitas dependensi implisit tersebut diperiksa sehubungan dengan
paket yang berisi file .bzl
tempat aturan (atau aspek) ditentukan. Di beberapa
pada contoh ini, kompilator C++ bisa bersifat pribadi
selama ia berada di ruang
sebagai definisi aturan cc_library
. Sebagai alternatif, jika
dependensi implisit tidak terlihat dari definisi, maka diperiksa dengan
sesuai dengan target cc_library
.
Anda dapat mengubah perilaku
ini dengan menonaktifkan
--incompatible_visibility_private_attributes_at_definition
Jika dinonaktifkan, dependensi implisit diperlakukan seperti dependensi lainnya.
Ini berarti bahwa target yang diandalkan (seperti kompilator C++ kita) harus
terlihat oleh setiap instance aturan. Dalam praktiknya, hal ini biasanya berarti target
harus memiliki visibilitas publik.
Jika Anda ingin membatasi penggunaan aturan untuk paket tertentu, gunakan memuat visibilitas.
Muat visibilitas
Visibilitas pemuatan mengontrol apakah file .bzl
dapat dimuat dari
File BUILD
atau .bzl
di luar paket saat ini.
Dengan cara yang sama seperti visibilitas target melindungi kode sumber yang dienkapsulasi
berdasarkan target, visibilitas pemuatan melindungi logika build yang dienkapsulasi oleh .bzl
. Misalnya, penulis file BUILD
mungkin ingin memperhitungkan beberapa pengulangan
definisi target ke dalam makro dalam file .bzl
. Tanpa perlindungan beban
mereka mungkin menemukan bahwa makro mereka digunakan kembali oleh kolaborator lain di
ruang kerja yang sama, sehingga memodifikasi makro akan
menghentikan tim lain build yang berbeda.
Perhatikan bahwa file .bzl
mungkin memiliki atau tidak memiliki target file sumber yang sesuai.
Jika ya, tidak ada jaminan bahwa visibilitas pemuatan dan target
terlihat bertepatan. Artinya, file BUILD
yang sama mungkin dapat memuat
.bzl
file tetapi tidak mencantumkannya dalam srcs
dari filegroup
,
atau sebaliknya. Hal ini terkadang dapat menyebabkan masalah
untuk aturan yang ingin menggunakan
File .bzl
seperti kode sumber, misalnya untuk pembuatan atau pengujian dokumentasi.
Untuk pembuatan prototipe, Anda dapat menonaktifkan penerapan visibilitas beban dengan menetapkan
--check_bzl_visibility=false
. Seperti halnya --check_visibility=false
, kode ini seharusnya
tidak dilakukan untuk kode yang dikirimkan.
Visibilitas pemuatan tersedia mulai Bazel 6.0.
Mendeklarasikan visibilitas pemuatan
Untuk menyetel visibilitas pemuatan file .bzl
, panggil metode
Fungsi visibility()
dari dalam file.
Argumen untuk visibility()
adalah daftar spesifikasi paket, seperti
atribut packages
dari
package_group
. Namun, visibility()
tidak menerima paket negatif
spesifikasi produk.
Panggilan ke visibility()
hanya boleh terjadi sekali per file, di tingkat teratas (bukan
di dalam fungsi), dan idealnya segera setelah pernyataan load()
.
Tidak seperti visibilitas target, visibilitas pemuatan default selalu bersifat publik. File
yang tidak memanggil visibility()
selalu dapat dimuat dari mana saja di
Workspace. Sebaiknya tambahkan visibility("private")
ke bagian atas
file .bzl
baru yang tidak secara khusus dimaksudkan untuk digunakan di luar paket.
Contoh
# //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
...
Memuat praktik visibilitas
Bagian ini menjelaskan tips untuk mengelola deklarasi visibilitas pemuatan.
Mempertimbangkan visibilitas
Sebaiknya beberapa file .bzl
memiliki visibilitas yang sama
memasukkan spesifikasi paket mereka
ke dalam daftar umum. Contoh:
# //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)
...
Hal ini membantu mencegah penyimpangan yang tidak disengaja antara berbagai file .bzl
visibilitas. Format ini juga lebih mudah dibaca jika daftar clients
berukuran besar.
Menyusun visibilitas
Terkadang file .bzl
mungkin harus terlihat oleh daftar yang diizinkan yang
yang terdiri dari beberapa daftar yang diizinkan. Hal ini dapat dianalisa dengan bagaimana
package_group
dapat menyertakan package_group
lain melalui
Atribut includes
.
Misalkan Anda menghentikan penggunaan makro yang banyak digunakan. Anda ingin item hanya terlihat untuk pengguna yang ada dan ke paket milik tim Anda sendiri. Anda dapat menulis:
# //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)
Menduplikasi grup paket
Tidak seperti visibilitas target, Anda tidak dapat mendefinisikan
package_group
. Jika Anda ingin menggunakan kembali daftar yang diizinkan yang sama untuk kedua target
visibilitas dan beban visibilitas, sebaiknya
pindahkan daftar paket
spesifikasi ke dalam file .bzl, di mana kedua jenis deklarasi dapat merujuk pada
anotasi. Mengembangkan contoh dalam Mempertimbangkan visibilitas
di atas, Anda dapat menulis:
# //mylib/BUILD
load(":internal_defs", "clients")
package_group(
name = "my_pkg_grp",
packages = clients,
)
Perintah ini hanya berfungsi jika daftar tidak berisi paket negatif apa pun spesifikasi produk.
Melindungi setiap simbol
Setiap simbol Starlark yang namanya dimulai dengan garis bawah tidak dapat dimuat dari
file lain. Hal ini memudahkan pembuatan simbol pribadi, tetapi tidak memungkinkan
Anda untuk berbagi simbol-simbol ini dengan
kumpulan file yang terbatas. Di sisi lain
tangan, visibilitas beban memberi Anda kontrol atas apa yang mungkin dilihat oleh paket
.bzl file
, tetapi tidak memungkinkan Anda mencegah simbol yang tidak digarisbawahi
sedang dimuat.
Untungnya, Anda dapat menggabungkan kedua fitur ini untuk mendapatkan kontrol yang lebih detail.
# //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
Lint Buildifier bzl-visibilitas
Ada lint Buildifier
yang memberikan peringatan jika pengguna memuat file dari direktori bernama internal
atau private
, jika file pengguna tidak berada di bawah induknya
saat ini. Lint ini mendahului fitur visibilitas pemuatan dan tidak diperlukan dalam
ruang kerja tempat file .bzl
mendeklarasikan visibilitas.