تقدّم هذه الصفحة نظرة عامة على كيفية توفير الدعم للمصدر الذي تم إنشاؤه وكيفية استخدامه في نظام التصميم.
توفّر جميع مولّدات التعليمات البرمجية المصدر وظائف مماثلة لنظام الإنشاء. حالات الاستخدام الثلاث المتاحة لإنشاء المصدر في نظام الإصدار هي إنشاء روابط C باستخدام bindgen، وواجهات AIDL، وواجهات protobuf.
حِزم من مصدر تم إنشاؤه
يمكن استخدام كل وحدة Rust تنشئ رمزًا مصدرًا كحزمة، تمامًا كما لو تم تعريفها على أنّها rust_library. (وهذا يعني أنّه يمكن تعريفها كاعتمادية في السمات rustlibs وrlibs وdylibs). أفضل نمط استخدام لرمز المنصّة هو استخدام المصدر الذي تم إنشاؤه كحزمة. على الرغم من أنّ الماكرو
include! متاح للمصدر الذي تم إنشاؤه، فإنّ الغرض الأساسي منه هو
إتاحة الرموز البرمجية التابعة لجهات خارجية والموجودة في external/.
هناك حالات قد يظل فيها رمز النظام الأساسي يستخدم المصدر الذي تم إنشاؤه من خلال الماكرو include!()، مثل عندما تستخدم وحدة genrule لإنشاء مصدر بطريقة فريدة.
استخدام include!() لتضمين رمز المصدر الذي تم إنشاؤه
يتم تناول استخدام مستند مصدر من إنشاء الذكاء الاصطناعي كحزمة في الأمثلة الواردة في صفحة كل وحدة نمطية محددة (ذات صلة). يوضّح هذا القسم كيفية الإشارة إلى المصدر الذي تم إنشاؤه
من خلال وحدة الماكرو include!(). يُرجى العِلم أنّ هذه العملية مماثلة لجميع مولّدات المصدر.
المتطلبات الأساسية
يستند هذا المثال إلى افتراض أنّك حدّدت وحدة rust_bindgen (libbuzz_bindgen) ويمكنك الانتقال إلى خطوات تضمين المصدر الذي تم إنشاؤه لاستخدام الماكرو include!(). إذا لم تكن قد فعلت ذلك، يُرجى الانتقال إلى تحديد وحدة rust bindgen، وإنشاء libbuzz_bindgen، ثم الرجوع إلى هنا.
يُرجى العلم أنّ أجزاء ملف الإنشاء هذه تنطبق على جميع مولّدات التعليمات البرمجية المصدر.
خطوات تضمين المصدر الذي تم إنشاؤه
أنشئ الملف external/rust/hello_bindgen/Android.bp مع المحتوى التالي:
rust_binary {
name: "hello_bzip_bindgen_include",
srcs: [
// The primary rust source file must come first in this list.
"src/lib.rs",
// The module providing the bindgen bindings is
// included in srcs prepended by ":".
":libbuzz_bindgen",
],
// Dependencies need to be redeclared when generated source is used via srcs.
shared_libs: [
"libbuzz",
],
}
أنشئ الملف external/rust/hello_bindgen/src/bindings.rs مع المحتوى التالي:
#![allow(clippy::all)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused)]
#![allow(missing_docs)]
// Note that "bzip_bindings.rs" here must match the source_stem property from
// the rust_bindgen module.
include!(concat!(env!("OUT_DIR"), "/bzip_bindings.rs"));
أنشئ الملف external/rust/hello_bindgen/src/lib.rs مع المحتوى التالي:
mod bindings;
fn main() {
let mut x = bindings::foo { x: 2 };
unsafe { bindings::fizz(1, &mut x as *mut bindings::foo) }
}
لماذا يتم إنشاء حزم للمصدر الذي تم إنشاؤه؟
على عكس برامج تجميع C/C++، لا تقبل rustc سوى ملف مصدر واحد يمثّل نقطة دخول إلى ملف ثنائي أو مكتبة. ويفترض أنّ شجرة المصدر منظَّمة بطريقة تتيح العثور تلقائيًا على جميع ملفات المصدر المطلوبة. وهذا يعني أنّه يجب وضع رمز المصدر الذي تم إنشاؤه في شجرة المصدر أو تقديمه من خلال توجيه تضمين في المصدر:
include!("/path/to/hello.rs");
يعتمد منتدى Rust على نصوص build.rs، وعلى افتراضات بشأن بيئة الإصدار Cargo، من أجل التعامل مع هذا الاختلاف.
عندما يتم إنشاء التطبيق، يضبط الأمر cargo OUT_DIR متغير بيئة
يُتوقّع أن تضع فيه النصوص البرمجية build.rs رمز المصدر الذي تم إنشاؤه. استخدِم الأمر التالي لتضمين رمز المصدر:
include!(concat!(env!("OUT_DIR"), "/hello.rs"));
يشكّل ذلك تحديًا لـ Soong لأنّ نواتج كل وحدة يتم وضعها في out/ دليل1 خاص بها. لا يوجد OUT_DIR واحد
تُخرج فيه التبعيات رمز المصدر الذي تم إنشاؤه.
بالنسبة إلى رمز النظام الأساسي، يفضّل مشروع AOSP تجميع الرمز المصدر الذي تم إنشاؤه في حزمة يمكن استيرادها، وذلك لعدة أسباب:
- منع تعارض أسماء ملفات المصدر التي تم إنشاؤها
- تقليل رمز النص النموذجي الذي يتم تسجيله في جميع أنحاء الشجرة والذي يتطلب صيانة. يمكن الاحتفاظ بأي رمز نموذجي مطلوب لإتاحة تجميع الرمز المصدر الذي تم إنشاؤه في حزمة بشكل مركزي.
- تجنَّب التفاعلات الضمنية2 بين الرمز البرمجي الذي تم إنشاؤه والحزمة المحيطة.
- تقليل الضغط على الذاكرة والقرص من خلال الربط الديناميكي بالمصادر التي يتم إنشاؤها بشكل شائع الاستخدام
نتيجةً لذلك، تنتج جميع أنواع وحدات إنشاء رموز مصدر Rust في Android رموزًا برمجية يمكن تجميعها واستخدامها كحزمة.
لا يزال Soong يتيح استخدام حِزم خارجية بدون تعديل إذا تم نسخ جميع التبعيات الخاصة بالمصدر التي تم إنشاؤها لوحدة معيّنة إلى دليل واحد لكل وحدة، على غرار Cargo. في هذه الحالات، يضبط Soong المتغيّر البيئي OUT_DIR على هذا الدليل عند تجميع الوحدة، وبالتالي يمكن العثور على الرمز المصدر الذي تم إنشاؤه.
ومع ذلك، للأسباب الموضّحة سابقًا، من أفضل الممارسات عدم استخدام هذه الآلية في رمز النظام الأساسي إلا عند الضرورة القصوى.
-
لا يسبّب ذلك أي مشاكل في لغتَي C/C++ واللغات المشابهة، لأنّه يتم تقديم مسار المصدر الذي تم إنشاؤه مباشرةً إلى المترجم. ↩
-
بما أنّ
include!تعمل من خلال التضمين النصي، قد تشير إلى قيم من مساحة الاسم المحيطة أو تعدّل مساحة الاسم أو تستخدم بنى مثل#![foo]. وقد يكون من الصعب الحفاظ على هذه التفاعلات الضمنية. ننصحك دائمًا باستخدام وحدات الماكرو عند الحاجة إلى التفاعل مع بقية الحزمة. ↩