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

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

توفّر جميع أدوات إنشاء المصادر وظيفة نظام إنشاء مماثلة. إنّ حالات الاستخدام الثلاث لإنشاء المصادر المتوافقة مع نظام الإنشاء هي إنشاء ربطات C باستخدام bindgen وواجهات AIDL وواجهات protobuf.

الصناديق من مصدر تم إنشاؤه

يمكن استخدام كل وحدة Rust تُنشئ رمز المصدر في شكل صندوق، تمامًا كما لو تم تحديدها على أنّها rust_library. (يعني ذلك أنّه يمكن تعريفه على أنّه ملف ملحق في السمات rustlibs وrlibs وdylibs). إنّ أفضل نمط استخدام لرمز النظام الأساسي هو استخدام المصدر الذي تم إنشاؤه كحزمة. على الرغم من أنّ الماكرو include! متوافق مع المصدر الذي تم إنشاؤه، إلا أنّ الغرض الأساسي منه هو إتاحة استخدام الرمز البرمجي التابع لجهة خارجية والمضمّن في external/.

في بعض الحالات، قد يستمر رمز النظام الأساسي في استخدام المصدر الذي تم إنشاؤه من خلال الماكرو include!()، مثل استخدام وحدة genrule لإنشاء مصدر بطريقة فريدة.

استخدام التضمين!() لتضمين المصدر الذي تم إنشاؤه

يتناول القسم "أمثلة" في كل صفحة وحدة (معنيّة) استخدام المصدر الذي تم إنشاؤه كحزمة. يوضّح هذا القسم كيفية الإشارة إلى المصدر الذي تم إنشاؤه من خلال وحدة الماكرو 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"));

ويشكّل ذلك تحديًا لتطبيق Sayg، إذ يتم وضع مخرجات كل وحدة في دليل out/1 الخاص بها. لا يتوفّر OUT_DIR واحد حيث تُخرج التبعيات المصدر الذي تم إنشاؤه.

بالنسبة إلى رمز النظام الأساسي، يفضّل AOSP تجميع المصدر الذي تم إنشاؤه في حزمة يمكن استيرادها، وذلك لعدة أسباب:

  • منع تطابق أسماء ملفات المصدر التي تم إنشاؤها
  • قلِّل من الرموز البرمجية النموذجية التي تم تسجيلها في جميع أنحاء الشجرة وتتطلّب الصيانة. يمكن الاحتفاظ بشكل مركزي بأي نموذج معدّ مسبقًا لإنشاء مصدر وتحويله إلى حزمة.
  • تجنَّب التفاعلات الضمنية2 بين الرمز الذي تم إنشاؤه والمجموعة المحيطة به.
  • تقليل الضغط على الذاكرة والقرص من خلال الربط الديناميكي بالمصادر المنشأة الشائعة الاستخدام

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


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

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