টুলচেন

এই পৃষ্ঠাটি টুলচেন ফ্রেমওয়ার্ক বর্ণনা করে, যা নিয়ম লেখকদের জন্য প্ল্যাটফর্ম-ভিত্তিক সরঞ্জামগুলির নির্বাচন থেকে তাদের নিয়ম যুক্তিকে ডিকপল করার একটি উপায়। চালিয়ে যাওয়ার আগে নিয়ম এবং প্ল্যাটফর্মের পৃষ্ঠাগুলি পড়ার সুপারিশ করা হয়। এই পৃষ্ঠাটি কভার করে কেন টুলচেন প্রয়োজন, কীভাবে সেগুলিকে সংজ্ঞায়িত করতে হবে এবং ব্যবহার করতে হবে এবং কীভাবে ব্যাজেল প্ল্যাটফর্মের সীমাবদ্ধতার উপর ভিত্তি করে একটি উপযুক্ত টুলচেইন নির্বাচন করে।

প্রেরণা

আসুন প্রথমে সমস্যাটি দেখুন টুলচেনগুলি সমাধান করার জন্য ডিজাইন করা হয়েছে। ধরুন আপনি "বার" প্রোগ্রামিং ভাষা সমর্থন করার নিয়ম লিখছেন। আপনার bar_binary নিয়মটি barc কম্পাইলার ব্যবহার করে *.bar ফাইল কম্পাইল করবে, একটি টুল যা নিজেই আপনার ওয়ার্কস্পেসে অন্য টার্গেট হিসেবে তৈরি করা হয়েছে। যেহেতু bar_binary লক্ষ্যগুলি লেখেন তাদের কম্পাইলারের উপর নির্ভরতা নির্দিষ্ট করতে হবে না, তাই আপনি এটিকে একটি ব্যক্তিগত বৈশিষ্ট্য হিসাবে নিয়মের সংজ্ঞাতে যুক্ত করে একটি অন্তর্নিহিত নির্ভরতা তৈরি করেন।

bar_binary = rule(
    implementation = _bar_binary_impl,
    attrs = {
        "srcs": attr.label_list(allow_files = True),
        ...
        "_compiler": attr.label(
            default = "//bar_tools:barc_linux",  # the compiler running on linux
            providers = [BarcInfo],
        ),
    },
)

//bar_tools:barc_linux এখন প্রতিটি bar_binary টার্গেটের নির্ভরতা, তাই এটি যেকোনো bar_binary টার্গেটের আগে তৈরি করা হবে। এটি অন্য যেকোনো বৈশিষ্ট্যের মতো নিয়মের বাস্তবায়ন ফাংশন দ্বারা অ্যাক্সেস করা যেতে পারে:

BarcInfo = provider(
    doc = "Information about how to invoke the barc compiler.",
    # In the real world, compiler_path and system_lib might hold File objects,
    # but for simplicity they are strings for this example. arch_flags is a list
    # of strings.
    fields = ["compiler_path", "system_lib", "arch_flags"],
)

def _bar_binary_impl(ctx):
    ...
    info = ctx.attr._compiler[BarcInfo]
    command = "%s -l %s %s" % (
        info.compiler_path,
        info.system_lib,
        " ".join(info.arch_flags),
    )
    ...

এখানে সমস্যা হল যে কম্পাইলারের লেবেলটি bar_binary তে হার্ডকোড করা হয়েছে, তবুও বিভিন্ন টার্গেটের জন্য বিভিন্ন কম্পাইলারের প্রয়োজন হতে পারে তা নির্ভর করে তারা কোন প্ল্যাটফর্মের জন্য তৈরি করা হচ্ছে এবং কোন প্ল্যাটফর্মে তৈরি করা হচ্ছে -- যাকে যথাক্রমে টার্গেট প্ল্যাটফর্ম এবং এক্সিকিউশন প্ল্যাটফর্ম বলা হয়। উপরন্তু, নিয়ম লেখক অগত্যা এমনকি সমস্ত উপলব্ধ সরঞ্জাম এবং প্ল্যাটফর্মগুলি জানেন না, তাই নিয়মের সংজ্ঞায় তাদের হার্ডকোড করা সম্ভব নয়৷

