Görünürlük

Sorun bildirin Kaynağı göster

Bu sayfada, Bazel'ın iki görünürlük sistemi ele alınmaktadır: hedef görünürlük ve yük görünürlüğü.

Her iki görünürlük türü de diğer geliştiricilerin, kitaplığınızın herkese açık API'si ile uygulama ayrıntılarını ayırt etmesine ve çalışma alanınız büyüdükçe yapının uygulanmasına yardımcı olur. Ayrıca görünürlük, herkese açık bir API'yi kullanımdan kaldırırken mevcut kullanıcılara izin verirken yenilerini reddederken de kullanılabilir.

Hedef görünürlük

Hedef görünürlük, hedefinize bağlı olabilecek kişileri, yani hedefinizin etiketini deps gibi bir özellikte kimlerin kullanabileceğini kontrol eder.

Bir hedef A, aynı paketteyse veya A, B paketine görünürlük izni veriyorsa B hedefi tarafından görülebilir. Bu nedenle, erişim izni verilip verilmeyeceğine karar vermek için kullanılan ayrıntı birimi paketlerdir. B, A öğesine bağımlıysa ancak A, B tarafından görülemiyorsa analiz sırasında B derlemesi girişimi başarısız olur.

Bir pakete görünürlük vermenin, kendi başına alt paketlerine görünürlük sağlamadığını unutmayın. Paket ve alt paketler hakkında daha fazla bilgi için Kavramlar ve terminoloji bölümüne bakın.

Prototip oluşturmak için --check_visibility=false işaretini ayarlayarak hedef görünürlüğüyle ilgili uygulamayı devre dışı bırakabilirsiniz. Bu, gönderilen koddaki üretim kullanımı için yapılmamalıdır.

Görünürlüğü kontrol etmenin birincil yolu, kural hedeflerindeki visibility özelliğini kullanmaktır. Bu bölümde, bu özelliğin biçimi ve bir hedefin görünürlüğünün nasıl belirleneceği açıklanmaktadır.

Görünürlük spesifikasyonları

Tüm kural hedeflerinde, etiketler listesini alan bir visibility özelliği bulunur. Her etiket aşağıdaki biçimlerden birine sahiptir. Son biçim dışında, bunlar yalnızca gerçek bir hedefe karşılık gelmeyen söz dizimsel yer tutuculardır.

  • "//visibility:public": Tüm paketlere erişim izni verir. (Başka bir spesifikasyonla birleştirilemez.)

  • "//visibility:private": Ek erişim izni vermez; yalnızca bu paketteki hedefler bu hedefi kullanabilir. (Diğer spesifikasyonlarla birleştirilemez.)

  • "//foo/bar:__pkg__": //foo/bar öğesine erişim izni verir (ancak alt paketlerine izin vermez).

  • "//foo/bar:__subpackages__": //foo/bar ürününe ve tüm doğrudan ve dolaylı alt paketlerine erişim izni verir.

  • "//some_pkg:my_package_group": Belirtilen package_group kapsamındaki tüm paketlere erişim izni verir.

    • Paket grupları, paketleri belirtmek için farklı bir söz dizimi kullanır. Paket grubu içinde "//foo/bar:__pkg__" ve "//foo/bar:__subpackages__" formları sırasıyla "//foo/bar" ve "//foo/bar/..." ile değiştirilir. Benzer şekilde, "//visibility:public" ve "//visibility:private" yalnızca "public" ve "private" değerleridir.

Örneğin, //some/package:mytarget parametresinin visibility değeri [":__subpackages__", "//tests:__pkg__"] olarak ayarlanmışsa //some/package/... kaynak ağacının bir parçası olan herhangi bir hedefin yanı sıra //tests/BUILD içinde tanımlanan ancak //tests/integration/BUILD içinde tanımlanan hedefler tarafından kullanılamayan hedefler tarafından kullanılabilir.

