पहलू

अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है किसी समस्या की शिकायत करें सोर्स देखें रात · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

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

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

आसपेक्ट से जुड़ी बुनियादी बातें

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

यह 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 फ़ाइल डिपेंडेंसी ग्राफ़.

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

आसपेक्ट, नियमों से मिलते-जुलते होते हैं, क्योंकि उनमें लागू करने का फ़ंक्शन होता है जो कार्रवाइयां करने और सामान लौटाने की सेवा देने वाली कंपनियों को जनरेट करता है. हालांकि, उनकी ताकत इनसे आती है डिपेंडेंसी ग्राफ़ बनाने का तरीका. किसी पहलू को लागू किया गया है साथ ही, उन सभी एट्रिब्यूट की लिस्ट दी जाएगी जिन्हें यह समझा जाता है. ऐसे पहलू A पर विचार करें जो "deps" नाम के एट्रिब्यूट के साथ आगे बढ़ता है. यह पहलू लागू किया जा सकता है एक टारगेट X, जो आसपेक्ट ऐप्लिकेशन नोड A(X) देता है. इसे लागू करने के दौरान, आसपेक्ट A को उन सभी टारगेट पर बार-बार लागू किया जाता है जिनके बारे में X के "डेप" में बताया गया है एट्रिब्यूट (A की प्रोपगेशन लिस्ट में मौजूद सभी एट्रिब्यूट).

इसलिए, टारगेट X पर पहलू A लागू करने का एक ही काम करने पर "शैडो ग्राफ़" मिलता है में से टारगेट का ओरिजनल डिपेंडेंसी ग्राफ़, नीचे दिए गए डायग्राम में दिखाया गया है:

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

दूसरा डायग्राम. पहलुओं के साथ ग्राफ़ बनाएं.

सिर्फ़ उन किनारों को शैडो किया जाता है जो एट्रिब्यूट के किनारे मौजूद होते हैं प्रोपगेशन सेट किया जाता है, इसलिए 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 []

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

  • 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 के लिए एक नियम लागू करने से और पहलू A को लागू करना. सेवा देने वाली ऐसी कंपनियां जिन्हें लागू करने के नियम लागू होते हैं पहलुओं को लागू किए जाने से पहले बनाया और फ़्रीज़ किया जाता है और पक्ष है. अगर दोनों पर एक टारगेट और कोई पहलू लागू किया जाता है, तो यह एक गड़बड़ी है अपवाद के साथ, एक ही तरह की सेवा देने वाली कंपनी उपलब्ध कराएं 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 = '*'),
    },
)

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

नियम की परिभाषा से (extension) पैरामीटर तय करने का तरीका पता चलता है और इसे एक डिफ़ॉल्ट मान (*) दें. ध्यान दें कि अगर आपके पास एक डिफ़ॉल्ट मान है, '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 के ज़रिए बार-बार ऐक्सेस किया जा सकता है.