दृश्यता

किसी समस्या की शिकायत करना सोर्स देखना Nightly · 8.0 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

इस पेज पर, Bazel के विज़िबिलिटी सिस्टम के बारे में बताया गया है: टारगेट विज़िबिलिटी और लोड विज़िबिलिटी.

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

टारगेट किसको दिखे

टारगेट की दिखने की सेटिंग से यह तय होता है कि आपके टारगेट पर कौन निर्भर हो सकता है. इसका मतलब है कि deps जैसे किसी एट्रिब्यूट में, आपके टारगेट के लेबल का इस्तेमाल कौन कर सकता है. अगर कोई टारगेट, अपनी किसी डिपेंडेंसी की दिखने की सेटिंग का उल्लंघन करता है, तो विश्लेषण के दौरान उसे बिल्ड नहीं किया जा सकेगा.

आम तौर पर, टारगेट 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 का इस्तेमाल करें. इससे सूचियों को पढ़ना आसान हो जाता है और वे सिंक होने से नहीं रुकती हैं.

सबसे सही तरीका: किसी दूसरी टीम के प्रोजेक्ट को दिखने की अनुमति देते समय, __pkg__ के बजाय __subpackages__ को प्राथमिकता दें. इससे, प्रोजेक्ट के डेटा में बदलाव होने और नए सब-पैकेज जोड़ने पर, प्रोजेक्ट के दिखने की सेटिंग में होने वाले बदलावों से बचा जा सकता है.

नियम के टारगेट की उपलब्धता

नियम के टारगेट के दिखने की स्थिति, उसके visibility एट्रिब्यूट के आधार पर तय की जाती है. अगर एट्रिब्यूट नहीं दिया गया है, तो कोई सही डिफ़ॉल्ट एट्रिब्यूट दिया जाता है. साथ ही, उस जगह को जोड़ा जाता है जहां टारगेट तय किया गया था. अगर पैकेज में default_visibility तय किया गया है, तो सिम्बॉलिक मैक्रो में एलान नहीं किए गए टारगेट के लिए, इस डिफ़ॉल्ट का इस्तेमाल किया जाता है. अन्य सभी पैकेज और सिम्बॉलिक मैक्रो में एलान किए गए टारगेट के लिए, डिफ़ॉल्ट तौर पर सिर्फ़ ["//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/..."],
)

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

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

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

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

सोर्स फ़ाइल के टारगेट की उपलब्धता

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

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

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 को सार्वजनिक माना जाता है. भले ही, पैकेज-लेवल default_visibility कुछ भी हो. ऐसा तब भी होता है, जब config_setting में visibility की जानकारी न दी गई हो.

  • --incompatible_config_setting_private_default_visibility config_setting को पैकेज के default_visibility का पालन करने के लिए मजबूर करता है. साथ ही, किसी भी दूसरे नियम के टारगेट की तरह ही, visibility के न होने पर निजी तौर पर दिखने की सेटिंग पर फ़ॉलबैक करता है. अगर --incompatible_enforce_config_setting_visibility सेट नहीं है, तो यह काम नहीं करेगा.

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

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

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

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

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

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

अगर आपको किसी नियम के इस्तेमाल को कुछ पैकेज तक सीमित करना है, तो इसके बजाय लोड की जाने वाली प्रॉपर्टी का इस्तेमाल करें.

विज़िबिलिटी और सिंबल मैक्रो

इस सेक्शन में बताया गया है कि विज़िबिलिटी सिस्टम, सिंबल मैक्रो के साथ कैसे इंटरैक्ट करता है.

सिंबल वाले मैक्रो में जगहें

विज्ञापन दिखाने की सुविधा के सिस्टम की एक अहम जानकारी यह है कि हम किसी एलान की जगह कैसे तय करते हैं. जिन टारगेट को सिंबल मैक्रो में एलान नहीं किया गया है उनके लिए, जगह सिर्फ़ वह पैकेज है जहां टारगेट मौजूद है -- BUILD फ़ाइल का पैकेज. हालांकि, सिंबल मैक्रो में बनाए गए टारगेट के लिए, वह पैकेज ही जगह होती है जिसमें .bzl फ़ाइल होती है. इसमें मैक्रो की परिभाषा (my_macro = macro(...) स्टेटमेंट) दिखती है. जब किसी टारगेट को कई नेस्ट किए गए टारगेट के अंदर बनाया जाता है, तो हमेशा सबसे अंदर मौजूद सिंबल मैक्रो की परिभाषा का इस्तेमाल किया जाता है.

इसी सिस्टम का इस्तेमाल यह तय करने के लिए किया जाता है कि किसी डिपेंडेंसी के दिखने की जांच किस जगह पर की जाए. अगर डेटा का इस्तेमाल करने वाला टारगेट, मैक्रो के अंदर बनाया गया था, तो हम उस पैकेज के बजाय, सबसे अंदर मौजूद मैक्रो की परिभाषा देखते हैं जिसमें डेटा का इस्तेमाल करने वाला टारगेट मौजूद है.

