BazelCon 2022 16-17 নভেম্বর নিউ ইয়র্ক এবং অনলাইনে আসছে।
নিবন্ধন আজ!

ম্যাক্রো

সেভ করা পৃষ্ঠা গুছিয়ে রাখতে 'সংগ্রহ' ব্যবহার করুন আপনার পছন্দ অনুযায়ী কন্টেন্ট সেভ করুন ও সঠিক বিভাগে রাখুন।

এই পৃষ্ঠাটি ম্যাক্রো ব্যবহারের মৌলিক বিষয়গুলি কভার করে এবং সাধারণ ব্যবহারের ক্ষেত্রে, ডিবাগিং এবং নিয়মাবলী অন্তর্ভুক্ত করে৷

একটি ম্যাক্রো হল একটি ফাংশন যা BUILD ফাইল থেকে বলা হয় যা নিয়মগুলিকে তাত্ক্ষণিক করতে পারে। ম্যাক্রোগুলি প্রধানত এনক্যাপসুলেশন এবং বিদ্যমান নিয়ম এবং অন্যান্য ম্যাক্রোগুলির কোড পুনঃব্যবহারের জন্য ব্যবহৃত হয়। লোডিং পর্বের শেষে, ম্যাক্রো আর বিদ্যমান নেই, এবং Bazel শুধুমাত্র তাত্ক্ষণিক নিয়মের কংক্রিট সেট দেখে।

ব্যবহার

একটি ম্যাক্রোর জন্য সাধারণ ব্যবহারের ক্ষেত্রে যখন আপনি একটি নিয়ম পুনরায় ব্যবহার করতে চান।

উদাহরণস্বরূপ, একটি BUILD ফাইলের জেনরুল কমান্ডে হার্ডকোড করা some_arg আর্গুমেন্ট সহ //:generator ব্যবহার করে একটি ফাইল তৈরি করে:

genrule(
    name = "file",
    outs = ["file.txt"],
    cmd = "$(location //:generator) some_arg > $@",
    tools = ["//:generator"],
)

আপনি যদি বিভিন্ন আর্গুমেন্ট সহ আরও ফাইল তৈরি করতে চান তবে আপনি এই কোডটিকে একটি ম্যাক্রো ফাংশনে এক্সট্রাক্ট করতে চাইতে পারেন। ম্যাক্রো file_generator কল করা যাক, যার name এবং arg প্যারামিটার রয়েছে। নিম্নলিখিত দিয়ে জেনরুল প্রতিস্থাপন করুন:

load("//path:generator.bzl", "file_generator")

file_generator(
    name = "file",
    arg = "some_arg",
)

file_generator(
    name = "file-two",
    arg = "some_arg_two",
)

file_generator(
    name = "file-three",
    arg = "some_arg_three",
)

এখানে, আপনি //path প্যাকেজে অবস্থিত একটি .bzl ফাইল থেকে file_generator চিহ্নটি লোড করুন। একটি পৃথক .bzl ফাইলে ম্যাক্রো ফাংশন সংজ্ঞা রেখে, আপনি আপনার BUILD ফাইলগুলিকে পরিষ্কার এবং ঘোষণামূলক রাখেন, .bzl ফাইলটি ওয়ার্কস্পেসের যেকোনো প্যাকেজ থেকে লোড করা যেতে পারে।

অবশেষে, path/generator.bzl এ, মূল জেনরুলের সংজ্ঞাকে এনক্যাপসুলেট এবং প্যারামিটারাইজ করতে ম্যাক্রোর সংজ্ঞা লিখুন:

def file_generator(name, arg, visibility=None):
  native.genrule(
    name = name,
    outs = [name + ".txt"],
    cmd = "$(location //:generator) %s > $@" % arg,
    tools = ["//:generator"],
    visibility = visibility,
  )

আপনি একসাথে নিয়মগুলি চেইন করতে ম্যাক্রো ব্যবহার করতে পারেন। এই উদাহরণটি শৃঙ্খলিত জেনরুলগুলি দেখায়, যেখানে একটি জেনরুল ইনপুট হিসাবে পূর্ববর্তী জেনরুলের আউটপুট ব্যবহার করে:

def chained_genrules(name, visibility=None):
  native.genrule(
    name = name + "-one",
    outs = [name + ".one"],
    cmd = "$(location :tool-one) $@",
    tools = [":tool-one"],
    visibility = ["//visibility:private"],
  )

  native.genrule(
    name = name + "-two",
    srcs = [name + ".one"],
    outs = [name + ".two"],
    cmd = "$(location :tool-two) $< $@",
    tools = [":tool-two"],
    visibility = visibility,
  )