_compiler অ্যাট্রিবিউটটিকে অ-প্রাইভেট করে ব্যবহারকারীদের উপর বোঝা সরানো একটি আদর্শ সমাধানের চেয়ে কম। তারপরে পৃথক লক্ষ্যগুলিকে এক বা অন্য প্ল্যাটফর্মের জন্য তৈরি করতে হার্ডকোড করা যেতে পারে।

bar_binary(
    name = "myprog_on_linux",
    srcs = ["mysrc.bar"],
    compiler = "//bar_tools:barc_linux",
)

bar_binary(
    name = "myprog_on_windows",
    srcs = ["mysrc.bar"],
    compiler = "//bar_tools:barc_windows",
)

আপনি প্ল্যাটফর্মের উপর ভিত্তি করে compiler চয়ন করতে select ব্যবহার করে এই সমাধানটি উন্নত করতে পারেন:

config_setting(
    name = "on_linux",
    constraint_values = [
        "@platforms//os:linux",
    ],
)

config_setting(
    name = "on_windows",
    constraint_values = [
        "@platforms//os:windows",
    ],
)

bar_binary(
    name = "myprog",
    srcs = ["mysrc.bar"],
    compiler = select({
        ":on_linux": "//bar_tools:barc_linux",
        ":on_windows": "//bar_tools:barc_windows",
    }),
)

কিন্তু এটি ক্লান্তিকর এবং প্রতিটি একক bar_binary ব্যবহারকারীর কাছে জিজ্ঞাসা করার জন্য কিছুটা বেশি। যদি এই স্টাইলটি পুরো ওয়ার্কস্পেস জুড়ে ধারাবাহিকভাবে ব্যবহার না করা হয়, তাহলে এটি এমন বিল্ডগুলির দিকে নিয়ে যায় যা একটি একক প্ল্যাটফর্মে ভাল কাজ করে কিন্তু মাল্টি-প্ল্যাটফর্ম পরিস্থিতিতে প্রসারিত হলে ব্যর্থ হয়। এটি বিদ্যমান নিয়ম বা লক্ষ্যগুলি পরিবর্তন না করে নতুন প্ল্যাটফর্ম এবং কম্পাইলারগুলির জন্য সমর্থন যোগ করার সমস্যার সমাধান করে না।

টুলচেন ফ্রেমওয়ার্ক অতিরিক্ত মাত্রার পরোক্ষ যোগ করে এই সমস্যার সমাধান করে। মূলত, আপনি ঘোষণা করেন যে আপনার নিয়মের লক্ষ্য পরিবারের কিছু সদস্যের (একটি টুলচেন প্রকার) উপর একটি বিমূর্ত নির্ভরতা রয়েছে এবং Bazel প্রযোজ্য প্ল্যাটফর্মের সীমাবদ্ধতার উপর ভিত্তি করে একটি নির্দিষ্ট লক্ষ্যে (একটি টুলচেন) স্বয়ংক্রিয়ভাবে এটি সমাধান করে। নিয়ম লেখক বা লক্ষ্য লেখকের উপলব্ধ প্ল্যাটফর্ম এবং টুলচেইনের সম্পূর্ণ সেট জানার প্রয়োজন নেই।

টুলচেইন ব্যবহার করে এমন নিয়ম লেখা

টুলচেন ফ্রেমওয়ার্কের অধীনে, নিয়মগুলি সরাসরি সরঞ্জামের উপর নির্ভর করার পরিবর্তে, তারা পরিবর্তে টুলচেনের প্রকারের উপর নির্ভর করে। একটি টুলচেন টাইপ হল একটি সাধারণ টার্গেট যা বিভিন্ন প্ল্যাটফর্মের জন্য একই ভূমিকা পরিবেশন করে এমন এক শ্রেণীর সরঞ্জামকে প্রতিনিধিত্ব করে। উদাহরণস্বরূপ, আপনি একটি টাইপ ঘোষণা করতে পারেন যা বার কম্পাইলারকে প্রতিনিধিত্ব করে:

# By convention, toolchain_type targets are named "toolchain_type" and
# distinguished by their package path. So the full path for this would be
# //bar_tools:toolchain_type.
toolchain_type(name = "toolchain_type")

পূর্ববর্তী বিভাগে নিয়ম সংজ্ঞাটি পরিবর্তন করা হয়েছে যাতে কম্পাইলারকে একটি বৈশিষ্ট্য হিসাবে গ্রহণ করার পরিবর্তে, এটি ঘোষণা করে যে এটি একটি //bar_tools:toolchain_type টুলচেন ব্যবহার করে।

bar_binary = rule(
    implementation = _bar_binary_impl,
    attrs = {
        "srcs": attr.label_list(allow_files = True),
        ...
        # No `_compiler` attribute anymore.
    },
    toolchains = ["//bar_tools:toolchain_type"],
)

ইমপ্লিমেন্টেশন ফাংশন এখন ctx.attr-এর পরিবর্তে ctx.toolchains এর অধীনে এই নির্ভরতা অ্যাক্সেস করে, টুলচেন ctx.attr কী হিসাবে ব্যবহার করে।

def _bar_binary_impl(ctx):
    ...
    info = ctx.toolchains["//bar_tools:toolchain_type"].barcinfo
    # The rest is unchanged.
    command = "%s -l %s %s" % (
        info.compiler_path,
        info.system_lib,
        " ".join(info.arch_flags),
    )
    ...

ctx.toolchains["//bar_tools:toolchain_type"] যেই টার্গেট Bazel টুলচেইন নির্ভরতা সমাধান করেছে তার ToolchainInfo প্রদানকারীকে ফেরত দেয়। ToolchainInfo অবজেক্টের ক্ষেত্রগুলি অন্তর্নিহিত টুলের নিয়ম দ্বারা সেট করা হয়; পরবর্তী বিভাগে, এই নিয়মটি এমনভাবে সংজ্ঞায়িত করা হয়েছে যে একটি barcinfo ক্ষেত্র রয়েছে যা একটি BarcInfo অবজেক্টকে আবৃত করে।

লক্ষ্যে টুলচেন সমাধানের জন্য Bazel এর পদ্ধতি নীচে বর্ণিত হয়েছে। শুধুমাত্র সমাধান করা টুলচেন টার্গেটকে আসলে bar_binary টার্গেটের নির্ভরতা করা হয়, প্রার্থী টুলচেনের পুরো স্থান নয়।

বাধ্যতামূলক এবং ঐচ্ছিক টুলচেইন

ডিফল্টরূপে, যখন একটি নিয়ম একটি বেয়ার লেবেল ব্যবহার করে একটি টুলচেইনের প্রকার নির্ভরতা প্রকাশ করে (উপরে দেখানো হয়েছে), টুলচেইনের ধরন বাধ্যতামূলক বলে বিবেচিত হয়। যদি Bazel একটি বাধ্যতামূলক টুলচেন প্রকারের জন্য একটি ম্যাচিং টুলচেন খুঁজে না পায় (নীচে টুলচেন রেজোলিউশন দেখুন), এটি একটি ত্রুটি এবং বিশ্লেষণ বন্ধ হয়ে যায়।

পরিবর্তে একটি ঐচ্ছিক টুলচেন প্রকার নির্ভরতা ঘোষণা করা সম্ভব, নিম্নরূপ:

bar_binary = rule(
    ...
    toolchains = [
        config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False),
    ],
)

যখন একটি ঐচ্ছিক টুলচেন টাইপ সমাধান করা যায় না, তখন বিশ্লেষণ চলতে থাকে এবং ctx.toolchains[""//bar_tools:toolchain_type"] এর ফলাফল None হয়।

config_common.toolchain_type ফাংশন ডিফল্ট বাধ্যতামূলক।

নিম্নলিখিত ফর্ম ব্যবহার করা যেতে পারে:

  • বাধ্যতামূলক টুলচেইন প্রকার:
    • toolchains = ["//bar_tools:toolchain_type"]
    • toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type")]
    • toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = True)]
  • ঐচ্ছিক টুলচেইন প্রকার:
    • toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False)]
