इस पेज पर, Bagel के दो विज़िबिलिटी सिस्टम के बारे में जानकारी दी गई है: टारगेट विज़िबिलिटी और लोड विज़िबिलिटी.
विज़िबिलिटी से जुड़ी दोनों सेटिंग से अन्य डेवलपर को आपकी लाइब्रेरी के सार्वजनिक एपीआई और उसे लागू करने से जुड़ी जानकारी के बीच अंतर करने में मदद मिलती है. साथ ही, आपका फ़ाइल फ़ोल्डर बढ़ता है. इससे स्ट्रक्चर को लागू करने में भी मदद मिलती है. सार्वजनिक एपीआई को बंद करते समय, 'किसको दिखे' सेटिंग का भी इस्तेमाल किया जा सकता है. इससे मौजूदा उपयोगकर्ताओं को अनुमति देने और नए एपीआई को अस्वीकार करने की अनुमति मिलती है.
दिखने वाले टारगेट (विज्ञापन के लिए सही दर्शक चुनना)
टारगेट किसको दिखे से यह कंट्रोल किया जाता है कि आपके टारगेट पर कौन निर्भर हो सकता है — यानी कि 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
का इस्तेमाल करें. इससे आसानी से पढ़ा जा सकता है और सूचियों को सिंक होने से रोका जा सकता है.
नियम टारगेट किसको दिखे
नियम के टारगेट की विज़िबिलिटी:
अगर सेट हो, तो इसके
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"],
)
कॉन्फ़िगरेशन सेटिंग किसको दिखे
अब तक, Basel ने 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
सेट नहीं है, तो यह नहीं चलेगा.
लेगसी व्यवहार पर भरोसा करने से बचें. अगर पैकेज में सही default_visibility
मौजूद नहीं है, तो मौजूदा पैकेज के बाहर इस्तेमाल किए जाने वाले config_setting
में, साफ़ तौर पर visibility
होना चाहिए.
पैकेज ग्रुप का टारगेट किसको दिखे
package_group
टारगेट में visibility
एट्रिब्यूट नहीं है. वे हमेशा सार्वजनिक रूप से दिखती हैं.
इंप्लिसिट डिपेंडेंसी की विज़िबिलिटी
कुछ नियमों में इंप्लिसिट डिपेंडेंसी होती हैं —
ऐसी डिपेंडेंसी जो BUILD
फ़ाइल में नहीं लिखी जाती हैं, लेकिन
उस नियम के हर इंस्टेंस से जुड़ी होती हैं. उदाहरण के लिए, cc_library
नियम अपने नियम के हर टारगेट की वजह से, C++ कंपाइलर को दिखाने वाले एक्ज़ीक्यूटेबल टारगेट पर डिपेंडेंसी बना सकता है.
इस तरह की इंप्लिसिट डिपेंडेंसी के दिखने की जांच उस पैकेज के हिसाब से की जाती है जिसमें .bzl
फ़ाइल होती है, जिसमें नियम (या पहलू) की जानकारी होती है. हमारे उदाहरण में, C++ कंपाइलर तब तक निजी रह सकता है, जब तक वह cc_library
नियम की परिभाषा के मुताबिक उसी पैकेज में हो. फ़ॉलबैक के तौर पर, अगर
डेफ़िनिशन में इंप्लिसिट डिपेंडेंसी नहीं दिख रही है, तो cc_library
टारगेट के हिसाब से इसकी जांच की जाती है.
--incompatible_visibility_private_attributes_at_definition
को बंद करके, ऐसा किया जा सकता है.
बंद होने पर, इंप्लिसिट डिपेंडेंसी को किसी दूसरी डिपेंडेंसी की तरह माना जाता है.
इसका मतलब है कि जिस टारगेट पर भरोसा किया जा रहा है (जैसे कि C++ कंपाइलर), वह नियम के हर इंस्टेंस में दिखना चाहिए. आम तौर पर, इसका मतलब है कि टारगेट
लोगों के पास होना ज़रूरी है.
अगर आपको किसी नियम के इस्तेमाल को कुछ खास पैकेज तक सीमित रखना है, तो इसके बजाय लोड विज़िबिलिटी का इस्तेमाल करें.
विज़िबिलिटी लोड करें
लोड दिखने की सेटिंग से यह कंट्रोल किया जाता है कि .bzl
फ़ाइल को अन्य BUILD
या .bzl
फ़ाइलों से लोड किया जा सकता है या नहीं.
जिस तरह टारगेट विज़िबिलिटी, टारगेट के ज़रिए इनकैप्सुलेट किए गए सोर्स कोड को टारगेट करती है उसी तरह लोड दिखने की सेटिंग, बिल्ड लॉजिक को सुरक्षित रखती है. बिल्ड लॉजिक, .bzl
फ़ाइलों में एन्क्रिप्ट यानी सुरक्षित किया जाता है. उदाहरण के लिए, हो सकता है कि BUILD
फ़ाइल का लेखक, .bzl
फ़ाइल में बार-बार आने वाली टारगेट परिभाषाओं को मैक्रो में शामिल करना चाहे. हो सकता है कि लोड दृश्यता की सुरक्षा के बिना, उन्हें अपने मैक्रो का फिर से उपयोग उसी फ़ाइल फ़ोल्डर में अन्य सहयोगियों द्वारा फिर से उपयोग किया गया हो, जिससे मैक्रो में बदलाव करने से अन्य टीमों का बिल्ड टूट जाता है.
ध्यान दें कि .bzl
फ़ाइल से जुड़ा सोर्स फ़ाइल टारगेट हो भी सकता है और नहीं भी.
अगर ऐसा होता है, तो इस बात की कोई गारंटी नहीं है कि लोड के दिखने की सेटिंग और टारगेट के तौर पर दिखने वाला विज्ञापन एक जैसा होगा. इसका मतलब है कि वही BUILD
फ़ाइल, .bzl
फ़ाइल को लोड कर सकती है, लेकिन उसे filegroup
के srcs
में शामिल नहीं कर पाएगी. इसकी वजह से, कभी-कभी उन नियमों में समस्या आ सकती है जो सोर्स कोड के तौर पर .bzl
फ़ाइलों का इस्तेमाल करना चाहते हैं, जैसे कि दस्तावेज़ जनरेट करना या जांच करना.
प्रोटोटाइपिंग के लिए, --check_bzl_visibility=false
को सेट करके लोड किए गए 'किसको दिखे' सेटिंग को बंद किया जा सकता है. --check_visibility=false
की तरह ही, सबमिट किए गए कोड के लिए ऐसा नहीं किया जाना चाहिए.
Basel 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-विज़िबिलिटी बिल्डिफ़ायर लिंट
एक बिल्डिफ़ायर लिंट होता है, जो उस स्थिति में चेतावनी देता है, जब उपयोगकर्ता internal
या private
नाम की डायरेक्ट्री से कोई फ़ाइल लोड करते हैं. ऐसा तब होता है, जब उपयोगकर्ता की फ़ाइल उस डायरेक्ट्री के पैरंट नीचे न हो. यह लिंट, लोड होने की जानकारी दिखाने की सुविधा से पहले का है. साथ ही, यह उन फ़ाइल फ़ोल्डर में गैर-ज़रूरी है जहां .bzl
फ़ाइलें, दिखने की सेटिंग के बारे में बताती हैं.