দিক

এই পৃষ্ঠাটি দিকগুলি ব্যবহার করার মৌলিক এবং সুবিধাগুলি ব্যাখ্যা করে এবং সহজ এবং উন্নত উদাহরণ প্রদান করে।

দিকগুলি অতিরিক্ত তথ্য এবং ক্রিয়াকলাপ সহ নির্ভরশীলতা গ্রাফ তৈরি করার অনুমতি দেয়। কিছু সাধারণ পরিস্থিতিতে যখন দিকগুলি কার্যকর হতে পারে:

  • Bazel সংহত IDE গুলি প্রকল্প সম্পর্কে তথ্য সংগ্রহ করতে দিকগুলি ব্যবহার করতে পারে৷
  • কোড তৈরির সরঞ্জামগুলি লক্ষ্য-অজ্ঞেয়বাদী পদ্ধতিতে তাদের ইনপুটগুলি চালানোর জন্য দিকগুলিকে লিভারেজ করতে পারে। একটি উদাহরণ হিসাবে, BUILD ফাইলগুলি প্রোটোবাফ লাইব্রেরির সংজ্ঞাগুলির একটি শ্রেণিবিন্যাস নির্দিষ্ট করতে পারে, এবং ভাষা-নির্দিষ্ট নিয়মগুলি একটি নির্দিষ্ট ভাষার জন্য প্রোটোবাফ সমর্থন কোড তৈরির ক্রিয়াগুলি সংযুক্ত করতে দিকগুলি ব্যবহার করতে পারে।

দৃষ্টিভঙ্গি মৌলিক

BUILD ফাইলগুলি একটি প্রজেক্টের সোর্স কোডের একটি বিবরণ প্রদান করে: কোন সোর্স ফাইলগুলি প্রজেক্টের অংশ, সেই ফাইলগুলি থেকে কী আর্টিফ্যাক্ট ( লক্ষ্যগুলি ) তৈরি করা উচিত, সেই ফাইলগুলির মধ্যে নির্ভরতা কী ইত্যাদি৷ Bazel এই তথ্যগুলি একটি বিল্ড সম্পাদন করতে ব্যবহার করে , অর্থাৎ, এটি আর্টিফ্যাক্টগুলি (যেমন কম্পাইলার বা লিঙ্কার চালানো) তৈরি করার জন্য প্রয়োজনীয় ক্রিয়াগুলির সেট বের করে এবং সেই ক্রিয়াগুলি সম্পাদন করে। Bazel লক্ষ্যগুলির মধ্যে একটি নির্ভরতা গ্রাফ তৈরি করে এবং সেই ক্রিয়াগুলি সংগ্রহ করতে এই গ্রাফটি পরিদর্শন করে এটি সম্পন্ন করে।

নিম্নলিখিত 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 graph

চিত্র 1. ফাইল BUILD গ্রাফ তৈরি করুন।

Bazel উপরের উদাহরণে প্রতিটি লক্ষ্যের জন্য সংশ্লিষ্ট নিয়মের (এই ক্ষেত্রে "java_library") একটি বাস্তবায়ন ফাংশন কল করে এই নির্ভরতা গ্রাফ বিশ্লেষণ করে। নিয়ম বাস্তবায়ন ফাংশনগুলি এমন ক্রিয়া তৈরি করে যা আর্টিফ্যাক্ট তৈরি করে, যেমন .jar ফাইল, এবং তথ্য প্রদান করে, যেমন অবস্থান এবং সেই আর্টিফ্যাক্টগুলির নাম, প্রদানকারীদের সেই লক্ষ্যগুলির বিপরীত নির্ভরতাগুলিতে।

দিকগুলি নিয়মের অনুরূপ যে তাদের একটি বাস্তবায়ন ফাংশন রয়েছে যা অ্যাকশন তৈরি করে এবং প্রদানকারীদের প্রদান করে। যাইহোক, তাদের শক্তি যেভাবে তাদের জন্য নির্ভরতা গ্রাফ তৈরি করা হয়েছে তা থেকে আসে। একটি দিক একটি বাস্তবায়ন এবং এটি বরাবর প্রচারিত সমস্ত বৈশিষ্ট্যের একটি তালিকা আছে। একটি দিক A বিবেচনা করুন যা "deps" নামক বৈশিষ্ট্যগুলির সাথে প্রচার করে। এই দিকটি একটি লক্ষ্য X এ প্রয়োগ করা যেতে পারে, একটি দৃষ্টিভঙ্গি অ্যাপ্লিকেশন নোড A(X) প্রদান করে। এটির প্রয়োগের সময়, দৃষ্টিভঙ্গি A পুনরাবৃত্তিমূলকভাবে সমস্ত লক্ষ্যগুলিতে প্রয়োগ করা হয় যা X তার "deps" বৈশিষ্ট্যে (A এর প্রচার তালিকার সমস্ত বৈশিষ্ট্য) উল্লেখ করে।

এইভাবে একটি লক্ষ্য X-এ দৃষ্টিভঙ্গি A প্রয়োগ করার একটি একক কাজ নিম্নলিখিত চিত্রে দেখানো লক্ষ্যগুলির মূল নির্ভরতা গ্রাফের একটি "ছায়া গ্রাফ" প্রদান করে:

Build Graph with Aspect

চিত্র 2. দিকগুলি সহ গ্রাফ তৈরি করুন।

শুধুমাত্র যে প্রান্তগুলি ছায়াযুক্ত তা হল প্রচার সেটের বৈশিষ্ট্যগুলির সাথে প্রান্তগুলি, এইভাবে runtime_deps প্রান্তটি এই উদাহরণে ছায়াযুক্ত নয়। একটি দৃষ্টিভঙ্গি বাস্তবায়ন ফাংশন তারপর ছায়া গ্রাফের সমস্ত নোডে আহ্বান করা হয় যেভাবে মূল গ্রাফের নোডগুলিতে নিয়ম বাস্তবায়নের আহ্বান করা হয়।

সহজ উদাহরণ

এই উদাহরণটি দেখায় যে কীভাবে একটি নিয়মের জন্য উত্স ফাইলগুলি পুনরাবৃত্তভাবে মুদ্রণ করা যায় এবং এর সমস্ত নির্ভরতা যার একটি deps বৈশিষ্ট্য রয়েছে। এটি একটি দৃষ্টিভঙ্গি বাস্তবায়ন, একটি দৃষ্টিভঙ্গি সংজ্ঞা এবং কীভাবে Bazel কমান্ড লাইন থেকে দৃষ্টিভঙ্গিকে আহ্বান করতে হয় তা দেখায়।

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 এর জন্য একটি নিয়ম বাস্তবায়ন এবং দিক 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 = '*'),
    },
)

নিয়ম বাস্তবায়ন দেখায় কিভাবে ctx.attr.deps এর মাধ্যমে 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 মাধ্যমে পুনরাবৃত্তভাবে সমস্ত লক্ষ্য অ্যাক্সেসযোগ্য।