किसको दिखाई दे

किसी समस्या की शिकायत करें सोर्स देखें Nightly · 7.4 .

इस पेज पर, Basel के दो विज़िबिलिटी सिस्टम के बारे में जानकारी दी गई है: टारगेट विज़िबिलिटी और लोड विज़िबिलिटी.

विज़िबिलिटी से जुड़ी दोनों सेटिंग से अन्य डेवलपर को आपकी लाइब्रेरी के सार्वजनिक एपीआई और उसे लागू करने से जुड़ी जानकारी के बीच अंतर करने में मदद मिलती है. साथ ही, आपका फ़ाइल फ़ोल्डर बढ़ता है. इससे स्ट्रक्चर को लागू करने में भी मदद मिलती है. किसी सार्वजनिक एपीआई को बंद करते समय, 'दिखाई जा रही है' एट्रिब्यूट का इस्तेमाल करके, मौजूदा उपयोगकर्ताओं को अनुमति दी जा सकती है और नए उपयोगकर्ताओं को अनुमति नहीं दी जा सकती.

दिखने वाले टारगेट (विज्ञापन के लिए सही दर्शक चुनना)

टारगेट किसको दिखे से यह कंट्रोल किया जाता है कि आपके टारगेट पर कौन निर्भर हो सकता है — यानी कि deps जैसे एट्रिब्यूट में आपके टारगेट के लेबल का इस्तेमाल कौन कर सकता है.

टारगेट A, टारगेट B को दिखता है. ऐसा तब होता है, जब वे एक ही पैकेज में हों या A, B के पैकेज को देखने की अनुमति देता हो. इसलिए, पैकेज, ऐक्सेस की अनुमति देने या न देने का फ़ैसला लेने के लिए, जानकारी की ज़्यादा सटीक इकाई होते हैं. अगर B, A पर निर्भर करता है, लेकिन B को A नहीं दिखता, तो विश्लेषण के दौरान B बनाने की कोई भी कोशिश फ़ेल हो जाती है.

ध्यान दें कि किसी पैकेज को दिखने की अनुमति देने से, उसके सब-पैकेज अपने-आप दिखने लगते हैं. पैकेज और सबपैकेज के बारे में ज़्यादा जानकारी के लिए, कॉन्सेप्ट और शब्दावली देखें.

प्रोटोटाइपिंग के लिए, --check_visibility=false फ़्लैग को सेट करके, टारगेट के दिखने की सेटिंग पर रोक लगाई जा सकती है. सबमिट किए गए कोड में प्रोडक्शन के इस्तेमाल के लिए ऐसा नहीं किया जाना चाहिए.

प्रॉडक्ट दिखने को कंट्रोल करने का मुख्य तरीका है, नियम के टारगेट पर visibility एट्रिब्यूट का इस्तेमाल करना. इस सेक्शन में इस एट्रिब्यूट के फ़ॉर्मैट के बारे में बताया गया है. साथ ही, यह तय करने का तरीका बताया गया है कि आपका टारगेट कितने लोगों को दिखेगा.

प्रॉडक्ट के दिखने की जानकारी

नियम के सभी टारगेट में एक visibility एट्रिब्यूट होता है, जो लेबल की सूची लेता है. हर लेबल का फ़ॉर्मैट, इनमें से कोई एक होता है. आखिरी फ़ॉर्म को छोड़कर, ये सिर्फ़ वाक्यात्मक प्लेसहोल्डर हैं जो किसी भी असल टारगेट से जुड़े नहीं हैं.

  • "//visibility:public": सभी पैकेज का ऐक्सेस देता है. (इसे किसी अन्य स्पेसिफ़िकेशन के साथ नहीं जोड़ा जा सकता.)

  • "//visibility:private": यह कोई अतिरिक्त ऐक्सेस नहीं देता है; सिर्फ़ इस पैकेज में शामिल टारगेट इस टारगेट का इस्तेमाल कर सकते हैं. (इसे किसी अन्य स्पेसिफ़िकेशन के साथ नहीं जोड़ा जा सकता.)

  • "//foo/bar:__pkg__": //foo/bar का ऐक्सेस देता है (लेकिन इसके सबपैकेज नहीं).

  • "//foo/bar:__subpackages__": //foo/bar और इसके सभी डायरेक्ट और इनडायरेक्ट सबपैकेज का ऐक्सेस देता है.

  • "//some_pkg:my_package_group": यह किसी package_group के सभी पैकेज का ऐक्सेस देता है.

    • पैकेज ग्रुप, पैकेज की जानकारी देने के लिए अलग-अलग सिंटैक्स का इस्तेमाल करते हैं. पैकेज ग्रुप में, "//foo/bar:__pkg__" और "//foo/bar:__subpackages__" फ़ॉर्म को "//foo/bar" और "//foo/bar/..." से बदल दिया जाता है. इसी तरह, "//visibility:public" और "//visibility:private" सिर्फ़ "public" और "private" हैं.

