أدوات إنشاء المصادر

تقدّم هذه الصفحة نظرة عامة على كيفية توفّر المصدر الذي تم إنشاؤه و كيفية استخدامه في نظام الإنشاء.

توفّر جميع أدوات إنشاء المصادر وظائف مماثلة لنظام الإنشاء. إنّ حالات الاستخدام الثلاث لإنشاء المصادر المتوافقة مع نظام الإنشاء هي إنشاء ربطات 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 في المصدر:

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 المحيطة به.
  • تقليل الضغط على الذاكرة والقرص من خلال الربط الديناميكي بالمصادر المنشأة الشائعة الاستخدام

نتيجةً لذلك، تُنشئ جميع أنواع وحدات إنشاء رمز المصدر في Rust لنظام التشغيل Android رمزًا يمكن تجميعه واستخدامه كحزمة. لا يزال Soong متوافقًا مع حِزم الجهات الخارجية بدون تعديل إذا تم نسخ كل الموارد المُنشأة للمستودعات في وحدة إلى ملف واحد لكل ملف دليل، على غرار Cargo. في هذه الحالات، يضبط Soong متغيّر البيئة OUT_DIR على هذا الدليل عند تجميع الوحدة، حتى يمكن العثور على المصدر الذي تم إنشاؤه. ومع ذلك، ولأسباب سبق توضيحها، من أفضل الممارسات عدم استخدام هذه الآلية في رمز المنصة إلا عند الضرورة القصوى.


  1. ولا يتسبب ذلك في أي مشاكل في لغة C/C++ واللغات المشابهة، لأنّه يتم تقديم ملف تعريف الارتباط إلى المُجمِّع مباشرةً. 

  2. بما أنّ الدالة include! تعمل من خلال التضمين النصي، قد تشير إلى قيم من مساحة الاسم المُحيطة أو تعدّل مساحة الاسم أو تستخدِم بنى مثل #![foo]. وقد يكون من الصعب الحفاظ على هذه التفاعلات الضمنية. ننصحك دائمًا باستخدام وحدات الماكرو عندما يكون التفاعل مع بقية الحزمة مطلوبًا حقًا.