bar_binary = rule(
    ...
    toolchains = [
        "//foo_tools:toolchain_type",
        config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False),
    ],
)

আপনি একই নিয়মে ফর্মগুলি মিশ্রিত করতে এবং মেলাতে পারেন। যাইহোক, যদি একই টুলচেনের ধরন একাধিকবার তালিকাভুক্ত করা হয়, তবে এটি সবচেয়ে কঠোর সংস্করণ গ্রহণ করবে, যেখানে বাধ্যতামূলকটি ঐচ্ছিক থেকে বেশি কঠোর।

লেখার দিকগুলি যা টুলচেইন ব্যবহার করে

দিকগুলির নিয়ম হিসাবে একই টুলচেন API-এ অ্যাক্সেস রয়েছে: আপনি প্রয়োজনীয় টুলচেন প্রকারগুলি সংজ্ঞায়িত করতে পারেন, প্রসঙ্গের মাধ্যমে টুলচেইন অ্যাক্সেস করতে পারেন এবং টুলচেন ব্যবহার করে নতুন অ্যাকশন তৈরি করতে তাদের ব্যবহার করতে পারেন।

bar_aspect = aspect(
    implementation = _bar_aspect_impl,
    attrs = {},
    toolchains = ['//bar_tools:toolchain_type'],
)

def _bar_aspect_impl(target, ctx):
  toolchain = ctx.toolchains['//bar_tools:toolchain_type']
  # Use the toolchain provider like in a rule.
  return []

টুলচেইন সংজ্ঞায়িত করা

একটি প্রদত্ত টুলচেন প্রকারের জন্য কিছু টুলচেইন সংজ্ঞায়িত করতে, আপনার তিনটি জিনিস প্রয়োজন:

  1. টুল বা টুল স্যুট ধরনের প্রতিনিধিত্ব করে একটি ভাষা-নির্দিষ্ট নিয়ম। নিয়ম অনুসারে এই নিয়মের নাম "_toolchain" এর সাথে প্রত্যয়িত হয়।

    1. দ্রষ্টব্য: \_toolchain নিয়ম কোনো বিল্ড অ্যাকশন তৈরি করতে পারে না। বরং, এটি অন্যান্য নিয়ম থেকে আর্টিফ্যাক্ট সংগ্রহ করে এবং টুলচেন ব্যবহার করে এমন নিয়মে ফরোয়ার্ড করে। এই নিয়মটি সমস্ত বিল্ড অ্যাকশন তৈরির জন্য দায়ী।
  2. বিভিন্ন প্ল্যাটফর্মের জন্য টুল বা টুল স্যুটের সংস্করণের প্রতিনিধিত্ব করে এই নিয়মের ধরনের বেশ কয়েকটি লক্ষ্য।

  3. এই ধরনের প্রতিটি টার্গেটের জন্য, টুলচেন ফ্রেমওয়ার্ক দ্বারা ব্যবহৃত মেটাডেটা প্রদানের জন্য জেনেরিক toolchain নিয়মের একটি সংশ্লিষ্ট লক্ষ্য। এই toolchain টার্গেটটি এই টুলচেইনের সাথে যুক্ত toolchain_type বোঝায়। এর মানে হল যে একটি প্রদত্ত _toolchain নিয়ম যেকোনো toolchain_type এর সাথে যুক্ত হতে পারে, এবং শুধুমাত্র একটি toolchain উদাহরণে যেটি এই _toolchain নিয়মটি ব্যবহার করে যে নিয়মটি একটি toolchain_type এর সাথে যুক্ত।

আমাদের চলমান উদাহরণের জন্য, এখানে একটি bar_toolchain নিয়মের একটি সংজ্ঞা রয়েছে। আমাদের উদাহরণে শুধুমাত্র একটি কম্পাইলার আছে, কিন্তু অন্যান্য টুল যেমন একটি লিঙ্কারও এটির নীচে গোষ্ঠীভুক্ত হতে পারে।

