BazelCon 2022, 16 नवंबर से 17 नवंबर तक न्यूयॉर्क में और ऑनलाइन उपलब्ध है.
आज ही रजिस्टर करें!

पहलू

संग्रह की मदद से व्यवस्थित रहें अपनी प्राथमिकताओं के आधार पर, कॉन्टेंट को सेव करें और कैटगरी में बांटें.

इस पेज पर, अलग-अलग चीज़ों के इस्तेमाल से जुड़ी बुनियादी बातें और उनके फ़ायदों के बारे में बताया गया है. साथ ही, इस पेज के बारे में आसान और बेहतर उदाहरण भी दिए गए हैं.

पहलुओं में अतिरिक्त जानकारी और कार्रवाइयों के साथ बिल्ड डिपेंडेंसी ग्राफ़ को बढ़ाना शामिल है. कुछ सामान्य स्थितियां, जब पहलू उपयोगी हो सकते हैं:

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

आसपेक्ट बेसिक

BUILD फ़ाइलें किसी प्रोजेक्ट के सोर्स कोड का ब्यौरा देती हैं: प्रोजेक्ट की कौनसी फ़ाइलें, सोर्स के तौर पर बनाई जाती हैं, उन फ़ाइलों से कौनसे आर्टफ़ैक्ट (टारगेट) बनाए जाने चाहिए, उन फ़ाइलों के बीच में कौन-कौनसी निर्भरियां हैं वगैरह. बेज़ल इस जानकारी का इस्तेमाल बिल्ड बनाने के लिए करती हैं. यानी कि कंपाइलर या लिंकर जैसी कार्रवाइयां करने के लिए ज़रूरी कार्रवाइयों के सेट का पता लगाया जाता है. बेज़ल ने टारगेट के बीच डिपेंडेंसी ग्राफ़ बनाकर, ऐसी कार्रवाइयों को इकट्ठा करने के लिए इस ग्राफ़ पर विज़िट किया है.

इस BUILD फ़ाइल पर विचार करें:

java_library(name = 'W', ...)
java_library(name = 'Y', deps = [':W'], ...)
java_library(name = 'Z', deps = [':W'], ...)
java_library(name = 'Q', ...)
java_library(name = 'T', deps = [':Q'], ...)
java_library(name = 'X', deps = [':Y',':Z'], runtime_deps = [':T'], ...)

यह BUILD फ़ाइल इस डिपेंडेंसी में दिखाए गए डिपेंडेंसी ग्राफ़ के बारे में बताती है:

बिल्ड ग्राफ़

पहला डायग्राम. BUILD फ़ाइल डिपेंडेंसी ग्राफ़.

बेजल ऊपर दिए गए उदाहरण में हर टारगेट के लिए उससे जुड़े नियम (इस मामले में &kot;java_library&kot;) के लागू करने के फ़ंक्शन को कॉल करके इस डिपेंडेंसी ग्राफ़ का विश्लेषण करता है. नियम लागू करने वाले फ़ंक्शन ऐसी कार्रवाइयां करते हैं जो .jarफ़ाइल जैसी गतिविधियां बनाती हैं. साथ ही, उन कंपनियों की जगहों और नामों जैसी जानकारी पास करती हैं, जो सेवा देने वाली कंपनियों में उन टारगेट की रिवर्स डिपेंडेंसी पर निर्भर करती हैं.

