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