def _bar_toolchain_impl(ctx):
    toolchain_info = platform_common.ToolchainInfo(
        barcinfo = BarcInfo(
            compiler_path = ctx.attr.compiler_path,
            system_lib = ctx.attr.system_lib,
            arch_flags = ctx.attr.arch_flags,
        ),
    )
    return [toolchain_info]

bar_toolchain = rule(
    implementation = _bar_toolchain_impl,
    attrs = {
        "compiler_path": attr.string(),
        "system_lib": attr.string(),
        "arch_flags": attr.string_list(),
    },
)

নিয়মটি অবশ্যই একটি ToolchainInfo প্রদানকারীকে ফেরত দিতে হবে, যা ctx.toolchains এবং টুলচেন প্রকারের লেবেল ব্যবহার করে কনজিউমিং রুল পুনরুদ্ধার করা বস্তুতে পরিণত হয়। ToolchainInfo , struct এর মত, নির্বিচারে ক্ষেত্র-মান জোড়া রাখতে পারে। টুলচেইন ইনফোতে ঠিক কোন ক্ষেত্র যোগ করা হয়েছে তার ToolchainInfo স্পষ্টভাবে নথিভুক্ত করা উচিত। এই উদাহরণে, উপরে সংজ্ঞায়িত স্কিমা পুনরায় ব্যবহার করার জন্য একটি BarcInfo অবজেক্টে মোড়ানো মানগুলি ফিরে আসে; এই স্টাইলটি বৈধকরণ এবং কোড পুনঃব্যবহারের জন্য উপযোগী হতে পারে।

এখন আপনি নির্দিষ্ট barc কম্পাইলারের লক্ষ্য নির্ধারণ করতে পারেন।

bar_toolchain(
    name = "barc_linux",
    arch_flags = [
        "--arch=Linux",
        "--debug_everything",
    ],
    compiler_path = "/path/to/barc/on/linux",
    system_lib = "/usr/lib/libbarc.so",
)

bar_toolchain(
    name = "barc_windows",
    arch_flags = [
        "--arch=Windows",
        # Different flags, no debug support on windows.
    ],
    compiler_path = "C:\\path\\on\\windows\\barc.exe",
    system_lib = "C:\\path\\on\\windows\\barclib.dll",
)

অবশেষে, আপনি দুটি bar_toolchain লক্ষ্যগুলির জন্য toolchain সংজ্ঞা তৈরি করুন। এই সংজ্ঞাগুলি ভাষা-নির্দিষ্ট লক্ষ্যগুলিকে টুলচেইনের প্রকারের সাথে সংযুক্ত করে এবং সীমাবদ্ধতার তথ্য প্রদান করে যা Bazelকে বলে যে কখন টুলচেন একটি প্রদত্ত প্ল্যাটফর্মের জন্য উপযুক্ত।

toolchain(
    name = "barc_linux_toolchain",
    exec_compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
    ],
    target_compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
    ],
    toolchain = ":barc_linux",
    toolchain_type = ":toolchain_type",
)

toolchain(
    name = "barc_windows_toolchain",
    exec_compatible_with = [
        "@platforms//os:windows",
        "@platforms//cpu:x86_64",
    ],
    target_compatible_with = [
        "@platforms//os:windows",
        "@platforms//cpu:x86_64",
    ],
    toolchain = ":barc_windows",
    toolchain_type = ":toolchain_type",
)

উপরে আপেক্ষিক পাথ সিনট্যাক্সের ব্যবহার পরামর্শ দেয় যে এই সংজ্ঞাগুলি একই প্যাকেজে রয়েছে, তবে টুলচেনের ধরন, ভাষা-নির্দিষ্ট টুলচেন লক্ষ্য এবং toolchain সংজ্ঞা লক্ষ্যগুলি আলাদা প্যাকেজে থাকতে পারে না এমন কোনও কারণ নেই।

একটি বাস্তব বিশ্বের উদাহরণের জন্য go_toolchain দেখুন।