आसपेक्ट रेशियो, नियमों को लागू करने के तरीके से मिलते-जुलते होते हैं. ये फ़ंक्शन, फ़ंक्शन जनरेट करते हैं और सामान लौटाने की सुविधा देते हैं. हालांकि, उनकी क्षमता इस बात पर निर्भर करती है कि उनके लिए डिपेंडेंसी ग्राफ़ कैसे बनाया गया है. एक पहलू का लागू करना और उन सभी एट्रिब्यूट की सूची शामिल है जो इसे लागू करते हैं. एक ऐसा पहलू A पर विचार करें जो &&tt>डेप&कोट्स नाम के एट्रिब्यूट के साथ काम करता हो. इस आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) को टारगेट X पर लागू किया जा सकता है. इससे आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) नोड A (X) जनरेट होता है. अपने ऐप्लिकेशन के दौरान, असर {0/} बार-बार उन सभी टारगेट पर लागू होता है जिनके बारे में X, अपने &कोटेशन और कोट में एट्रिब्यूट के बारे में बताता है (A' की प्रचार सूची में मौजूद सभी एट्रिब्यूट).

इस तरह, टारगेट X के आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) लागू करने पर, एक सिंगल कोट (शब्द) &कोटेशन ग्राफ़ मिलता है. नीचे दिए गए चित्र में, टारगेट का मूल डिपेंडेंसी ग्राफ़ दिखता है:

पहलू के साथ ग्राफ़ बनाएं

दूसरा डायग्राम. आसपेक्ट रेशियो वाला ग्राफ़ बनाएं.

जिन किनारों को गहरे रंग में दिखाया गया है वे लागू किए गए सेट में मौजूद विशेषताओं के किनारे होते हैं. इसलिए, इस उदाहरण में runtime_deps किनारा शैडो नहीं किया जाता. इसके बाद, शैडो ग्राफ़ के सभी नोड पर आसपेक्ट रेशियो लागू किया जाता है. यह ठीक वैसा ही होता है जैसा मूल ग्राफ़ के नोड पर नियम लागू करने का तरीका शुरू किया जाता है.

आसान उदाहरण

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

def _print_aspect_impl(target, ctx):
    # Make sure the rule has a srcs attribute.
    if hasattr(ctx.rule.attr, 'srcs'):
        # Iterate through the files that make up the sources and
        # print their paths.
        for src in ctx.rule.attr.srcs:
            for f in src.files.to_list():
                print(f.path)
    return []

print_aspect = aspect(
    implementation = _print_aspect_impl,
    attr_aspects = ['deps'],
)

आइए उदाहरण को अलग-अलग हिस्सों में बांटते हैं और हर एक की अलग-अलग जांच करते हैं.

आसपेक्ट रेशियो की जानकारी

print_aspect = aspect(
    implementation = _print_aspect_impl,
    attr_aspects = ['deps'],
)

आसपेक्ट डेफ़िनिशन, नियम की परिभाषाओं से मिलती-जुलती हैं और aspect फ़ंक्शन का इस्तेमाल करके बताई गई हैं.

एक नियम की तरह ही, एक पहलू का भी लागू करने का फ़ंक्शन है, जो इस मामले में _print_aspect_impl है.

attr_aspects, नियम एट्रिब्यूट की एक सूची है, जिसके साथ आसपेक्ट रेशियो लागू होता है. इस मामले में, यह चौड़ाई उन नियमों के deps एट्रिब्यूट के साथ लागू होगी जिन पर यह लागू होती है.

attr_aspects का एक और सामान्य तर्क ['*'] है, जो किसी नियम की सभी विशेषताओं के बारे में बताता है.

आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) लागू करना

def _print_aspect_impl(target, ctx):
    # Make sure the rule has a srcs attribute.
    if hasattr(ctx.rule.attr, 'srcs'):
        # Iterate through the files that make up the sources and
        # print their paths.
        for src in ctx.rule.attr.srcs:
            for f in src.files.to_list():
                print(f.path)
    return []

आसपेक्ट रेशियो के फ़ंक्शन, नियम लागू करने वाले फ़ंक्शन की तरह ही होते हैं. ये सेवा देने वाली कंपनियां वापस करती हैं, कार्रवाइयां जनरेट कर सकती हैं और दो तर्क ले सकती हैं:

  • target: वह टारगेट जिसे लागू किया जा रहा है.
  • ctx: ctx ऑब्जेक्ट, जिसका इस्तेमाल एट्रिब्यूट को ऐक्सेस करने और आउटपुट और कार्रवाइयों को जनरेट करने के लिए किया जा सकता है.

