বাইন্ডজেন বাইন্ডিং মডিউল

বিল্ড সিস্টেমটি rust_bindgen মডিউল টাইপের মাধ্যমে বাইন্ডজেন বাইন্ডিং তৈরি করা সমর্থন করে। বাইন্ডজেন সি লাইব্রেরির জন্য রাস্ট এফএফআই বাইন্ডিং প্রদান করে (কিছু সীমিত সি++ সমর্থন সহ, যার জন্য cppstd প্রপার্টি সেট করতে হয়)।

rust_bindgen এর মৌলিক ব্যবহার

নিচে বাইন্ডজেন ব্যবহার করে এমন একটি মডিউল কীভাবে সংজ্ঞায়িত করতে হয় এবং সেই মডিউলটিকে একটি ক্রেট হিসেবে কীভাবে ব্যবহার করতে হয় তার একটি উদাহরণ দেওয়া হলো। যদি আপনার include!() ম্যাক্রোর মাধ্যমে বাইন্ডজেন বাইন্ডিং ব্যবহার করার প্রয়োজন হয়, যেমন এক্সটার্নাল কোডের জন্য, তাহলে সোর্স জেনারেটরস দেখুন।

রাস্ট থেকে কল করার জন্য উদাহরণ সি লাইব্রেরি

রাস্টে ব্যবহারের জন্য একটি স্ট্রাক্ট ও ফাংশন সংজ্ঞায়িত করে এমন একটি উদাহরণ সি লাইব্রেরি নিচে দেওয়া হলো।

external/rust/libbuzz/libbuzz.h

typedef struct foo {
    int x;
} foo;

void fizz(int i, foo* cs);

external/rust/libbuzz/libbuzz.c

#include <stdio.h>
#include "libbuzz.h"

void fizz(int i, foo* my_foo){
    printf("hello from c! i = %i, my_foo->x = %i\n", i, my_foo->x);
}

একটি rust_bindgen মডিউল সংজ্ঞায়িত করুন

external/rust/libbuzz/libbuzz_wrapper.h একটি র‍্যাপার হেডার সংজ্ঞায়িত করুন, যেটিতে সমস্ত প্রাসঙ্গিক হেডার অন্তর্ভুক্ত থাকবে:

// Include headers that are required for generating bindings in a wrapper header.
#include "libbuzz.h"

Android.bp ফাইলটিকে external/rust/libbuzz/Android.bp হিসেবে সংজ্ঞায়িত করুন:

cc_library {
    name: "libbuzz",
    srcs: ["libbuzz.c"],
}

rust_bindgen {
     name: "libbuzz_bindgen",

     // Crate name that's used to generate the rust_library variants.
     crate_name: "buzz_bindgen",

     // Path to the wrapper source file.
     wrapper_src: "libbuzz_wrapper.h",

     // 'source_stem' controls the output filename.
     // This is the filename that's used in an include! macro.
     //
     // In this case, we just use "bindings", which produces
     // "bindings.rs".
     source_stem: "bindings",

     // Bindgen-specific flags and options to customize the bindings.
     // See the bindgen manual for more information.
     bindgen_flags: ["--verbose"],

     // Clang flags to be used when generating the bindings.
     cflags: ["-DSOME_FLAG"],

     // Shared, static, and header libraries which export the necessary
     // include directories must be specified.
     //
     // These libraries will also be included in the crate if static,
     // or propagated to dependents if shared.
     // static_libs: ["libbuzz"]
     // header_libs: ["libbuzz"]
     shared_libs: ["libbuzz"],
}

bindgen ফ্ল্যাগ ব্যবহার সম্পর্কে আরও জানতে, bindgen ম্যানুয়ালের ‘Customizing the Generated Bindings’ অংশটি দেখুন।

যদি আপনি include!() ম্যাক্রো ব্যবহারের পূর্বশর্ত হিসেবে একটি rust_bindgen মডিউল সংজ্ঞায়িত করতে এই অংশটি ব্যবহার করে থাকেন, তাহলে সোর্স জেনারেটর পৃষ্ঠার পূর্বশর্ত (Prerequisite) অংশে ফিরে যান। অন্যথায়, পরবর্তী অংশগুলোতে অগ্রসর হন।

বাইন্ডিংগুলিকে ক্রেট হিসাবে ব্যবহার করুন

নিম্নলিখিত বিষয়বস্তু দিয়ে external/rust/hello_bindgen/Android.bp ফাইলটি তৈরি করুন:

rust_binary {
   name: "hello_bindgen",
   srcs: ["main.rs"],

   // Add the rust_bindgen module as if it were a rust_library dependency.
   rustlibs: ["libbuzz_bindgen"],
}

নিম্নলিখিত বিষয়বস্তু সহ external/rust/hello_bindgen/src/main.rs ফাইলটি তৈরি করুন:

//! Example crate for testing bindgen bindings

fn main() {
    let mut x = buzz_bindgen::foo { x: 2 };
    unsafe { buzz_bindgen::fizz(1, &mut x as *mut buzz_bindgen::foo) }
}

