बिल्ड सिस्टम, rust_bindgen
के ज़रिए बाइंडिंग बाइंडिंग जनरेट करने की सुविधा देता है
मॉड्यूल टाइप. Bindgen, C लाइब्रेरी के लिए Rust FFI बाइंडिंग उपलब्ध कराता है. इसमें C++ के साथ काम करने की कुछ सीमित सुविधाएं भी होती हैं. इसके लिए, cppstd
प्रॉपर्टी को सेट करना ज़रूरी होता है.
rust_bindgen का बुनियादी इस्तेमाल
यहां bindgen का इस्तेमाल करने वाले मॉड्यूल को तय करने और उस मॉड्यूल को क्रेट के तौर पर इस्तेमाल करने का उदाहरण दिया गया है. अगर आपको include!()
मैक्रो के ज़रिए bindgen बाइंडिंग का इस्तेमाल करना है, जैसे कि बाहरी कोड के लिए, तो सोर्स जनरेटर पेज देखें.
Rust से कॉल करने के लिए C लाइब्रेरी का उदाहरण
Rust में इस्तेमाल करने के लिए, स्ट्रक्चर और फ़ंक्शन की परिभाषा देने वाली C लाइब्रेरी का उदाहरण यहां दिया गया है.
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 मैन्युअल सेक्शन देखें जनरेट किए गए बाइंडिंग को पसंद के मुताबिक बनाना पर जाएं.
अगर आपने इस सेक्शन का इस्तेमाल करके, किसी rust_bindgen
मॉड्यूल को
include!()
मैक्रो का इस्तेमाल करके, ज़रूरी शर्त पर वापस जाएं
के लिए, सोर्स जनरेटर पेज पर भी उपलब्ध हो. अगर ऐसा नहीं है, तो अगले सेक्शन पर जाएं.
बाइंडिंग का इस्तेमाल क्रेट के तौर पर करना
इस कॉन्टेंट की मदद से 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
को कॉल करें.
Bingen बाइंडिंग की जांच करें
आम तौर पर, Bindgen बाइंडिंग में जनरेट किए गए कई लेआउट टेस्ट होते हैं, ताकि मेमोरी लेआउट के मेल न खाने से रोका जा सके. एओएसपी का सुझाव है कि आपके पास साथ ही, यह भी बताता है कि ये टेस्ट आपके प्रोजेक्ट के सामान्य टेस्ट सुइट के तौर पर कैसे चलते हैं.
rust_test
मॉड्यूल तय करके, इनके लिए टेस्ट बाइनरी आसानी से बनाई जा सकती है
external/rust/hello_bindgen/Android.bp
में:
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 बाइंडिंग का इस्तेमाल करने से बचने में मदद मिलती है.
- यह स्टैटिक और डाइनैमिक लिंकेज, दोनों के साथ डायमंड लिंक करने की समस्याओं से बचाता है.
आम तौर पर, आपको जनरेट किए गए उस मॉड्यूल के लिए एक सुरक्षित रैपर लाइब्रेरी देनी चाहिए जिसे आपने बिडिंग के साथ उसी डायरेक्ट्री ट्री में जोड़ा है जिसका इस्तेमाल अन्य डेवलपर करेंगे. अगर यह आपके इस्तेमाल के उदाहरण के लिए काम नहीं करता है, तो विज़िबिलिटी के लिए दूसरे पैकेज. दिखाई देने के अतिरिक्त दायरे जोड़ते समय, कृपया इस बात का ध्यान रखें कि में दो दायरे हो सकते हैं, जो आने वाले समय में इसी प्रोसेस में लिंक किए जा सकते हैं, क्योंकि लिंक नहीं किया जा सका.
rust_bindgen की मशहूर प्रॉपर्टी
नीचे बताई गई प्रॉपर्टी, ज़रूरी सामान्य प्रॉपर्टी के अतिरिक्त हैं
जो सभी मॉड्यूल पर लागू होते हैं. ये खास तौर पर Rust
बाइंडिंग मॉड्यूल या rust_bindgen
मॉड्यूल टाइप के हिसाब से खास व्यवहार दिखाता है.
स्टेम, नाम, crate_name
rust_bindgen
, लाइब्रेरी के वैरिएंट जनरेट करता है. इसलिए, वे एक जैसी ज़रूरी शर्तें पूरी करते हैं
stem
, name
, और crate_name
प्रॉपर्टी के लिए rust_library
मॉड्यूल. रेफ़रंस के लिए,
Rust लाइब्रेरी की खास प्रॉपर्टी देखें.
रैपर_src
यह रैपर हेडर फ़ाइल का रिलेटिव पाथ है, जिसमें ज़रूरी हेडर शामिल हैं
इन बाइंडिंग के लिए. फ़ाइल एक्सटेंशन, हेडर को समझने का तरीका तय करता है
और तय करता है कि डिफ़ॉल्ट रूप से किस -std
फ़्लैग का इस्तेमाल करना है. इसे C माना जाता है
हेडर जब तक एक्सटेंशन .hh
या .hpp
न हो. अगर आपके C++ हेडर का कोई दूसरा एक्सटेंशन होना चाहिए, तो cpp_std
प्रॉपर्टी सेट करें. इससे, फ़ाइल को C फ़ाइल मानने वाले डिफ़ॉल्ट व्यवहार को बदला जा सकता है.
source_stem
यह जनरेट की गई सोर्स फ़ाइल का फ़ाइल नाम है. इस फ़ील्ड को तय करना ज़रूरी है, भले ही आपने बाइंडिंग का इस्तेमाल क्रेट के तौर पर किया हो. इसकी वजह यह है कि stem
प्रॉपर्टी, जनरेट की गई लाइब्रेरी के वैरिएंट के लिए सिर्फ़ आउटपुट फ़ाइल का नाम कंट्रोल करती है.
अगर कोई मॉड्यूल एक से ज़्यादा सोर्स जनरेटर पर निर्भर करता है (जैसे कि bindgen
और protobuf
)
rustlibs
के ज़रिए अलग-अलग सोर्स के बजाय, आपको यह पक्का करना होगा कि सभी सोर्स जनरेटर
जो उस मॉड्यूल की डिपेंडेंसी हैं उनके 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
एक स्ट्रिंग है, जो यह बताती है कि C के स्टैंडर्ड वर्शन का इस्तेमाल करना है. मान्य मान:
- कोई खास वर्शन, जैसे कि
"gnu++11"
"experimental"
,build/soong/cc/config/global.go
में मौजूद बिल्ड सिस्टम से तय की गई वैल्यू है. यह C++1z जैसे ड्राफ़्ट वर्शन का इस्तेमाल तब कर सकता है, जब वे उपलब्ध हों.- इस नीति को अनसेट या
""
किया जाता है. इसका मतलब है कि बिल्ड सिस्टम की डिफ़ॉल्ट सुविधा का इस्तेमाल किया जाना चाहिए.
अगर यह सेट है, तो फ़ाइल एक्सटेंशन को अनदेखा कर दिया जाता है और हेडर को C++ हेडर माना जाता है. इसे c_std
के साथ सेट नहीं किया जा सकता.
क्फ़्लैग
cflags
, Clang फ़्लैग की ऐसी स्ट्रिंग सूची देता है जो
हेडर.
custom_bindgen
बेहतर इस्तेमाल के लिए, bindgen का इस्तेमाल लाइब्रेरी के तौर पर किया जा सकता है. इससे ऐसा एपीआई मिलता है जो
उनमें ज़रूरत के हिसाब से Rust बाइनरी के हिस्से के तौर पर बदलाव किया जा सकता है. custom_bindgen
फ़ील्ड, rust_binary_host
मॉड्यूल का मॉड्यूल नेम लेता है. यह सामान्य bindgen
बाइनरी के बजाय, bindgen API का इस्तेमाल करता है.
इस कस्टम बाइनरी को 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: ["."],
}