इस पेज पर Bazel के दो विज़िबिलिटी सिस्टम के बारे में बताया गया है: टारगेट विज़िबिलिटी और लोड विज़िबिलिटी.
दोनों तरह की विज़िबिलिटी, अन्य डेवलपर को आपकी लाइब्रेरी के सार्वजनिक एपीआई और उसे लागू करने की जानकारी के बीच अंतर करने में मदद करती है. साथ ही, जैसे-जैसे आपका फ़ाइल फ़ोल्डर बढ़ता है, स्ट्रक्चर लागू करने में मदद करता है. 'पब्लिक एपीआई' को बंद करते समय, 'किसको दिखे' सेटिंग का इस्तेमाल भी किया जा सकता है, ताकि मौजूदा उपयोगकर्ताओं को अनुमति दी जा सके और नए उपयोगकर्ताओं को अस्वीकार किया जा सके.
टारगेट विज़िबिलिटी
टारगेट विज़िबिलिटी यह कंट्रोल करती है कि आपके टारगेट पर कौन निर्भर कर सकता है. इसका मतलब है कि deps
जैसे किसी एट्रिब्यूट में आपके टारगेट के लेबल का इस्तेमाल कौन कर सकता है.
अगर टारगेट A
एक ही पैकेज में है या
A
, B
के पैकेज को देखने की अनुमति देता है, तो टारगेट 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
का इस्तेमाल करें. इससे, सूचियों को आसानी से पढ़ा जा सकता है और
सूची को सिंक होने से रोका जाता है.
सबसे सही तरीका: किसी दूसरे टीम के प्रोजेक्ट को विज़िबिलिटी देते समय, __pkg__
पर __subpackages__
को प्राथमिकता दें, ताकि उस प्रोजेक्ट के आगे बढ़ने और नए सबपैकेज जोड़ने पर, आपको बिना किसी वजह के उन लोगों तक पहुंचने की ज़रूरत न पड़े.
नियम टारगेट किसको दिखाई दे
नियम के टारगेट को इस तरह देखा जा सकता है:
अगर यह सेट है, तो इसके
visibility
एट्रिब्यूट की वैल्यू या अन्यअगर ऐसी कोई घोषणा मौजूद है, तो टारगेट की
BUILD
फ़ाइल मेंpackage
स्टेटमेंट केdefault_visibility
आर्ग्युमेंट की वैल्यू या कोई और//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++ कंपाइलर को दिखाने वाले एक्ज़ीक्यूटेबल टारगेट पर इंप्लिसिट डिपेंडेंसी बना दे.
इस तरह की इंप्लिसिट डिपेंडेंसी की विज़िबिलिटी .bzl
फ़ाइल वाले पैकेज के हिसाब से जांची जाती है, जिसमें नियम (या पहलू) तय किया गया है. हमारे उदाहरण में, C++ कंपाइलर तब तक निजी हो सकता है, जब तक वह उसी पैकेज में रहता है जिसमें cc_library
नियम की परिभाषा है. फ़ॉलबैक के तौर पर, अगर
इंप्लिसिट डिपेंडेंसी, परिभाषा से नहीं दिखती है, तो 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,
)
यह सिर्फ़ तब काम करता है, जब सूची में पैकेज से जुड़ी कोई भी नेगेटिव जानकारी शामिल न हो.
अलग-अलग सिंबल की सुरक्षा करना
स्टारलार्क का कोई भी चिह्न जिसका नाम अंडरस्कोर से शुरू होता है उसे दूसरी फ़ाइल से लोड नहीं किया जा सकता. इससे निजी चिह्नों को बनाना आसान हो जाता है, लेकिन इन निशानों को भरोसेमंद फ़ाइलों के सीमित सेट के साथ शेयर करने की अनुमति नहीं मिलती. वहीं दूसरी ओर, लोड विज़िबिलिटी की मदद से, यह कंट्रोल किया जा सकता है कि दूसरे पैकेज में आपके .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 बिल्डिफ़ायर का लिंट
अगर उपयोगकर्ता, internal
या private
नाम की किसी डायरेक्ट्री से कोई फ़ाइल लोड करता है, तो बिल्डिफ़ायर लिंट होता है, जो चेतावनी देता है. ऐसा तब होता है, जब उपयोगकर्ता की फ़ाइल खुद उस डायरेक्ट्री के पैरंट के नीचे न हो. यह लिंट, लोड होने की जानकारी देने वाली सुविधा से पहले का है. यह उन फ़ाइल फ़ोल्डर में ज़रूरी नहीं है जहां .bzl
फ़ाइलें दिखने की जानकारी देती हैं.