लागू करने का फ़ंक्शन, ctx.rule.attr के ज़रिए टारगेट के नियम की विशेषताओं को ऐक्सेस कर सकता है. यह सेवा उन कंपनियों की जांच कर सकती है जो उस टारगेट पर उपलब्ध कराई जाती हैं जिस पर यह लागू होता है. ऐसा target आर्ग्युमेंट की मदद से किया जाता है.

सेवा देने वाली कंपनियों की सूची दिखाने के लिए आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) ज़रूरी है. इस उदाहरण में, आसपेक्ट रेशियो कुछ भी नहीं देता, इसलिए यह एक खाली सूची दिखाता है.

कमांड लाइन का इस्तेमाल करके पहलू को लागू करना

कमांड लाइन से किसी पहलू को लागू करने का सबसे आसान तरीका --aspects तर्क का इस्तेमाल करना है. मान लें कि ऊपर पहलू को print.bzl नाम की फ़ाइल में परिभाषित किया गया था:

bazel build //MyExample:example --aspects print.bzl%print_aspect

इससे print_aspect को टारगेट example पर लागू किया जाएगा. साथ ही, टारगेट के वे सभी नियम लागू होंगे जिन्हें बार-बार deps एट्रिब्यूट का इस्तेमाल करके ऐक्सेस किया जा सकता है.

--aspects फ़्लैग एक तर्क लेता है, जो <extension file label>%<aspect top-level name> फ़ॉर्मैट में आसपेक्ट रेशियो की जानकारी है.

बेहतर उदाहरण

नीचे दिया गया उदाहरण, टारगेट करने के नियम का एक पहलू बताता है जो टारगेट में फ़ाइलों की गिनती करता है. साथ ही, उन्हें एक्सटेंशन के मुताबिक फ़िल्टर कर सकता है. यह दिखाता है कि मान देने के लिए सेवा देने वाली कंपनी का इस्तेमाल कैसे किया जाए. साथ ही, पैरामीटर को आसपेक्ट रेशियो में पास करने के लिए पैरामीटर का इस्तेमाल कैसे करें और नियम से किसी आसपेक्ट को कैसे शुरू करें.

file_count.bzl फ़ाइल:

FileCountInfo = provider(
    fields = {
        'count' : 'number of files'
    }
)

def _file_count_aspect_impl(target, ctx):
    count = 0
    # Make sure the rule has a srcs attribute.
    if hasattr(ctx.rule.attr, 'srcs'):
        # Iterate through the sources counting files
        for src in ctx.rule.attr.srcs:
            for f in src.files.to_list():
                if ctx.attr.extension == '*' or ctx.attr.extension == f.extension:
                    count = count + 1
    # Get the counts from our dependencies.
    for dep in ctx.rule.attr.deps:
        count = count + dep[FileCountInfo].count
    return [FileCountInfo(count = count)]

file_count_aspect = aspect(
    implementation = _file_count_aspect_impl,
    attr_aspects = ['deps'],
    attrs = {
        'extension' : attr.string(values = ['*', 'h', 'cc']),
    }
)

def _file_count_rule_impl(ctx):
    for dep in ctx.attr.deps:
        print(dep[FileCountInfo].count)

file_count_rule = rule(
    implementation = _file_count_rule_impl,
    attrs = {
        'deps' : attr.label_list(aspects = [file_count_aspect]),
        'extension' : attr.string(default = '*'),
    },
)

BUILD.bazel फ़ाइल:

load('//:file_count.bzl', 'file_count_rule')

cc_library(
    name = 'lib',
    srcs = [
        'lib.h',
        'lib.cc',
    ],
)

cc_binary(
    name = 'app',
    srcs = [
        'app.h',
        'app.cc',
        'main.cc',
    ],
    deps = ['lib'],
)