উদাহরণটি শুধুমাত্র দ্বিতীয় জেনুলে একটি দৃশ্যমানতার মান নির্ধারণ করে। এটি ম্যাক্রো লেখকদের মধ্যবর্তী নিয়মের আউটপুটগুলিকে কর্মক্ষেত্রে অন্যান্য লক্ষ্যগুলির উপর নির্ভরশীল থেকে আড়াল করার অনুমতি দেয়।

ম্যাক্রো প্রসারিত হচ্ছে

যখন আপনি একটি ম্যাক্রো কী করে তা তদন্ত করতে চান, প্রসারিত ফর্মটি দেখতে --output=build সহ query কমান্ডটি ব্যবহার করুন:

$ bazel query --output=build :file
# /absolute/path/test/ext.bzl:42:3
genrule(
  name = "file",
  tools = ["//:generator"],
  outs = ["//test:file.txt"],
  cmd = "$(location //:generator) some_arg > $@",
)

স্থানীয় নিয়ম তাত্ক্ষণিক করা

নেটিভ নিয়ম (নিয়ম যেগুলির load() স্টেটমেন্টের প্রয়োজন নেই) নেটিভ মডিউল থেকে ইনস্ট্যান্ট করা যেতে পারে:

def my_macro(name, visibility=None):
  native.cc_library(
    name = name,
    srcs = ["main.cc"],
    visibility = visibility,
  )

আপনি যদি প্যাকেজের নাম জানতে চান (উদাহরণস্বরূপ, কোন BUILD ফাইলটি ম্যাক্রোকে কল করছে), তাহলে native.package_name() ফাংশনটি ব্যবহার করুন। মনে রাখবেন যে native শুধুমাত্র .bzl ফাইলগুলিতে ব্যবহার করা যেতে পারে, এবং WORKSPACE বা BUILD ফাইলগুলিতে নয়৷

ম্যাক্রোতে লেবেল রেজোলিউশন

যেহেতু ম্যাক্রোগুলিকে লোডিং পর্যায়ে মূল্যায়ন করা হয়, তাই লেবেল স্ট্রিং যেমন "//foo:bar" একটি ম্যাক্রোতে দেখা যায় সেগুলি BUILD ফাইলের সাথে তুলনা করা হয় যেখানে ম্যাক্রোটি .bzl ফাইলের আপেক্ষিক না হয়ে ব্যবহৃত হয়। সংজ্ঞায়িত এই আচরণটি সাধারণত ম্যাক্রোগুলির জন্য অবাঞ্ছিত যেগুলি অন্যান্য সংগ্রহস্থলে ব্যবহার করার জন্য, যেমন তারা একটি প্রকাশিত স্টারলার্ক নিয়ম সেটের অংশ।

স্টারলার্কের নিয়মগুলির মতো একই আচরণ পেতে, Label কনস্ট্রাক্টরের সাথে লেবেল স্ট্রিংগুলি মোড়ানো:

# @my_ruleset//rules:defs.bzl
def my_cc_wrapper(name, deps = [], **kwargs):
  native.cc_library(
    name = name,
    deps = deps + select({
      # Due to the use of Label, this label is resolved within @my_ruleset,
      # regardless of its site of use.
      Label("//config:needs_foo"): [
        # Due to the use of Label, this label will resolve to the correct target
        # even if the canonical name of @dep_of_my_ruleset should be different
        # in the main workspace, such as due to repo mappings.
        Label("@dep_of_my_ruleset//tools:foo"),
      ],
      "//conditions:default": [],
    }),
    **kwargs,
  )

