इस पेज पर, Bazel के दो विज़िबिलिटी सिस्टम के बारे में बताया गया है: टारगेट विज़िबिलिटी और लोड विज़िबिलिटी.
इन दोनों सुविधाओं के दिखने से, दूसरे डेवलपर को आपकी लाइब्रेरी के पब्लिक एपीआई और उन्हें लागू करने से जुड़ी जानकारी में अंतर करने में मदद मिलती है. साथ ही, जैसे-जैसे आपका फ़ाइल फ़ोल्डर आगे बढ़ता है वैसे-वैसे स्ट्रक्चर को लागू करने में मदद मिलती है. किसी सार्वजनिक एपीआई को बंद करते समय भी, 'किसको दिखे' सेटिंग का इस्तेमाल किया जा सकता है. इससे, नए उपयोगकर्ताओं को अस्वीकार करते समय, मौजूदा उपयोगकर्ताओं को अनुमति दी जा सकती है.
टारगेट विज़िबिलिटी
टारगेट विज़िबिलिटी से यह कंट्रोल होता है कि आपके टारगेट पर कौन निर्भर कर सकता है — यानी कि कौन टारगेट कर सकता है, जैसे कि deps
जैसे किसी एट्रिब्यूट में.
टारगेट B
के लिए टारगेट A
तब ही दिखता है, जब वे एक ही पैकेज में शामिल हों या A
, B
के पैकेज के बारे में जानकारी देता हो. इसलिए, पैकेज को साफ़ तौर पर समझने की यूनिट में यह तय किया जाता है कि उसे ऐक्सेस देना है या नहीं. अगर B
, A
पर निर्भर है, लेकिन A
को B
नहीं दिखता, तो विश्लेषण के दौरान 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"],
)
कॉन्फ़िगरेशन सेटिंग किसको दिखे
अब तक, बेज़ल ने
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
जिसका इस्तेमाल मौजूदा पैकेज से बाहर किए जाने के लिए किया जाना चाहिए, अगर उसके पास सही default_visibility
न हो, तो उसके लिए साफ़ तौर पर 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
में शामिल नहीं की जा सकती. इसी तरह, BUILD
फ़ाइल भी लोड नहीं हो सकती. इसकी वजह से, कभी-कभी उन नियमों के लिए समस्याएं हो सकती हैं जो .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
फ़ाइल अच्छी तरह से दिख रही हो.