उदाहरण के लिए, अगर //some/package:mytarget का visibility, [":__subpackages__", "//tests:__pkg__"] पर सेट है, तो इसका इस्तेमाल //some/package/... सोर्स ट्री के साथ-साथ //tests/BUILD में तय किए गए किसी भी टारगेट के लिए किया जा सकता है. हालांकि, इसका इस्तेमाल //tests/integration/BUILD में तय किए गए टारगेट के लिए नहीं किया जा सकता.

सबसे सही तरीका: पैकेज के एक ही सेट को कई टारगेट दिखाने के लिए, हर टारगेट के visibility एट्रिब्यूट में मौजूद सूची को दोहराने के बजाय, package_group का इस्तेमाल करें. इससे आसानी से पढ़ा जा सकता है और सूचियों को सिंक होने से रोका जा सकता है.

नियम टारगेट किसको दिखे

नियम के टारगेट की स्थिति:

  1. अगर सेट हो, तो इसके visibility एट्रिब्यूट का मान या कुछ और

  2. टारगेट की BUILD फ़ाइल में, package स्टेटमेंट के default_visibility आर्ग्युमेंट की वैल्यू का इस्तेमाल किया जाता है. ऐसा तब किया जाता है, जब इस तरह का एलान मौजूद हो या

  3. //visibility:private.

सबसे सही तरीका: default_visibility को 'सार्वजनिक' पर सेट करने से बचें. यह प्रोटोटाइपिंग या छोटे कोडबेस में सुविधाजनक हो सकता है, लेकिन कोडबेस बढ़ने पर अनजाने में सार्वजनिक टारगेट बनने का जोखिम भी बढ़ जाता है. यह साफ़ तौर पर बताना बेहतर होता है कि कौनसे टारगेट, पैकेज के सार्वजनिक इंटरफ़ेस का हिस्सा हैं.

उदाहरण

फ़ाइल //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"],
)

फ़ाइल //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",
    ],
)

जनरेट की गई फ़ाइल के टारगेट की सेटिंग

जनरेट किया गया फ़ाइल टारगेट, उस नियम के टारगेट के बराबर दिखता है जो इसे जनरेट करता है.

सोर्स फ़ाइल का टारगेट विज़िबिलिटी

exports_files को कॉल करके, सोर्स फ़ाइल टारगेट की दिखने की सेटिंग को साफ़ तौर पर सेट किया जा सकता है. जब exports_files को कोई visibility तर्क पास नहीं किया जाता है, तो यह 'किसको दिखे' सेटिंग को सार्वजनिक कर देता है. जनरेट की गई फ़ाइल के दिखने की सेटिंग बदलने के लिए, exports_files का इस्तेमाल नहीं किया जा सकता.

उन सोर्स फ़ाइल टारगेट के लिए जो exports_files को किए गए कॉल में नहीं दिखते हैं, उनके लिए 'फ़्लैग' की वैल्यू --incompatible_no_implicit_file_export पर निर्भर करती है:

  • अगर फ़्लैग सेट है, तो 'किसको दिखे' सेटिंग 'निजी' के तौर पर सेट होती है.

  • ऐसा न होने पर, लेगसी कार्रवाई लागू होती है: BUILD फ़ाइल की default_visibility के दिखने की ही तरह होती है या डिफ़ॉल्ट रूप से 'किसको दिखे' सेटिंग निजी न होने पर, यह 'निजी' पर सेट होती है.