ডিবাগিং

  • bazel query --output=build //my/path:all আপনাকে দেখাবে যে BUILD ফাইলটি মূল্যায়নের পর কেমন দেখায়। সমস্ত ম্যাক্রো, গ্লোব, লুপ প্রসারিত হয়। পরিচিত সীমাবদ্ধতা: select করা অভিব্যক্তি বর্তমানে আউটপুটে দেখানো হয় না।

  • আপনি generator_function (যে ফাংশনটি নিয়মগুলি তৈরি করেছে) বা generator_name (ম্যাক্রোর নাম বৈশিষ্ট্য): bash $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)' এর উপর ভিত্তি করে আউটপুট ফিল্টার করতে পারেন bash $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)'

  • একটি BUILD ফাইলে ঠিক কোথায় foo রুল তৈরি হয়েছে তা খুঁজে বের করতে, আপনি নিম্নলিখিত কৌশলটি চেষ্টা করতে পারেন। BUILD ফাইলের উপরে এই লাইনটি সন্নিবেশ করুন: cc_library(name = "foo") । Bazel চালান। আপনি একটি ব্যতিক্রম পাবেন যখন নিয়ম foo তৈরি হবে (একটি নামের দ্বন্দ্বের কারণে), যা আপনাকে সম্পূর্ণ স্ট্যাক ট্রেস দেখাবে।

  • আপনি ডিবাগিংয়ের জন্য মুদ্রণও ব্যবহার করতে পারেন। এটি লোডিং পর্বের সময় একটি DEBUG লগ লাইন হিসাবে বার্তাটি প্রদর্শন করে। বিরল ক্ষেত্রে ব্যতীত, হয় print কলগুলি সরিয়ে দিন, অথবা ডিপোতে কোড জমা দেওয়ার আগে debugging প্যারামিটারের অধীনে তাদের শর্তসাপেক্ষ করুন যা False এ ডিফল্ট হয়৷

ত্রুটি

আপনি একটি ত্রুটি নিক্ষেপ করতে চান, ব্যর্থ ফাংশন ব্যবহার করুন. কী ভুল হয়েছে এবং কীভাবে তাদের BUILD ফাইলটি ঠিক করবেন তা ব্যবহারকারীকে স্পষ্টভাবে ব্যাখ্যা করুন। ত্রুটি ধরা সম্ভব নয়।

def my_macro(name, deps, visibility=None):
  if len(deps) < 2:
    fail("Expected at least two values in deps")
  # ...

কনভেনশন

  • সমস্ত পাবলিক ফাংশন (যে ফাংশনগুলি আন্ডারস্কোর দিয়ে শুরু হয় না) যে নিয়মগুলিকে তাত্ক্ষণিক করে তাদের একটি name যুক্তি থাকতে হবে। এই যুক্তিটি ঐচ্ছিক হওয়া উচিত নয় (একটি ডিফল্ট মান দেবেন না)।

  • Python কনভেনশন অনুসরণ করে পাবলিক ফাংশনগুলির একটি ডকস্ট্রিং ব্যবহার করা উচিত।

  • BUILD ফাইলে, ম্যাক্রোর name আর্গুমেন্ট অবশ্যই একটি কীওয়ার্ড আর্গুমেন্ট হতে হবে (পজিশনাল আর্গুমেন্ট নয়)।

  • একটি ম্যাক্রো দ্বারা উত্পন্ন নিয়মের name বৈশিষ্ট্যে একটি উপসর্গ হিসাবে নাম যুক্তি অন্তর্ভুক্ত করা উচিত। উদাহরণস্বরূপ, macro(name = "foo") একটি cc_library foo এবং একটি genrule foo_gen তৈরি করতে পারে।

  • বেশিরভাগ ক্ষেত্রে, ঐচ্ছিক পরামিতিগুলির একটি ডিফল্ট মান None হওয়া উচিত। None সরাসরি দেশীয় নিয়মে পাস করা যাবে না, যা এটিকে একইভাবে বিবেচনা করে যেন আপনি কোনো যুক্তিতে পাস করেননি। সুতরাং, এই উদ্দেশ্যে এটিকে 0 , False , বা [] দিয়ে প্রতিস্থাপন করার প্রয়োজন নেই। পরিবর্তে, ম্যাক্রোর এটি তৈরি করা নিয়মগুলিকে পিছিয়ে দেওয়া উচিত, কারণ তাদের ডিফল্টগুলি জটিল হতে পারে বা সময়ের সাথে সাথে পরিবর্তিত হতে পারে। অতিরিক্তভাবে, একটি প্যারামিটার যা স্পষ্টভাবে এটির ডিফল্ট মানতে সেট করা হয় সেটির থেকে আলাদা দেখায় যা কখনই সেট করা হয় না (বা None সেট করা হয় না) যখন ক্যোয়ারী ভাষা বা বিল্ড-সিস্টেম ইন্টারনালের মাধ্যমে অ্যাক্সেস করা হয়।

  • ম্যাক্রোর একটি ঐচ্ছিক visibility যুক্তি থাকা উচিত।