এরপর, বাইনারিটি বিল্ড করার জন্য m hello_bindgen কল করুন।

টেস্ট বাইন্ডজেন বাইন্ডিং

মেমরি লেআউটের অমিল রোধ করার জন্য বাইন্ডজেন বাইন্ডিংগুলিতে সাধারণত বেশ কিছু জেনারেটেড লেআউট টেস্ট থাকে। AOSP সুপারিশ করে যে, এই টেস্টগুলির জন্য আপনার একটি টেস্ট মডিউল সংজ্ঞায়িত করা উচিত এবং টেস্টগুলি আপনার প্রোজেক্টের সাধারণ টেস্ট স্যুটের অংশ হিসাবে চালানো উচিত।

আপনি external/rust/hello_bindgen/Android.bp তে একটি rust_test মডিউল সংজ্ঞায়িত করে এগুলোর জন্য একটি টেস্ট বাইনারি তৈরি করতে পারেন:

rust_test {
    name: "bindings_test",
    srcs: [
        ":libbuzz_bindgen",
    ],
    crate_name: "buzz_bindings_test",
    test_suites: ["general-tests"],
    auto_gen_config: true,

    // Be sure to disable lints as the generated source
    // is not guaranteed to be lint-free.
    clippy_lints: "none",
    lints: "none",
}

দৃশ্যমানতা এবং সংযোগ

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

ডিফল্টরূপে, rust_bindgen মডিউলগুলির একটি [":__subpackages__"] visibility প্রপার্টি থাকে, যা একই Android.bp ফাইলে থাকা অথবা ডিরেক্টরি হায়ারার্কিতে এর নিচের মডিউলগুলিকে এটিকে দেখতে দেয়। এটি দুটি উদ্দেশ্য পূরণ করে:

  • ট্রি-এর অন্যত্র সরাসরি C বাইন্ডিং ব্যবহারকে নিরুৎসাহিত করে।
  • স্ট্যাটিক ও ডাইনামিক লিঙ্কেজের মিশ্রণের মাধ্যমে ডায়মন্ড লিঙ্কিং-এর সমস্যা এড়ানো হয়।

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

উল্লেখযোগ্য rust_bindgen বৈশিষ্ট্য

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

স্টেম, নাম, ক্রেট_নাম

rust_bindgen লাইব্রেরির বিভিন্ন সংস্করণ তৈরি করে, তাই stem , name , এবং crate_name প্রোপার্টিগুলোর ক্ষেত্রে এগুলোর জন্য rust_library মডিউলগুলোর মতোই একই শর্তাবলী প্রযোজ্য। বিস্তারিত তথ্যের জন্য, Notable Rust library properties দেখুন।

wrapper_src

এটি একটি র‍্যাপার হেডার ফাইলের আপেক্ষিক পাথ, যেখানে এই বাইন্ডিংগুলির জন্য প্রয়োজনীয় হেডারগুলি অন্তর্ভুক্ত থাকে। ফাইল এক্সটেনশনটি নির্ধারণ করে যে হেডারটিকে কীভাবে ব্যাখ্যা করা হবে এবং ডিফল্টরূপে কোন -std ফ্ল্যাগটি ব্যবহার করা হবে। এক্সটেনশনটি .hh বা .hpp না হলে, এটিকে একটি C হেডার হিসেবে ধরে নেওয়া হয়। যদি আপনার C++ হেডারের অন্য কোনো এক্সটেনশন থাকতেই হয়, তবে ফাইলটিকে একটি C ফাইল হিসেবে ধরে নেওয়ার ডিফল্ট আচরণকে ওভাররাইড করতে cpp_std প্রপার্টিটি সেট করুন।

উৎস_কাণ্ড

এটি জেনারেট করা সোর্স ফাইলের ফাইলের নাম। এই ফিল্ডটি অবশ্যই সংজ্ঞায়িত করতে হবে, এমনকি যদি আপনি বাইন্ডিংগুলোকে একটি ক্রেট হিসেবে ব্যবহার করেন, কারণ stem প্রপার্টিটি শুধুমাত্র জেনারেট করা লাইব্রেরি ভ্যারিয়েন্টগুলোর আউটপুট ফাইলের নাম নিয়ন্ত্রণ করে। যদি কোনো মডিউল rustlibs -এর মাধ্যমে ক্রেট হিসেবে নয়, বরং সোর্স হিসেবে একাধিক সোর্স জেনারেটরের (যেমন bindgen এবং protobuf ) উপর নির্ভর করে, তবে নিশ্চিত করুন যে সেই মডিউলের ডিপেন্ডেন্সি হিসেবে থাকা সমস্ত সোর্স জেনারেটরের source_stem ভ্যালুগুলো অনন্য। ডিপেন্ডেন্ট মডিউলগুলো srcs এ সংজ্ঞায়িত সমস্ত SourceProvider ডিপেন্ডেন্সি থেকে সোর্সগুলোকে একটি সাধারণ OUT_DIR ডিরেক্টরিতে কপি করে, তাই source_stem -এ কোনো সংঘর্ষ হলে OUT_DIR ডিরেক্টরিতে জেনারেট করা সোর্স ফাইলগুলো ওভাররাইট হয়ে যাবে।

