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

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

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

टारगेट विज़िबिलिटी

टारगेट विज़िबिलिटी यह कंट्रोल करती है कि आपके टारगेट पर कौन निर्भर हो सकता है. इसका मतलब है कि 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 फ़ाइल में, default_visibility package स्टेटमेंट के तर्क की वैल्यू. अगर ऐसा एलान मौजूद है, तो या और

  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 ने config_setting टारगेट के लिए, 'किसको दिखे' सेटिंग लागू नहीं की है, जिनका रेफ़रंस select() की कुंजियों में किया गया है. इस लेगसी बिहेवियर को हटाने के लिए दो फ़्लैग हैं:

  • --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() को कॉल नहीं करती हैं वे कभी भी, वर्कस्पेस में कहीं से भी लोड की जा सकती हैं. visibility("private") को ऐसी किसी भी नई .bzl फ़ाइल में सबसे ऊपर जोड़ना अच्छा होता है जिसे खास तौर पर पैकेज के बाहर इस्तेमाल करने के लिए न बनाया गया हो.

उदाहरण

# //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-विज़िबिलिटी बिल्डिफ़ायर लिंट

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