Görünürlük

Sorun bildirme Kaynağı görüntüleme Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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ı arasında ayrım yapmasına ve çalışma alanınız büyüdükçe yapıyı zorunlu kılmaya yardımcı olur. Ayrıca, herkese açık bir API'nin desteğini sonlandırırken mevcut kullanıcılara izin vermek ve yeni kullanıcıları reddetmek için de görünürlük özelliğini kullanabilirsiniz.

Hedef görünürlük

Hedef görünürlüğü, hedefinize bağlı olabilecek kullanıcıları (yani deps gibi bir özellik içinde hedefinizin etiketini kullanabilecek kullanıcıları) kontrol eder.

Aynı paketteyse veya A, B'nin paketine görünürlük sağlıyorsa bir A hedefi, B hedefine görünür. Bu nedenle, erişime izin verilip verilmeyeceğine karar vermek için paketler ayrıntı düzeyi birimidir. B, A'a bağlıysa ancak A, B tarafından görülemiyorsa B oluşturma girişimleri analiz sırasında başarısız olur.

Bir pakete görünürlük verilmesinin, alt paketlerinin de görünürlük kazanmasını 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. Gönderilen kodda üretim kullanımı için bu işlem 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 özellikleri

Tüm kural hedeflerinde, etiketlerin 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. (Başka bir spesifikasyonla birleştirilemez.)

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

  • "//foo/bar:__subpackages__": //foo/bar'a ve doğrudan ve dolaylı tüm 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", "public" ve "private"'tır.

Örneğin, //some/package:mytarget'ün visibility özelliği [":__subpackages__", "//tests:__pkg__"] olarak ayarlanmışsa //some/package/... kaynak ağacının parçası olan tüm hedeflerin yanı sıra //tests/BUILD'te tanımlanan hedefler tarafından kullanılabilir ancak //tests/integration/BUILD'te tanımlanan hedefler tarafından kullanılamaz.

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 olmasını önler.

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

Kural hedefinin görünürlüğü:

  1. Ayarlanmışsa visibility özelliğinin değeri, 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 dosya hedefi, onu oluşturan kural hedefiyle aynı görünürlüğe sahiptir.

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

exports_files işlevini çağırarak bir kaynak dosya hedefinin görünürlüğünü açıkça ayarlayabilirsiniz. exports_files işlevine visibility bağımsız değişkeni iletilmediğinde görünürlük herkese açık olur. 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çerli olur: Görünürlük, BUILD dosyasının default_visibility ile aynıdır veya varsayılan bir görünürlük belirtilmemişse gizlidir.

Eski davranışa güvenmekten 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. Kural hedefleri genellikle yalnızca aynı pakette bulunan kaynak dosyalara doğrudan referans vermelidir.

Örnek

//frobber/data/BUILD dosyası:

exports_files(["readme.txt"])

//frobber/bin/BUILD dosyası:

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

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

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

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

  • --incompatible_config_setting_private_default_visibility, visibility belirtmeyen config_setting'ların paketin default_visibility'ine uymasına ve diğer tüm kural hedeflerinde olduğu gibi gizli görünürlükte geriye dönük bir işlem yapmasına neden olur. --incompatible_enforce_config_setting_visibility ayarlanmamışsa işlem yapılmaz.

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 hedeflerinin visibility özelliği yok. Bunlar her zaman herkes tarafından görülebilir.

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

Bazı kurallarda örtülü bağımlılıklar bulunur. Bu bağımlılıklar, BUILD dosyasında belirtilmez ancak söz konusu kuralın her örneğine özgüdür. Örneğin, bir cc_library kuralı, kural hedeflerinin her biri ile C++ derleyicisini temsil eden bir yürütülebilir hedef arasında dolaylı bir bağımlılık oluşturabilir.

Bu tür bir örtülü bağımlığın görünürlüğü, kuralın (veya yönü) 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. Yedek olarak, gizli bağımlılık tanımda görünmüyorsa cc_library hedefiyle ilgili olarak kontrol edilir.

