বিল্ড সিস্টেমটি 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 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 মডিউলগুলির একটি visibility প্রপার্টি [":__subpackages__"] থাকে, যা শুধুমাত্র একই Android.bp ফাইলে থাকা অথবা ডিরেক্টরি হায়ারার্কিতে এর নিচের মডিউলগুলিকেই এটিকে দেখতে দেয়। এর দুটি উদ্দেশ্য রয়েছে:
- এটি ট্রি-এর অন্য কোথাও সরাসরি C বাইন্ডিং ব্যবহারকে নিরুৎসাহিত করে।
- এটি স্ট্যাটিক এবং ডাইনামিক লিঙ্কেজের মিশ্রণের মাধ্যমে ডায়মন্ড লিঙ্কিং-এর সমস্যা এড়িয়ে চলে।
সাধারণত, অন্যান্য ডেভেলপারদের ব্যবহারের জন্য আপনার তৈরি করা মডিউলটির চারপাশে একটি নিরাপদ র্যাপার লাইব্রেরি প্রদান করা উচিত, যা বাইন্ডিংগুলোর সাথে একই ডিরেক্টরি ট্রিতে যুক্ত থাকবে। যদি এটি আপনার ব্যবহারের ক্ষেত্রে কাজ না করে, তবে আপনি 'visible'- এ অতিরিক্ত প্যাকেজ যোগ করতে পারেন। অতিরিক্ত 'visible' স্কোপ যোগ করার সময়, অনুগ্রহ করে খেয়াল রাখবেন যেন এমন দুটি স্কোপ যোগ না করেন যা ভবিষ্যতে একই প্রসেসে লিঙ্ক করা হতে পারে, কারণ এতে লিঙ্ক ব্যর্থ হতে পারে।
উল্লেখযোগ্য 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 fucntions
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: ["."],
}