इसका मतलब है कि जिन मैक्रो का कोड एक ही पैकेज में तय किया गया है वे एक-दूसरे के लिए अपने-आप "फ़्रेंड" बन जाते हैं. //lib:defs.bzl में तय किए गए किसी मैक्रो से सीधे तौर पर बनाया गया कोई भी टारगेट, //lib में तय किए गए किसी भी अन्य मैक्रो से देखा जा सकता है. इससे कोई फ़र्क़ नहीं पड़ता कि मैक्रो असल में किन पैकेज में इंस्टैंशिएट किए गए हैं. इसी तरह, ये //lib/BUILD और उसके लेगसी मैक्रो में सीधे तौर पर तय किए गए टारगेट देख सकते हैं और उन्हें देखा जा सकता है. इसके उलट, अगर एक ही पैकेज में मौजूद कम से कम एक टारगेट को सिंबल मैक्रो से बनाया गया है, तो हो सकता है कि वे एक-दूसरे को न देख पाएं.

सिंबल वाले मैक्रो के लागू करने वाले फ़ंक्शन में, visibility पैरामीटर में मैक्रो के visibility एट्रिब्यूट की असरदार वैल्यू होती है. यह वैल्यू, मैक्रो को कॉल करने की जगह को जोड़ने के बाद दिखती है. मैक्रो के लिए, अपने किसी टारगेट को कॉलर को एक्सपोर्ट करने का स्टैंडर्ड तरीका यह है कि इस वैल्यू को टारगेट के एलान के साथ फ़ॉरवर्ड किया जाए, जैसा कि some_rule(..., visibility = visibility) में किया गया है. जिन टारगेट में यह एट्रिब्यूट शामिल नहीं होता है वे मैक्रो को कॉल करने वाले को तब तक नहीं दिखेंगे, जब तक कॉलर मैक्रो की परिभाषा वाले पैकेज में न हो. इस व्यवहार का मतलब है कि सबमैक्रोस के नेस्ट किए गए कॉल की चेन में, हर कॉल visibility = visibility को पास कर सकता है. साथ ही, हर लेवल पर कॉल करने वाले को इनर मैक्रो के एक्सपोर्ट किए गए टारगेट को फिर से एक्सपोर्ट करता है. ऐसा करने के लिए, मैक्रो को लागू करने की किसी भी जानकारी को ज़ाहिर नहीं किया जाता.

किसी सब-मैक्रो को खास अधिकार देना

विज़िबिलिटी मॉडल में एक खास सुविधा होती है, जिसकी मदद से कोई मैक्रो, अपनी अनुमतियां किसी सबमैक्रो को दे सकता है. यह फ़ैक्टर और मैक्रो बनाने के लिए ज़रूरी है.

मान लें कि आपके पास एक मैक्रो my_macro है, जो किसी दूसरे पैकेज के नियम some_library का इस्तेमाल करके, डिपेंडेंसी एज बनाता है:

# //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", ...)

//pkg:foo_dependency टारगेट में कोई visibility नहीं दिया गया है, इसलिए यह सिर्फ़ //macro में दिखता है. यह टारगेट का इस्तेमाल करने वाले टारगेट के लिए ठीक से काम करता है. अब, अगर //lib का लेखक some_library को फिर से लिखकर, उसे मैक्रो का इस्तेमाल करके लागू करता है, तो क्या होगा?

# //lib:defs.bzl

def _impl(name, visibility, deps, ...):
    some_rule(
        # Main target, exported.
        name = name,
        visibility = visibility,
        deps = deps,
        ...)

some_library = macro(implementation = _impl, ...)

इस बदलाव के बाद, //pkg:foo_consumer की जगह अब //macro के बजाय //lib है. इसलिए, //pkg:foo_dependency का इस्तेमाल करने पर, डिपेंडेंसी के दिखने की नीति का उल्लंघन होता है. my_macro के लेखक से यह उम्मीद नहीं की जा सकती कि वह सिर्फ़ लागू करने की इस जानकारी को हल करने के लिए, visibility = ["//lib"] को डिपेंडेंसी के एलान में पास करे.

इस वजह से, जब किसी टारगेट की डिपेंडेंसी, टारगेट का एलान करने वाले मैक्रो की एट्रिब्यूट वैल्यू भी होती है, तो हम डिपेंडेंसी की विज़िबिलिटी की जांच, उसे इस्तेमाल करने वाले टारगेट की जगह मैक्रो की जगह के हिसाब से करते हैं.

इस उदाहरण में, यह पुष्टि करने के लिए कि //pkg:foo_consumer, //pkg:foo_dependency को देख सकता है या नहीं, हम देखते हैं कि //pkg:foo_dependency को my_macro में some_library के कॉल के इनपुट के तौर पर भी पास किया गया था. इसके बजाय, इस कॉल की जगह //macro के हिसाब से, डिपेंडेंसी की विज़िबिलिटी की जांच की जाती है.

यह प्रोसेस बार-बार दोहराई जा सकती है, बशर्ते कोई टारगेट या मैक्रो एलान, किसी दूसरे सिंबल मैक्रो के अंदर हो. साथ ही, उस मैक्रो के लेबल-टाइप वाले एट्रिब्यूट में डिपेंडेंसी का लेबल हो.

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

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

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

ध्यान दें कि .bzl फ़ाइल में, सोर्स फ़ाइल का टारगेट हो सकता है या नहीं. अगर ऐसा होता है, तो इस बात की कोई गारंटी नहीं है कि लोड विज़िबिलिटी और टारगेट विज़िबिलिटी एक ही हो. इसका मतलब है कि एक ही BUILD फ़ाइल, .bzl फ़ाइल को लोड कर सकती है, लेकिन उसे filegroup के srcs में शामिल नहीं कर सकती. इसके अलावा, ऐसा भी हो सकता है कि 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 फ़ाइलों में फ़ाइल की स्थिति की जानकारी दी गई है.