En iyi uygulama: Aynı paket grubu tarafından birden fazla hedefin görünür olmasını sağlamak için her bir hedefin visibility özelliğinde listeyi tekrarlamak yerine bir package_group kullanın. Bu, okunabilirliği artırır ve listelerin senkronize edilmesini önler.

Kural hedef görünürlüğü

Bir kural hedefinin görünürlüğü:

  1. Ayarlanmışsa visibility özelliğinin değeri veya aksi takdirde

  2. Hedefin BUILD dosyasındaki package ifadesinin default_visibility bağımsız değişkeninin değeri (böyle bir beyan varsa)

  3. //visibility:private.

En iyi uygulama: default_visibility öğesini herkese açık olarak ayarlamaktan kaçının. Prototip oluşturma veya küçük kod tabanlarında kolaylık sağlayabilir ancak kod tabanı büyüdükçe yanlışlıkla herkese açık hedefler oluşturma riski artar. Paketin herkese açık arayüzünün bir parçası olan hedeflerin açıkça belirtilmesi daha iyidir.

Örnek

Dosya //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"],
)

Dosya //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",
    ],
)

Oluşturulan dosya hedefi görünürlüğü

Oluşturulan bir dosya hedefi, onu oluşturan kural hedefiyle aynı görünürlüğe sahiptir.

Kaynak dosya hedefi görünürlüğü

exports_files yöntemini çağırarak kaynak dosya hedefinin görünürlüğünü açıkça ayarlayabilirsiniz. exports_files hizmetine hiçbir visibility bağımsız değişkeni iletilmediğinde, görünürlük herkese açık hale gelir. exports_files, oluşturulan bir dosyanın görünürlüğünü geçersiz kılmak için kullanılamaz.

exports_files çağrısında görünmeyen kaynak dosya hedefleri için görünürlük, --incompatible_no_implicit_file_export işaretinin değerine bağlıdır:

  • Bayrak ayarlanırsa görünürlük gizli olur.

  • Aksi takdirde, eski davranış geçerlidir: Görünürlük, BUILD dosyasının default_visibility değeriyle aynıdır veya varsayılan bir görünürlük belirtilmediyse gizlidir.

Eski davranışı kullanmaktan kaçının. Kaynak dosya hedefi gizli olmayan görünürlüğe ihtiyaç duyduğunda her zaman bir exports_files bildirimi yazın.

En iyi uygulama: Mümkün olduğunda, kaynak dosya yerine bir kural hedefini göstermeyi tercih edin. Örneğin, .java dosyasında exports_files yöntemini çağırmak yerine dosyayı gizli olmayan bir java_library hedefine sarmalayın. Genel olarak, kural hedefleri yalnızca aynı paket içinde bulunan kaynak dosyalara doğrudan başvurmalıdır.

Örnek

Dosya //frobber/data/BUILD:

exports_files(["readme.txt"])

Dosya //frobber/bin/BUILD:

cc_binary(
  name = "my-program",
  data = ["//frobber/data:readme.txt"],
)

Yapılandırma ayarı görünürlüğü

Geçmişte Bazel, select() anahtarlarında referans verilen config_setting hedefleri için görünürlük zorunlu kılmamıştı. Bu eski davranışı kaldırmak için iki işaret vardır:

  • --incompatible_enforce_config_setting_visibility bu hedefler için görünürlük kontrolü sağlar. Taşıma işlemine yardımcı olmak için, visibility belirtmeyen tüm config_setting öğelerinin de herkese açık olarak kabul edilmesine (paket düzeyindeki default_visibility bağımsız olarak) neden olur.

  • --incompatible_config_setting_private_default_visibility, diğer tüm kural hedeflerinde olduğu gibi, visibility belirtmeyen config_setting'lerin, paketin default_visibility değerine uyması ve gizli görünürlükten yararlanmasına neden olur. --incompatible_enforce_config_setting_visibility ayarlanmazsa işlem yok demektir.