টুলচেইন এবং কনফিগারেশন

নিয়ম লেখকদের জন্য একটি গুরুত্বপূর্ণ প্রশ্ন হল, যখন একটি bar_toolchain লক্ষ্য বিশ্লেষণ করা হয়, তখন এটি কোন কনফিগারেশন দেখতে পায় এবং নির্ভরতার জন্য কোন রূপান্তর ব্যবহার করা উচিত? উপরের উদাহরণটি স্ট্রিং বৈশিষ্ট্যগুলি ব্যবহার করে, তবে আরও জটিল টুলচেনের জন্য কী ঘটবে যা বেজেল সংগ্রহস্থলের অন্যান্য লক্ষ্যগুলির উপর নির্ভর করে?

আসুন bar_toolchain এর আরও জটিল সংস্করণ দেখি:

def _bar_toolchain_impl(ctx):
    # The implementation is mostly the same as above, so skipping.
    pass

bar_toolchain = rule(
    implementation = _bar_toolchain_impl,
    attrs = {
        "compiler": attr.label(
            executable = True,
            mandatory = True,
            cfg = "exec",
        ),
        "system_lib": attr.label(
            mandatory = True,
            cfg = "target",
        ),
        "arch_flags": attr.string_list(),
    },
)

attr.label এর ব্যবহার একটি প্রমিত নিয়মের মতই, কিন্তু cfg প্যারামিটারের অর্থ একটু ভিন্ন।

টুলচেন রেজোলিউশনের মাধ্যমে একটি টার্গেট ("পিতামাতা" বলা হয়) থেকে টুলচেইনে নির্ভরতা একটি বিশেষ কনফিগারেশন ট্রানজিশন ব্যবহার করে যাকে "টুলচেইন ট্রানজিশন" বলা হয়। টুলচেন ট্রানজিশন কনফিগারেশনটিকে একই রাখে, তা ছাড়া এটি এক্সিকিউশন প্ল্যাটফর্মটিকে টুলচেইনের জন্য প্যারেন্টের মতো একই হতে বাধ্য করে (অন্যথায়, টুলচেনের জন্য টুলচেন রেজোলিউশন যেকোনো এক্সিকিউশন প্ল্যাটফর্ম বেছে নিতে পারে এবং অগত্যা একই হবে না পিতামাতার জন্য)। এটি টুলচেইনের যেকোন exec নির্ভরতাকে পিতামাতার বিল্ড অ্যাকশনের জন্যও নির্বাহযোগ্য হতে দেয়। টুলচেইনের যেকোন নির্ভরতা যা cfg = "target" ব্যবহার করে (অথবা যা cfg নির্দিষ্ট করে না, যেহেতু "টার্গেট" ডিফল্ট) প্যারেন্টের মতো একই টার্গেট প্ল্যাটফর্মের জন্য তৈরি করা হয়। এটি টুলচেন নিয়মগুলিকে লাইব্রেরি (উপরের system_lib অ্যাট্রিবিউট) এবং টুলস ( compiler অ্যাট্রিবিউট) উভয়ই বিল্ড নিয়মগুলিতে অবদান রাখতে দেয় যা তাদের প্রয়োজন। সিস্টেম লাইব্রেরিগুলি চূড়ান্ত আর্টিফ্যাক্টের সাথে সংযুক্ত করা হয়েছে, এবং তাই একই প্ল্যাটফর্মের জন্য তৈরি করা প্রয়োজন, যেখানে কম্পাইলার হল একটি টুল যা বিল্ড করার সময় আমন্ত্রণ জানানো হয় এবং কার্যকরী প্ল্যাটফর্মে চালানোর জন্য সক্ষম হওয়া প্রয়োজন।

টুলচেইন দিয়ে রেজিস্টার করা এবং তৈরি করা