लेगसी व्यवहार पर भरोसा करने से बचें. जब भी किसी सोर्स फ़ाइल टारगेट को गैर-निजी दिखने की ज़रूरत हो, तो हमेशा exports_files से जुड़ी जानकारी लिखें.

सबसे सही तरीका: जब भी मुमकिन हो, सोर्स फ़ाइल के बजाय नियम के टारगेट को दिखाएं. उदाहरण के लिए, किसी .java फ़ाइल पर exports_files को कॉल करने के बजाय, फ़ाइल को ऐसे java_library टारगेट में रैप करें जो निजी नहीं है. आम तौर पर, नियम के टारगेट में सिर्फ़ उन सोर्स फ़ाइलों का रेफ़रंस होना चाहिए जो एक ही पैकेज में मौजूद हों.

उदाहरण

फ़ाइल //frobber/data/BUILD:

exports_files(["readme.txt"])

फ़ाइल //frobber/bin/BUILD:

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

कॉन्फ़िगरेशन सेटिंग किसको दिखे

अब तक, Bazel ने select() की कुंजियों में रेफ़रंस दिए गए config_setting टारगेट के लिए, दिखने की सेटिंग लागू नहीं की है. इस लेगसी व्यवहार को हटाने के लिए, दो फ़्लैग हैं:

  • --incompatible_enforce_config_setting_visibility से, इन टारगेट के लिए 'किसको दिखे' सेटिंग चालू हो जाएगी. माइग्रेशन में मदद करने के लिए, इसकी वजह से किसी ऐसे config_setting को सार्वजनिक माना जाता है जो visibility के बारे में नहीं बताता है. भले ही, पैकेज-लेवल default_visibility कुछ भी हो.

  • --incompatible_config_setting_private_default_visibility की वजह से config_setting होते हैं, जो पैकेज के default_visibility के हिसाब से visibility तय नहीं करते हैं और किसी भी दूसरे नियम के टारगेट की तरह, 'निजी' के तौर पर सेट हो जाते हैं. अगर --incompatible_enforce_config_setting_visibility सेट नहीं है, तो यह काम नहीं करेगा.

लेगसी व्यवहार पर भरोसा करने से बचें. मौजूदा पैकेज के बाहर इस्तेमाल किए जाने वाले किसी भी config_setting में, साफ़ तौर पर visibility होना चाहिए. ऐसा तब होना चाहिए, जब पैकेज में सही default_visibility तय न किया गया हो.

पैकेज ग्रुप टारगेट की विज़िबिलिटी

package_group टारगेट में visibility एट्रिब्यूट नहीं है. ये हमेशा सार्वजनिक तौर पर दिखते हैं.

इंप्लिसिट डिपेंडेंसी की विज़िबिलिटी

कुछ नियमों में अहम डिपेंडेंसी होती हैं — ऐसी डिपेंडेंसी जिन्हें BUILD फ़ाइल में नहीं बताया गया है, लेकिन वे उस नियम के हर उदाहरण में मौजूद होती हैं. उदाहरण के लिए, cc_library नियम अपने हर नियम के टारगेट से, C++ कंपाइलर को दिखाने वाले एक ऐसे टारगेट पर, डिफ़ॉल्ट रूप से डिपेंडेंसी बना सकता है जिसे चलाया जा सकता है.

फ़िलहाल, जानकारी दिखाने के लिए इन इंप्लिसिट डिपेंडेंसी को किसी अन्य डिपेंडेंसी की तरह माना जाता है. इसका मतलब है कि जिस टारगेट पर निर्भर किया जा रहा है (जैसे, हमारा C++ कंपाइलर) वह नियम के हर इंस्टेंस को दिखना चाहिए. आम तौर पर, इसका मतलब है कि टारगेट सार्वजनिक तौर पर दिखना चाहिए.