file_count_rule(
    name = 'file_count',
    deps = ['app'],
    extension = 'h',
)

आसपेक्ट रेशियो की जानकारी

file_count_aspect = aspect(
    implementation = _file_count_aspect_impl,
    attr_aspects = ['deps'],
    attrs = {
        'extension' : attr.string(values = ['*', 'h', 'cc']),
    }
)

यह उदाहरण दिखाता है कि आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) deps एट्रिब्यूट का इस्तेमाल करके कैसे लागू होता है.

attrs किसी पहलू के लिए विशेषताओं का एक सेट बताता है. सार्वजनिक आसपेक्ट एट्रिब्यूट string टाइप के होते हैं और उन्हें पैरामीटर कहा जाता है. पैरामीटर में values एट्रिब्यूट ज़रूर शामिल किया जाना चाहिए. इस उदाहरण में extension नाम का एक पैरामीटर है, जिसमें '*', 'h' या 'cc' मान के रूप में शामिल हैं.

आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) एट्रिब्यूट की वैल्यू, स्ट्रिंग एट्रिब्यूट से ली जाती है. इसमें पसंद के मुताबिक अनुरोध करने वाले नियम का ही नाम होता है (file_count_rule की परिभाषा देखें). पैरामीटर वाले लाइन का इस्तेमाल नहीं किया जा सकता, क्योंकि पैरामीटर को तय करने के लिए कोई सिंटैक्स नहीं है.

पहलुओं को label या label_list के प्रकार की निजी विशेषताओं की भी अनुमति है. निजी लेबल विशेषताओं का इस्तेमाल उन टूल या लाइब्रेरी पर निर्भरता तय करने के लिए किया जा सकता है जो आसपेक्ट से जनरेट हुई कार्रवाइयों के लिए ज़रूरी हैं. इस उदाहरण में कोई निजी विशेषता तय नहीं की गई है, लेकिन नीचे दिया गया कोड स्निपेट यह दिखाता है कि आप किसी टूल में आसपेक्ट को कैसे पास कर सकते हैं:

...
    attrs = {
        '_protoc' : attr.label(
            default = Label('//tools:protoc'),
            executable = True,
            cfg = "exec"
        )
    }
...

आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) लागू करना

FileCountInfo = provider(
    fields = {
        'count' : 'number of files'
    }
)

def _file_count_aspect_impl(target, ctx):
    count = 0
    # Make sure the rule has a srcs attribute.
    if hasattr(ctx.rule.attr, 'srcs'):
        # Iterate through the sources counting files
        for src in ctx.rule.attr.srcs:
            for f in src.files.to_list():
                if ctx.attr.extension == '*' or ctx.attr.extension == f.extension:
                    count = count + 1
    # Get the counts from our dependencies.
    for dep in ctx.rule.attr.deps:
        count = count + dep[FileCountInfo].count
    return [FileCountInfo(count = count)]

नियम लागू करने वाले फ़ंक्शन की तरह ही, आसपेक्ट रेशियो या फ़ंक्शन की मदद से, सेवा देने वाली कंपनियों की जानकारी मिलती है. इससे वे डिपेंडेंसी ऐक्सेस कर सकते हैं.

इस उदाहरण में, FileCountInfo को एक कंपनी के तौर पर बताया गया है, जिसमें एक count फ़ील्ड है. fields एट्रिब्यूट का इस्तेमाल करके, सेवा देने वाली कंपनी के फ़ील्ड के बारे में साफ़ तौर पर बताना सबसे सही तरीका है.

आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) ऐप्लिकेशन A (X) के लिए, सेवा देने वाली कंपनियों का सेट, उन कंपनियों का संगठन है जो टारगेट X के नियम लागू करने और आसपेक्ट रेशियो लागू करने से मिलते हैं. सेवा देने वाली जिन कंपनियों को नियम लागू किया जाता है वे अलग-अलग पहलुओं को लागू करने से पहले बनाई और फ़्रीज़ की जाती हैं. साथ ही, पहलू में बदलाव नहीं किया जा सकता. अगर किसी टारगेट और पहलू को लागू किया जाता है, तो गड़बड़ी की यह स्थिति सामने आती है. हालांकि, OutputGroupInfo (जिसका नियम और आसपेक्ट रेशियो अलग-अलग आउटपुट ग्रुप में तय किया गया हो) और InstrumentedFilesInfo (जो आसपेक्ट से लिया गया है) के अपवादों को छोड़कर, इसी तरह की जानकारी देने वाली कंपनी अलग-अलग तरह की जानकारी देती है. इसका मतलब है कि आसपेक्ट रेशियो लागू करने पर शायद DefaultInfo न दिखे.

पैरामीटर और निजी एट्रिब्यूट, ctx के एट्रिब्यूट में पास किए जाते हैं. यह उदाहरण extension पैरामीटर का संदर्भ देता है और तय करता है कि किन फ़ाइलों की गिनती करनी है.

सेवा देने वाली कंपनियों के लिए, उन एट्रिब्यूट की वैल्यू जिनके साथ आसपेक्ट रेशियो लागू किया जाता है उनकी जगह पर लागू किए गए आसपेक्ट रेशियो के नतीजों को बदल दिया जाता है. ऐसा attr_aspects सूची से होता है. उदाहरण के लिए, अगर टारगेट X को अपने डेप में Y और Z दिया गया है, तो A(X) के लिए ctx.rule.attr.deps, [A(Y), A(Z)] होगा. इस उदाहरण में, ctx.rule.attr.deps ऐसे टारगेट ऑब्जेक्ट हैं जो उन मूल टारगेट के 'deps' आसपेक्ट पर लागू करने के नतीजे हैं जिस पर आसपेक्ट रेशियो लागू किया गया है.

उदाहरण में, यह पहलू टारगेट' डिपेंडेंसी को FileCountInfo सेवा से ऐक्सेस करता है. यह फ़ाइलों की कुल ट्रांज़िटिव संख्या इकट्ठा करता है.

नियम की मदद से आसपेक्ट रेशियो बनाना

def _file_count_rule_impl(ctx):
    for dep in ctx.attr.deps:
        print(dep[FileCountInfo].count)

file_count_rule = rule(
    implementation = _file_count_rule_impl,
    attrs = {
        'deps' : attr.label_list(aspects = [file_count_aspect]),
        'extension' : attr.string(default = '*'),
    },
)

नियम लागू करने से पता चलता है कि ctx.attr.deps के ज़रिए FileCountInfo को कैसे ऐक्सेस करना है.

नियम की परिभाषा से पता चलता है कि पैरामीटर को कैसे तय किया जाए (extension) और इसे एक डिफ़ॉल्ट मान (*) दें. ध्यान दें कि कोई डिफ़ॉल्ट मान जो ##39;cc', 'h' या '*' में से एक नहीं है; आसपेक्ट रेशियो में पैरामीटर पर लगाई गई पाबंदियों की वजह से गड़बड़ी होगी.

टारगेट किए गए नियम के तहत आसपेक्ट रेशियो को बढ़ावा देना

load('//:file_count.bzl', 'file_count_rule')

cc_binary(
    name = 'app',
...
)

file_count_rule(
    name = 'file_count',
    deps = ['app'],
    extension = 'h',
)

यह बताता है कि नियम के ज़रिए extension पैरामीटर को आसपेक्ट रेशियो में कैसे पास किया जाए. नियम लागू करने में extension पैरामीटर की डिफ़ॉल्ट वैल्यू है, इसलिए extension एक वैकल्पिक पैरामीटर माना जाएगा.

जब file_count टारगेट बनाया गया था, तब हमारे आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) का आकलन खुद किया जाएगा. साथ ही, deps के ज़रिए सभी टारगेट को बार-बार ऐक्सेस किया जाएगा.