এই মুহুর্তে সমস্ত বিল্ডিং ব্লক একত্রিত করা হয়, এবং আপনাকে কেবল Bazel এর রেজোলিউশন পদ্ধতিতে টুলচেইনগুলি উপলব্ধ করতে হবে। এটি করা হয় টুলচেইন নিবন্ধন করার মাধ্যমে, হয় register_toolchains() ব্যবহার করে একটি WORKSPACE ফাইলে, অথবা --extra_toolchains পতাকা ব্যবহার করে কমান্ড লাইনে টুলচেইনের লেবেল পাস করার মাধ্যমে।

register_toolchains(
    "//bar_tools:barc_linux_toolchain",
    "//bar_tools:barc_windows_toolchain",
    # Target patterns are also permitted, so you could have also written:
    # "//bar_tools:all",
)

এখন আপনি যখন একটি টুলচেইনের প্রকারের উপর নির্ভর করে এমন একটি লক্ষ্য তৈরি করবেন, তখন লক্ষ্য এবং কার্যকরী প্ল্যাটফর্মের উপর ভিত্তি করে একটি উপযুক্ত টুলচেইন নির্বাচন করা হবে।

# my_pkg/BUILD

platform(
    name = "my_target_platform",
    constraint_values = [
        "@platforms//os:linux",
    ],
)

bar_binary(
    name = "my_bar_binary",
    ...
)
bazel build //my_pkg:my_bar_binary --platforms=//my_pkg:my_target_platform

Bazel দেখতে পাবে যে //my_pkg:my_bar_binary একটি প্ল্যাটফর্মের সাথে তৈরি করা হচ্ছে যেটিতে @platforms//os:linux আছে এবং সেইজন্য //bar_tools:toolchain_type //bar_tools:barc_linux_toolchain । এটি নির্মাণ শেষ করবে //bar_tools:barc_linux কিন্তু নয় //bar_tools:barc_windows

টুলচেন রেজোলিউশন

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

উপলব্ধ এক্সিকিউশন প্ল্যাটফর্ম এবং টুলচেইনগুলি WORKSPACE ফাইল থেকে register_execution_platforms এবং register_toolchains এর মাধ্যমে সংগ্রহ করা হয়। অতিরিক্ত এক্সিকিউশন প্ল্যাটফর্ম এবং টুলচেইনগুলি কমান্ড লাইনে --extra_execution_platforms এবং --extra_toolchains এর মাধ্যমেও নির্দিষ্ট করা যেতে পারে। হোস্ট প্ল্যাটফর্ম স্বয়ংক্রিয়ভাবে একটি উপলব্ধ এক্সিকিউশন প্ল্যাটফর্ম হিসাবে অন্তর্ভুক্ত করা হয়। উপলব্ধ প্ল্যাটফর্ম এবং টুলচেইনগুলিকে তালিকার আগের আইটেমগুলিকে অগ্রাধিকার দিয়ে, নির্ধারণের জন্য আদেশকৃত তালিকা হিসাবে ট্র্যাক করা হয়।

রেজল্যুশনের ধাপগুলো নিম্নরূপ।

  1. একটি target_compatible_with বা exec_compatible_with clause একটি প্ল্যাটফর্মের সাথে মেলে যদি, তার তালিকায় থাকা প্রতিটি constraint_value এর জন্য, প্ল্যাটফর্মের সেই constraint_value ও থাকে (হয় স্পষ্টভাবে বা ডিফল্ট হিসাবে)।

    যদি প্ল্যাটফর্মের constraint_value s থেকে constraint_setting s গুলি ক্লজ দ্বারা উল্লেখ করা না হয়, তাহলে এগুলো মিলকে প্রভাবিত করে না।

  2. যদি তৈরি করা exec_compatible_with অ্যাট্রিবিউট নির্দিষ্ট করে (বা এর নিয়ম সংজ্ঞা exec_compatible_with argument ) নির্দিষ্ট করে, তাহলে উপলব্ধ এক্সিকিউশন প্ল্যাটফর্মের তালিকাটি এক্সিকিউশন সীমাবদ্ধতার সাথে মেলে না এমন যেকোনও অপসারণ করতে ফিল্টার করা হয়।

  3. প্রতিটি উপলব্ধ এক্সিকিউশন প্ল্যাটফর্মের জন্য, আপনি প্রতিটি টুলচেন প্রকারকে প্রথম উপলব্ধ টুলচেইনের সাথে সংযুক্ত করেন, যদি থাকে, যা এই এক্সিকিউশন প্ল্যাটফর্ম এবং লক্ষ্য প্ল্যাটফর্মের সাথে সামঞ্জস্যপূর্ণ।

  4. যেকোন এক্সিকিউশন প্ল্যাটফর্ম যা তার টুলচেন প্রকারের একটির জন্য একটি সামঞ্জস্যপূর্ণ বাধ্যতামূলক টুলচেন খুঁজে পেতে ব্যর্থ হয়েছে তা বাতিল করা হয়। অবশিষ্ট প্ল্যাটফর্মগুলির মধ্যে, প্রথমটি বর্তমান টার্গেটের এক্সিকিউশন প্ল্যাটফর্মে পরিণত হয় এবং এর সাথে যুক্ত টুলচেইনগুলি (যদি থাকে) লক্ষ্যের নির্ভরতা হয়ে ওঠে।