সি_এসটিডি

এটি একটি স্ট্রিং যা নির্দেশ করে কোন সি-স্ট্যান্ডার্ড সংস্করণটি ব্যবহার করতে হবে। বৈধ মানগুলি এখানে তালিকাভুক্ত করা হলো:

  • একটি নির্দিষ্ট সংস্করণ, যেমন gnu11
  • experimental , যা build/soong/cc/config/global.go তে বিল্ড সিস্টেম দ্বারা সংজ্ঞায়িত একটি মান, উপলব্ধ হলে C++1z-এর মতো ড্রাফট সংস্করণ ব্যবহার করতে পারে।
  • অনির্ধারিত বা "" , যা নির্দেশ করে যে বিল্ড সিস্টেমের ডিফল্ট ব্যবহার করা উচিত।

এটি সেট করা থাকলে, ফাইল এক্সটেনশনটি উপেক্ষা করা হয় এবং হেডারটিকে একটি C হেডার হিসেবে ধরে নেওয়া হয়। এটি cpp_std সাথে একই সময়ে সেট করা যায় না।

cpp_std

cpp_std হলো একটি স্ট্রিং যা নির্দেশ করে কোন সি স্ট্যান্ডার্ড সংস্করণ ব্যবহার করতে হবে। বৈধ মানগুলো এখানে তালিকাভুক্ত করা হলো:

  • একটি নির্দিষ্ট সংস্করণ, যেমন gnu++11
  • experimental , যা build/soong/cc/config/global.go তে বিল্ড সিস্টেম দ্বারা সংজ্ঞায়িত একটি মান, উপলব্ধ হলে C++1z-এর মতো ড্রাফট সংস্করণ ব্যবহার করতে পারে।
  • অনির্ধারিত বা "" , যা নির্দেশ করে যে বিল্ড সিস্টেমের ডিফল্ট ব্যবহার করা উচিত।

এটি সেট করা থাকলে, ফাইল এক্সটেনশনটি উপেক্ষা করা হয় এবং হেডারটিকে একটি C++ হেডার হিসেবে ধরে নেওয়া হয়। এটি c_std সাথে একই সময়ে সেট করা যায় না।

সিফ্ল্যাগস

cflags হেডারগুলো সঠিকভাবে ব্যাখ্যা করার জন্য প্রয়োজনীয় Clang ফ্ল্যাগগুলোর একটি স্ট্রিং তালিকা প্রদান করে।

কাস্টম_বাইন্ডজেন

উন্নত ব্যবহারের ক্ষেত্রে, বাইন্ডজেনকে একটি লাইব্রেরি হিসেবে ব্যবহার করা যেতে পারে, যা এমন একটি এপিআই (API) প্রদান করে যাকে একটি কাস্টম রাস্ট বাইনারির অংশ হিসেবে নিয়ন্ত্রণ করা যায়। custom_bindgen ফিল্ডটি ` rust_binary_host মডিউলের নাম গ্রহণ করে, যা সাধারণ bindgen বাইনারির পরিবর্তে বাইন্ডজেন এপিআই ব্যবহার করে।

এই কাস্টম বাইনারিটিকে অবশ্যই bindgen এর মতোই আর্গুমেন্ট গ্রহণ করতে হবে, যেমন—

$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]

এর বেশিরভাগই bindgen লাইব্রেরি নিজেই পরিচালনা করে। এর ব্যবহারের একটি উদাহরণ দেখতে, external/rust/crates/libsqlite3-sys/android/build.rs ফাইলটি দেখুন।

এছাড়াও, লাইব্রেরির কম্পাইলেশন নিয়ন্ত্রণের জন্য লাইব্রেরি প্রপার্টিজের সম্পূর্ণ সেট উপলব্ধ রয়েছে, যদিও এগুলি সংজ্ঞায়িত বা পরিবর্তন করার প্রয়োজন খুব কমই হয়।

handle_static_inline এবং static_inline_library

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

এগুলো ব্যবহার করতে, handle_static_inline: true সেট করুন এবং static_inline_library কে সংশ্লিষ্ট cc_library_static এ সেট করুন, যা rust_bindgen মডিউলকে সোর্স ইনপুট হিসেবে সংজ্ঞায়িত করে।

ব্যবহারের উদাহরণ:

    rust_bindgen {
        name: "libbindgen",
        wrapper_src: "src/any.h",
        crate_name: "bindgen",
        stem: "libbindgen",
        source_stem: "bindings",

        // Produce bindings for static inline functions
        handle_static_inline: true,
        static_inline_library: "libbindgen_staticfns"
    }

    cc_library_static {
        name: "libbindgen_staticfns",

        // This is the rust_bindgen module defined above
        srcs: [":libbindgen"],

        // The include path to the header file in the generated C file is
        // relative to build top.
        include_dirs: ["."],
    }