Eski davranışı kullanmaktan kaçının. Paket zaten uygun bir default_visibility belirtmiyorsa geçerli paketin dışında kullanılması amaçlanan tüm config_setting açık bir visibility içermelidir.

Paket grubu hedef görünürlüğü

package_group hedeflerin visibility özelliği yok. Bunlar her zaman herkes tarafından görülebilir.

Dolaylı bağımlılıkların görünürlüğü

Bazı kuralların dolaylı bağımlılıkları vardır. Bunlar, BUILD dosyasında belirtilmemiş olan ancak bu kuralın her örneğinde bulunan bağımlılıklardır. Örneğin bir cc_library kuralı, kural hedeflerinin her birinden C++ derleyiciyi temsil eden yürütülebilir bir hedefe örtülü bağımlılık oluşturabilir.

Böyle bir örtülü bağımlılığın görünürlüğü, kuralın (veya özelliğin) tanımlandığı .bzl dosyasını içeren paketle ilgili olarak kontrol edilir. Örneğimizde, C++ derleyicisi, cc_library kuralının tanımıyla aynı pakette bulunduğu sürece gizli olabilir. Dolaylı bağımlılık tanımda görünmüyorsa yedek olarak cc_library hedefine göre kontrol edilir.

--incompatible_visibility_private_attributes_at_definition hizmetini devre dışı bırakarak bu davranışı değiştirebilirsiniz. Devre dışı bırakıldığında örtülü bağımlılıklar diğer tüm bağımlılıklar gibi ele alınır. Bu, bağımlı olan hedefin (ör. C++ derleyicimiz) kuralın her örneğine görünür olması gerektiği anlamına gelir. Pratikte bu genellikle hedefin herkesin görünür olması gerektiği anlamına gelir.

Bir kuralın kullanımını belirli paketlerle kısıtlamak istiyorsanız bunun yerine yükleme görünürlüğünü kullanın.

Görünürlüğü yükle

Yükleme görünürlüğü, bir .bzl dosyasının mevcut paketin dışındaki diğer BUILD veya .bzl dosyalarından yüklenip yüklenemeyeceğini kontrol eder.

Hedef görünürlük, hedefler tarafından kapsüllenen kaynak kodunu nasıl koruduğu gibi, yük görünürlüğü de .bzl dosyaları tarafından kapsüllenen derleme mantığını korur. Örneğin, bir BUILD dosyasının yazarı bazı tekrarlanan hedef tanımlarını .bzl dosyasındaki bir makroda hesaba katmak isteyebilir. Yük görünürlüğünün korunması olmadan, makrolarının aynı çalışma alanında diğer ortak çalışanlar tarafından yeniden kullanıldığını bulabilirler. Bu durumda makronun değiştirilmesi, diğer ekiplerin derlemelerini bozar.

Bir .bzl dosyasının karşılık gelen bir kaynak dosya hedefinin olabileceğini veya olmayabileceğini unutmayın. Bu durumda, yük görünürlüğü ile hedef görünürlüğün çakıştığının garantisi yoktur. Yani aynı BUILD dosyası, .bzl dosyasını yükleyebilir ancak filegroup öğesinin srcs içinde (veya tam tersi) listelemeyebilir. Bu durum, bazen belge oluşturma veya test etme gibi amaçlarla .bzl dosyalarını kaynak kodu olarak kullanmak isteyen kurallar için sorunlara neden olabilir.

Prototip oluşturmak için --check_bzl_visibility=false ayarlayarak yük görünürlüğünün uygulanmasını devre dışı bırakabilirsiniz. --check_visibility=false için olduğu gibi, bu işlem gönderilen kod için de yapılmamalıdır.

Yükleme görünürlüğü, Bazel 6.0'dan itibaren kullanılabilmektedir.

Yük görünürlüğü beyan ediliyor

Bir .bzl dosyasının yük görünürlüğünü ayarlamak için dosya içinden visibility() işlevini çağırın. visibility() bağımsız değişkeni, tıpkı package_group öğesinin packages özelliği gibi, paket spesifikasyonlarının bir listesidir. Ancak, visibility() negatif paket özelliklerini kabul etmez.