--incompatible_visibility_private_attributes_at_definition को सेट करके, इस व्यवहार को बदला जा सकता है. चालू होने पर, सवाल में शामिल टारगेट सिर्फ़ उस नियम को दिखना चाहिए जो इसे एक छिपी हुई डिपेंडेंसी के तौर पर बताता है. इसका मतलब है कि यह उस पैकेज में दिखना चाहिए जिसमें .bzl फ़ाइल है, जिसमें नियम तय किया गया है. हमारे उदाहरण में, C++ कंपाइलर तब तक निजी रह सकता है, जब तक वह cc_library नियम की परिभाषा के हिसाब से उसी पैकेज में रहता है.

लोड की गई इमेज किसको दिखे

लोड विज़िबिलिटी से यह कंट्रोल होता है कि किसी .bzl फ़ाइल को दूसरी BUILD या .bzl फ़ाइलों से लोड किया जा सकता है या नहीं.

जिस तरह टारगेट के दिखने की सेटिंग, टारगेट में शामिल किए गए सोर्स कोड को सुरक्षित रखती है उसी तरह लोड के दिखने की सेटिंग, .bzl फ़ाइलों में शामिल किए गए बिल्ड लॉजिक को सुरक्षित रखती है. उदाहरण के लिए, हो सकता है कि BUILD फ़ाइल का लेखक, .bzl फ़ाइल में बार-बार आने वाली टारगेट परिभाषाओं को मैक्रो में शामिल करना चाहे. हो सकता है कि लोड दृश्यता की सुरक्षा के बिना, उन्हें अपना मैक्रो उसी फ़ाइल फ़ोल्डर में अन्य सहयोगियों द्वारा फिर से उपयोग किया गया मिल जाए, जिससे मैक्रो में बदलाव करने से अन्य टीमों का बिल्ड टूट जाता है.

ध्यान दें कि .bzl फ़ाइल में, सोर्स फ़ाइल का टारगेट हो सकता है या नहीं. अगर ऐसा होता है, तो इस बात की कोई गारंटी नहीं है कि लोड विज़िबिलिटी और टारगेट विज़िबिलिटी एक ही हो. इसका मतलब है कि वही BUILD फ़ाइल .bzl फ़ाइल को लोड कर सकती है, लेकिन उसे filegroup के srcs में शामिल नहीं कर पाएगी. इससे कभी-कभी उन नियमों में समस्याएं आ सकती हैं जो .bzl फ़ाइलों को सोर्स कोड के तौर पर इस्तेमाल करना चाहते हैं. जैसे, दस्तावेज़ जनरेट करने या टेस्टिंग के लिए.

प्रोटोटाइप बनाने के लिए, --check_bzl_visibility=false सेट करके, लोड दिखने की ज़रूरी शर्त को बंद किया जा सकता है. --check_visibility=false की तरह ही, सबमिट किए गए कोड के लिए ऐसा नहीं किया जाना चाहिए.

लोड की जानकारी देखने की सुविधा, Bazel 6.0 से उपलब्ध है.

लोड किया जा रहा है या नहीं, इसकी जानकारी दी जा रही है

.bzl फ़ाइल के लोड होने पर दिखने की सेटिंग सेट करने के लिए, फ़ाइल में जाकर visibility() फ़ंक्शन को कॉल करें. visibility() के लिए आर्ग्युमेंट, पैकेज की खास जानकारी की सूची होती है. यह वैसी ही होती है जैसे कि package_group के packages एट्रिब्यूट के लिए. हालांकि, visibility() पैकेज की नेगेटिव जानकारी स्वीकार नहीं करता.

visibility() को हर फ़ाइल में सिर्फ़ एक बार, सबसे ऊपर (किसी फ़ंक्शन में नहीं) और load() स्टेटमेंट के ठीक बाद कॉल किया जाना चाहिए.

टारगेट की दृश्यता के उलट, डिफ़ॉल्ट लोड की दृश्यता हमेशा सार्वजनिक होती है. visibility() को कॉल न करने वाली फ़ाइलें, वर्कस्पेस में कहीं से भी लोड की जा सकती हैं. किसी ऐसी नई .bzl फ़ाइल के सबसे ऊपर visibility("private") जोड़ना बेहतर होता है जिसे खास तौर पर पैकेज के बाहर इस्तेमाल करने के लिए न बनाया गया हो.

उदाहरण

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

...

लोड दिखने के तरीके

इस सेक्शन में, लोड दिखने की जानकारी को मैनेज करने के बारे में सलाह दी गई है.