নির্বাচিত এক্সিকিউশন প্ল্যাটফর্মটি লক্ষ্য উত্পন্ন সমস্ত অ্যাকশন চালানোর জন্য ব্যবহৃত হয়।

যে ক্ষেত্রে একই টার্গেট একই বিল্ডের মধ্যে একাধিক কনফিগারেশনে (যেমন বিভিন্ন CPU-র জন্য) তৈরি করা যেতে পারে, রেজোলিউশন পদ্ধতি টার্গেটের প্রতিটি সংস্করণে স্বাধীনভাবে প্রয়োগ করা হয়।

যদি নিয়মটি এক্সিকিউশন গ্রুপ ব্যবহার করে, প্রতিটি এক্সিকিউশন গ্রুপ আলাদাভাবে টুলচেন রেজোলিউশন সঞ্চালন করে এবং প্রত্যেকটির নিজস্ব এক্সিকিউশন প্ল্যাটফর্ম এবং টুলচেইন রয়েছে।

ডিবাগিং টুলচেইন

আপনি যদি একটি বিদ্যমান নিয়মে টুলচেন সমর্থন যোগ করেন, তাহলে --toolchain_resolution_debug=regex পতাকা ব্যবহার করুন। টুলচেন রেজোলিউশনের সময়, পতাকা টুলচেন প্রকার বা টার্গেট নামের জন্য ভার্বোস আউটপুট প্রদান করে যা রেজেক্স ভেরিয়েবলের সাথে মেলে। আপনি সব তথ্য আউটপুট করতে .* ব্যবহার করতে পারেন। Bazel রেজোলিউশন প্রক্রিয়া চলাকালীন এটি চেক এবং এড়িয়ে যাওয়া টুলচেনের নাম আউটপুট করবে।

টুলচেন রেজোলিউশন থেকে কোন cquery নির্ভরতা আপনি দেখতে চান, cquery এর --transitions পতাকা ব্যবহার করুন:

# Find all direct dependencies of //cc:my_cc_lib. This includes explicitly
# declared dependencies, implicit dependencies, and toolchain dependencies.
$ bazel cquery 'deps(//cc:my_cc_lib, 1)'
//cc:my_cc_lib (96d6638)
@bazel_tools//tools/cpp:toolchain (96d6638)
@bazel_tools//tools/def_parser:def_parser (HOST)
//cc:my_cc_dep (96d6638)
@local_config_platform//:host (96d6638)
@bazel_tools//tools/cpp:toolchain_type (96d6638)
//:default_host_platform (96d6638)
@local_config_cc//:cc-compiler-k8 (HOST)
//cc:my_cc_lib.cc (null)
@bazel_tools//tools/cpp:grep-includes (HOST)

# Which of these are from toolchain resolution?
$ bazel cquery 'deps(//cc:my_cc_lib, 1)' --transitions=lite | grep "toolchain dependency"
  [toolchain dependency]#@local_config_cc//:cc-compiler-k8#HostTransition -> b6df211