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

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

توفّر جميع مولّدات التعليمات البرمجية المصدر وظائف مماثلة لنظام الإنشاء. حالات الاستخدام الثلاث التي يتيحها نظام الإنشاء لإنشاء المصدر هي إنشاء روابط 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 على هذا الدليل عند تجميع الوحدة، وبالتالي يمكن العثور على المصدر الذي تم إنشاؤه. ومع ذلك، للأسباب الموضّحة سابقًا، من أفضل الممارسات استخدام هذه الآلية في رمز النظام الأساسي فقط عند الضرورة القصوى.


  1. لا يسبّب ذلك أي مشاكل في لغتَي C/C++‎ واللغات المشابهة، لأنّه يتم توفير مسار المصدر الذي تم إنشاؤه مباشرةً إلى المترجم. 

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