दिखने वाले विज्ञापनों के फ़ैक्टर तय करना

जब एक से ज़्यादा .bzl फ़ाइलों को एक जैसा दिखना चाहिए, तो उनके पैकेज की खास बातों को एक ही सूची में शामिल करना मददगार हो सकता है. उदाहरण के लिए:

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

...

इससे, अलग-अलग .bzl फ़ाइलों के दिखने के तरीके में अनजाने में होने वाले बदलावों को रोकने में मदद मिलती है. clients सूची बड़ी होने पर भी, इसे पढ़ना आसान होता है.

विज़ुअल तौर पर लिखना

कभी-कभी हो सकता है कि .bzl फ़ाइल, अनुमति वाली सूची में दिखे, जिसमें कई छोटी-छोटी फ़ाइलें शामिल हों. यह उसी तरह है जिस तरह कोई package_group, अपने includes एट्रिब्यूट की मदद से अन्य package_group को शामिल कर सकता है.

मान लें कि आपको किसी ऐसे मैक्रो का इस्तेमाल बंद करना है जिसका इस्तेमाल काफ़ी लोग करते हैं. आपको इसे सिर्फ़ मौजूदा उपयोगकर्ताओं और अपनी टीम के मालिकाना हक वाले पैकेज को दिखाना है. आपके पास यह लिखने का विकल्प है:

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

पैकेज ग्रुप की मदद से डुप्लीकेट कॉन्टेंट हटाना

टारगेट विज़िबिलिटी के उलट, package_group के हिसाब से लोड विज़िबिलिटी तय नहीं की जा सकती. अगर आपको टारगेट के तौर पर दिखने वाले कॉन्टेंट और 'लोड किसको दिखे', दोनों के लिए अनुमति वाली एक ही सूची का फिर से इस्तेमाल करना है, तो पैकेज से जुड़ी खास जानकारी की सूची को .bzl फ़ाइल में ले जाना बेहतर होगा. यहां दोनों तरह की अनुमतियों का इस्तेमाल किया जा सकता है. ऊपर दिए गए दिखने वाले आंकड़ों के फ़ैक्टर में दिए गए उदाहरण को ध्यान में रखते हुए, यह लिखा जा सकता है:

# //mylib/BUILD

load(":internal_defs", "clients")

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

यह तरीका सिर्फ़ तब काम करता है, जब सूची में नेगेटिव पैकेज से जुड़ी कोई खास जानकारी शामिल न हो.

अलग-अलग सिंबल की सुरक्षा

किसी भी Starlark सिंबल को किसी दूसरी फ़ाइल से लोड नहीं किया जा सकता, जिसका नाम अंडरस्कोर से शुरू होता है. इससे निजी प्रतीक बनाना आसान हो जाता है, लेकिन इससे आप इन प्रतीकों को सीमित विश्वसनीय फ़ाइलों के साथ शेयर नहीं कर सकते. वहीं दूसरी ओर, 'लोड किसको दिखे' सेटिंग से आपको यह कंट्रोल करने की सुविधा मिलती है कि आपके .bzl file अन्य पैकेज किस तरह के हो सकते हैं. हालांकि, इससे आपको बिना अंडरस्कोर वाले सिंबल के लोड होने से रोकने की अनुमति नहीं मिलती है.

अच्छी बात यह है कि बेहतर कंट्रोल पाने के लिए, इन दोनों सुविधाओं को एक साथ इस्तेमाल किया जा सकता है.

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

Buildifier lint एक ऐसी सुविधा है जो चेतावनी देती है. यह चेतावनी तब दी जाती है, जब उपयोगकर्ता internal या private नाम की डायरेक्ट्री से कोई फ़ाइल लोड करते हैं और उनकी फ़ाइल उस डायरेक्ट्री के पैरंट डायरेक्ट्री में मौजूद नहीं होती. यह लिंट, फ़ाइल लोड होने पर उसकी स्थिति दिखाने की सुविधा से पहले का है. यह उन वर्कस्पेस में ज़रूरी नहीं है जहां .bzl फ़ाइलों में, फ़ाइल की स्थिति की जानकारी दी गई है.