visibility() çağrısı, üst düzeyde (bir işlevin içinde değil) dosya başına yalnızca bir kez yapılmalı ve ideal olarak load() ifadelerinin hemen ardından gelmelidir.

Hedef görünürlüğün aksine, varsayılan yükleme görünürlüğü her zaman herkese açıktır. visibility() işlevini çağırmayan dosyalar her zaman çalışma alanının herhangi bir yerinden yüklenebilir. Paket dışında kullanım için özel olarak tasarlanmamış tüm yeni .bzl dosyalarının en üstüne visibility("private") eklemek iyi bir fikirdir.

Örnek

# //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

...

Görünürlük uygulamalarını yükle

Bu bölümde, yük görünürlüğü beyanlarını yönetmeyle ilgili ipuçları açıklanmaktadır.

Görünürlükleri dikkate alma

Birden fazla .bzl dosyasının aynı görünürlüğe sahip olması gerektiğinde, bunların paket özelliklerini ortak bir listede hesaba katmak faydalı olabilir. Örneğin:

# //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)

...

Bu, çeşitli .bzl dosyalarının görünürlükleri arasında kazayla oluşan sapmaları önlemeye yardımcı olur. Ayrıca clients listesi büyük olduğunda daha okunaklı olur.

Görünürlükleri oluşturma

Bazen bir .bzl dosyasının, birden fazla küçük izin verilenler listesinden oluşan bir izin verilenler listesi için görünür olması gerekebilir. Bu, package_group öğesinin includes özelliği aracılığıyla diğer package_group öğelerini dahil etmesine benzer.

Yaygın olarak kullanılan bir makroyu kullanımdan kaldırdığınızı varsayalım. Paketin yalnızca mevcut kullanıcılar ve kendi ekibinizin sahip olduğu paketler tarafından görülebilmesini istiyorsunuz. Şöyle yazabilirsiniz:

# //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)

Paket gruplarıyla tekilleştirme

Hedef görünürlüğün aksine, yük görünürlüğünü package_group açısından tanımlayamazsınız. Hem hedef görünürlüğü hem de yük görünürlüğü için aynı izin verilenler listesini yeniden kullanmak istiyorsanız en iyi yöntem, paket özellikleri listesini bir .bzl dosyasına taşımaktır. Bu dosya, her iki bildirim türünde de buna işaret edebilir. Yukarıdaki Görünürlükleri dikkate alma bölümünde verilen örneği temel alarak şöyle yazabilirsiniz:

# //mylib/BUILD

load(":internal_defs", "clients")

package_group(
    name = "my_pkg_grp",
    packages = clients,
)

Bu işlem yalnızca listede negatif paket özellikleri yoksa çalışır.

Tek tek sembolleri koruma

Adı alt çizgiyle başlayan hiçbir Starlark sembolü başka bir dosyadan yüklenemez. Bu, özel simge oluşturmayı kolaylaştırır ancak bu simgeleri sınırlı bir güvenilir dosya grubuyla paylaşmanıza izin vermez. Diğer yandan, yük görünürlüğü, diğer paketlerin .bzl file öğenizi görebileceklerini kontrol etmenizi sağlar ancak alt çizgisiz sembollerin yüklenmesini önlemenize izin vermez.

Daha ayrıntılı bir kontrol elde etmek için bu iki özelliği birleştirebilirsiniz.

# //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-görünürlük Derlemesi Aracı lint'i

Kullanıcılar internal veya private adlı bir dizinden dosya yüklerse kullanıcı dosyası bu dizinin üst öğesi altında olmadığında uyarı sağlayan bir Buildifier lint dosyası bulunur. Bu hata analizi, yükleme görünürlüğü özelliğinden önce çalışır ve .bzl dosyalarının görünürlüğü bildirdiği çalışma alanlarında gerekli değildir.