--incompatible_visibility_private_attributes_at_definition seçeneğini devre dışı bırakarak bu davranışı değiştirebilirsiniz. Devre dışı bırakılan gizli bağımlılıklar, diğer tüm bağımlılıklar gibi ele alınır. Bu, bağımlı olunan hedefin (ör. C++ derleyicimiz) kuralın her örneği tarafından görülebilmesi gerektiği anlamına gelir. Uygulamada bu, genellikle hedefin herkese açık görünürlükte olması gerektiği anlamına gelir.

Bir kuralın kullanımını belirli paketlerle kısıtlamak istiyorsanız bunun yerine yük görünürlük özelliğini 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üğü, hedefler tarafından kapsüllenen kaynak kodu koruduğu gibi, yükleme 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ükleme görünürlüğünün koruması olmadan, makrolarının aynı çalışma alanındaki diğer ortak çalışanlar tarafından yeniden kullanıldığını görebilirler. Bu durumda, makroda yapılan değişiklikler 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ükleme görünürlüğünün ve hedef görünürlüğün aynı olacağı garanti edilmez. Yani aynı BUILD dosyası .bzl dosyasını yükleyebilir ancak filegroup dosyasının srcs bölümünde listeleyebilir veya bunun tam tersini yapabilir. Bu durum, bazen doküman oluşturma veya test etme gibi .bzl dosyalarını kaynak kod olarak kullanmak isteyen kurallarda sorunlara neden olabilir.

Prototipleme için --check_bzl_visibility=false değerini ayarlayarak yükleme görünürlüğü yaptırımını devre dışı bırakabilirsiniz. --check_visibility=false ile olduğu gibi, gönderilen kod için bu işlem yapılmamalıdır.

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

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

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

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

Hedef görünürlüğün aksine, varsayılan yükleme görünürlüğü her zaman herkese açıktır. visibility() çağrısı yapmayan dosyalar, çalışma alanının herhangi bir yerinden her zaman yüklenebilir. Paket dışında kullanılmak üzere ö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

...

Yükleme görünürlüğü uygulamaları

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

Görünürlükleri çarpanlarına ayırma

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 birleştirme

Bazen bir .bzl dosyasının, birden fazla küçük izin verilenler listesinden oluşan bir izin verilenler listesi tarafından görülebilmesi gerekebilir. Bu, bir package_group'nin includes özelliği aracılığıyla diğer package_group'leri dahil etmesine benzer.

Yaygın olarak kullanılan bir makronun desteğini sonlandırdığınızı varsayalım. Yalnızca mevcut kullanıcılar ve kendi ekibinizin sahip olduğu paketler tarafından görülebilmesini istiyorsunuz. Şunu 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ükleme görünürlüğünü package_group açısından tanımlayamazsınız. Hem hedef görünürlük hem de yükleme görünürlüğü için aynı izin verilenler listesini yeniden kullanmak istiyorsanız paket spesifikasyonlarının listesini, her iki tür beyanın da referans verebileceği bir .bzl dosyasına taşımak en iyisidir. Yukarıdaki Görünürlükleri hesaba katma bölümündeki örnekten yola çıkarak şunları yazabilirsiniz:

# //mylib/BUILD

load(":internal_defs", "clients")

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

Bu işlem yalnızca liste negatif paket özellikleri içermiyorsa çalışır.

Tek tek simgelerin korunması

Adı alt çizgiyle başlayan Starlark sembolleri başka bir dosyadan yüklenemez. Bu, özel simgeler oluşturmayı kolaylaştırır ancak bu simgeleri sınırlı sayıda güvenilir dosyayla paylaşmanıza izin vermez. Öte yandan yükleme görünürlüğü, diğer paketlerin .bzl file'nizi görebileceği durumlar üzerinde kontrol sahibi olmanızı sağlar ancak alt çizgi içermeyen sembollerin yüklenmesini engellemenize izin vermez.

Neyse ki ayrıntılı denetim 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-visibility Buildifier lint

Kullanıcının dosyası söz konusu dizinin üst klasöründe değilken kullanıcılar internal veya private adlı bir dizinden dosya yüklerse uyarı veren bir Buildifier lint vardır. Bu lint, yükleme görünürlüğü özelliğinden öncedir ve .bzl dosyalarının görünürlüğü tanımladığı çalışma alanlarında gereksizdir.