في Android 8.1 والإصدارات الأحدث ، يحتوي نظام الإنشاء على دعم VNDK المدمج. عند تمكين دعم VNDK ، يتحقق نظام الإنشاء من التبعيات بين الوحدات ، ويبني متغيرًا خاصًا بالمورد لوحدات البائعين النمطية ، ويقوم تلقائيًا بتثبيت هذه الوحدات النمطية في أدلة معينة.
نموذج دعم بناء VNDK
في هذا المثال ، يعرّف تعريف الوحدة النمطية Android.bp
مكتبة باسم libexample
. تشير الخاصية vendor_available
إلى وحدات إطار العمل وقد تعتمد وحدات البائع على libexample
:
يعتمد كل من إطار العمل القابل للتنفيذ /system/bin/foo
والمورد القابل للتنفيذ /vendor/bin/bar
على libexample
ولهما libexample
في خصائص shared_libs
الخاصة بهما.
إذا تم استخدام libexample
بواسطة كل من وحدات إطار العمل ووحدات البائع ، فسيتم إنشاء متغيرين من libexample
. يتم استخدام المتغير الأساسي (المسمى باسم libexample
) بواسطة وحدات إطار العمل ويتم استخدام متغير البائع (المسمى باسم libexample.vendor
) بواسطة وحدات البائع. يتم تثبيت المتغيرين في دلائل مختلفة:
- يتم تثبيت المتغير الأساسي في
/system/lib[64]/libexample.so
. - تم تثبيت متغير البائع في VNDK APEX لأن
vndk.enabled
true
.
لمزيد من التفاصيل ، راجع تعريف الوحدة النمطية .
تكوين دعم البناء
لتمكين دعم نظام البناء الكامل لجهاز منتج ، أضف BOARD_VNDK_VERSION
إلى BoardConfig.mk
:
BOARD_VNDK_VERSION := current
هذا الإعداد له تأثير عام: عند BoardConfig.mk
، يتم فحص جميع الوحدات النمطية. نظرًا لعدم وجود آلية لإدراج وحدة مسيئة في القائمة السوداء أو إدراجها في القائمة البيضاء ، يجب عليك تنظيف جميع التبعيات غير الضرورية قبل إضافة BOARD_VNDK_VERSION
. يمكنك اختبار وتجميع وحدة عن طريق تعيين BOARD_VNDK_VERSION
في متغيرات البيئة الخاصة بك:
$ BOARD_VNDK_VERSION=current m module_name.vendor
عند تمكين BOARD_VNDK_VERSION
، تتم إزالة العديد من مسارات البحث العامة الافتراضية. وتشمل هذه:
-
frameworks/av/include
-
frameworks/native/include
-
frameworks/native/opengl/include
-
hardware/libhardware/include
-
hardware/libhardware_legacy/include
-
hardware/ril/include
-
libnativehelper/include
-
libnativehelper/include_deprecated
-
system/core/include
-
system/media/audio/include
إذا كانت الوحدة النمطية تعتمد على الرؤوس من هذه الأدلة ، فيجب عليك تحديد التبعيات (صراحة) مع header_libs
و / أو static_libs
و / أو shared_libs
.
VNDK أبيكس
في Android 10 والإصدارات الأقدم ، تم تثبيت الوحدات النمطية التي تحتوي على vndk.enabled
في /system/lib[64]/vndk[-sp]-${VER}
. في Android 11 والإصدارات الأحدث ، يتم تجميع مكتبات VNDK بتنسيق APEX واسم VNDK APEX هو com.android.vndk.v${VER}
. اعتمادًا على تكوين الجهاز ، يتم تسطيح VNDK APEX أو عدم تسويته ومتاح من المسار المتعارف عليه /apex/com.android.vndk.v${VER}
.
تعريف الوحدة
لإنشاء Android باستخدام BOARD_VNDK_VERSION
، يجب مراجعة تعريف الوحدة إما في Android.mk
أو Android.bp
. يصف هذا القسم أنواعًا مختلفة من تعريفات الوحدات النمطية ، والعديد من خصائص الوحدة النمطية المتعلقة بـ VNDK ، وفحوصات التبعية المطبقة في نظام الإنشاء.
وحدات البائعين
الوحدات النمطية للمورد هي برامج تنفيذية خاصة بالمورد أو مكتبات مشتركة يجب تثبيتها في قسم البائع. في ملفات Android.bp
، يجب أن تقوم وحدات البائع بتعيين خاصية البائع أو الملكية على true
. في ملفات Android.mk
، يجب على وحدات البائع تعيين LOCAL_VENDOR_MODULE
أو LOCAL_PROPRIETARY_MODULE
على " true
".
إذا تم تعريف BOARD_VNDK_VERSION
، فإن نظام الإنشاء لا يسمح بالتبعية بين وحدات المورد ووحدات إطار العمل ويصدر أخطاء إذا:
- وحدة بدون
vendor:true
يعتمد على وحدة معvendor:true
، أو - الوحدة النمطية مع
vendor:true
على وحدةllndk_library
لا يوجد بهاvendor:true
ولاvendor_available:true
.
ينطبق فحص التبعية على header_libs
و static_libs
و shared_libs
في Android.bp
وعلى LOCAL_HEADER_LIBRARIES
و LOCAL_STATIC_LIBRARIES
و LOCAL_SHARED_LIBRARIES
في Android.mk
.
LL-NDK
مكتبات LL-NDK المشتركة هي مكتبات مشتركة مع ABIs مستقرة. تشترك كل من وحدات الإطار والمورد في نفس وأحدث تطبيق. لكل مكتبة LL-NDK مشتركة ، يحتوي Android.bp
على تعريف وحدة llndk_library
:
llndk_library { name: "libvndksupport", symbol_file: "libvndksupport.map.txt", }
يحدد تعريف الوحدة النمطية هذا اسم الوحدة النمطية وملف الرمز الذي يصف الرموز المرئية لوحدات البائع. علي سبيل المثال:
LIBVNDKSUPPORT { global: android_load_sphal_library; # llndk android_unload_sphal_library; # llndk local: *; };
استنادًا إلى ملف الرمز ، يقوم نظام الإنشاء بإنشاء مكتبة مشتركة أساسية لوحدات البائعين النمطية ، والتي ترتبط بهذه المكتبات عند تمكين BOARD_VNDK_VERSION
. يتم تضمين الرمز في المكتبة المشتركة الجذرية فقط إذا كان:
- لم يتم تعريفه في القسم الذي ينتهي بـ
_PRIVATE
أو_PLATFORM
، - لا يحتوي على علامة
#platform-only
، و - لا تحتوي على
#introduce*
أو تطابق العلامة مع الهدف.
VNDK
في ملفات Android.bp
، تدعم تعريفات الوحدة النمطية cc_library
و cc_library_static
و cc_library_shared
و cc_library_headers
ثلاث خصائص مرتبطة بـ VNDK: vendor_available
و vndk.enabled
و vndk.support_system_process
.
إذا كان vendor_available
أو vndk.enabled
true
، فيمكن بناء متغيرين ( أساسي وبائع ). يجب التعامل مع المتغير الأساسي كوحدة نمطية لإطار العمل ويجب التعامل مع متغير البائع كوحدة نمطية للبائع. إذا كانت بعض وحدات إطار العمل تعتمد على هذه الوحدة ، فسيتم بناء المتغير الأساسي. إذا كانت بعض وحدات البائع تعتمد على هذه الوحدة ، فسيتم بناء متغير البائع. يفرض نظام البناء فحوصات التبعية التالية:
- دائمًا ما يكون المتغير الأساسي في إطار العمل فقط ولا يمكن الوصول إليه لوحدات البائعين النمطية.
- دائمًا ما يتعذر الوصول إلى متغير المورد إلى وحدات إطار العمل.
- يجب أن تكون جميع تبعيات متغير البائع ، المحددة في
header_libs
و / أوstatic_libs
و / أوshared_libs
، إماllndk_library
أو وحدة نمطية بهاvendor_available
أوvndk.enabled
. - إذا كان
vendor_available
true
، فسيكون متغير البائع متاحًا لجميع وحدات البائع النمطية. - إذا كان
vendor_available
false
، فلا يمكن الوصول إلى متغير البائع إلا لوحدات VNDK أو VNDK-SP الأخرى (على سبيل المثال ، لا يمكن للوحدات النمطية معvendor:true
أن تربطvendor_available:false
modules).
يتم تحديد مسار التثبيت الافتراضي لـ cc_library
أو cc_library_shared
بالقواعد التالية:
- يتم تثبيت المتغير الأساسي على
/system/lib[64]
. - قد يختلف مسار تثبيت متغير البائع:
- إذا كان
vndk.enabled
false
، فسيتم تثبيت متغير البائع في/vendor/lib[64]
. - إذا كان
vndk.enabled
true
، يتم تثبيت متغير البائع في VNDK APEX (com.android.vndk.v${VER}
).
- إذا كان
يلخص الجدول أدناه كيفية تعامل نظام الإنشاء مع متغيرات البائع:
vendor_available | vndk ممكن | vndk عملية_دعم_نفس_العملية | أوصاف متغير البائع |
---|---|---|---|
true | false | false | متغيرات البائع هي VND-ONLY . يتم تثبيت المكتبات المشتركة في /vendor/lib[64] . |
true | غير صالح (خطأ في البناء) | ||
true | false | متغيرات البائع هي VNDK . يتم تثبيت المكتبات المشتركة على VNDK APEX. | |
true | متغيرات البائع هي VNDK-SP . يتم تثبيت المكتبات المشتركة على VNDK APEX. | ||
| | | لا توجد متغيرات البائع. هذه الوحدة هي FWK-ONLY . |
true | غير صالح (خطأ في البناء) | ||
true | false | متغيرات البائع هي VNDK-Private . يتم تثبيت المكتبات المشتركة على VNDK APEX. يجب ألا يتم استخدامها مباشرة بواسطة وحدات البائعين. | |
true | متغيرات البائع هي VNDK-SP-Private . يتم تثبيت المكتبات المشتركة على VNDK APEX. يجب ألا يتم استخدامها مباشرة بواسطة وحدات البائعين. |
ملحقات VNDK
امتدادات VNDK هي مكتبات مشتركة لـ VNDK مع واجهات برمجة تطبيقات إضافية. يتم تثبيت الإضافات على /vendor/lib[64]/vndk[-sp]
(بدون لاحقة الإصدار) وتجاوز مكتبات VNDK المشتركة الأصلية في وقت التشغيل.
تحديد امتدادات VNDK
في Android 9 والإصدارات الأحدث ، يدعم Android.bp
أصلاً امتدادات VNDK. لإنشاء امتداد VNDK ، حدد وحدة نمطية أخرى مع vendor:true
و extends
:
cc_library { name: "libvndk", vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libvndk_ext", vendor: true, vndk: { enabled: true, extends: "libvndk", }, }
الوحدة النمطية مع vendor:true
، vndk.enabled:true
، extends
الخصائص تحدد امتداد VNDK:
- يجب أن تحدد خاصية التوسيع اسم مكتبة
extends
المشتركة الأساسي (أو اسم مكتبة VNDK-SP المشتركة). - تتم تسمية امتدادات VNDK (أو امتدادات VNDK-SP) بعد أسماء الوحدات الأساسية التي تمتد منها. على سبيل المثال ، الملف الثنائي الناتج من
libvndk_ext
هوlibvndk.so
بدلاً منlibvndk_ext.so
. - يتم تثبيت امتدادات VNDK في
/vendor/lib[64]/vndk
. - يتم تثبيت امتدادات VNDK-SP في
/vendor/lib[64]/vndk-sp
. - يجب أن تحتوي المكتبات المشتركة الأساسية على كل من
vndk.enabled:true
وvendor_available:true
.
يجب أن يمتد امتداد VNDK-SP من مكتبة مشتركة لـ VNDK-SP (يجب أن يكون vndk.support_system_process
متساويًا):
cc_library { name: "libvndk_sp", vendor_available: true, vndk: { enabled: true, support_system_process: true, }, } cc_library { name: "libvndk_sp_ext", vendor: true, vndk: { enabled: true, extends: "libvndk_sp", support_system_process: true, }, }
قد تعتمد امتدادات VNDK (أو امتدادات VNDK-SP) على المكتبات المشتركة للموردين الآخرين:
cc_library { name: "libvndk", vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libvndk_ext", vendor: true, vndk: { enabled: true, extends: "libvndk", }, shared_libs: [ "libvendor", ], } cc_library { name: "libvendor", vendor: true, }
باستخدام ملحقات VNDK
إذا كانت وحدة المورد تعتمد على واجهات برمجة التطبيقات الإضافية المحددة بواسطة امتدادات VNDK ، فيجب أن تحدد الوحدة اسم امتداد VNDK في خاصية shared_libs
الخاص بها:
// A vendor shared library example cc_library { name: "libvendor", vendor: true, shared_libs: [ "libvndk_ext", ], } // A vendor executable example cc_binary { name: "vendor-example", vendor: true, shared_libs: [ "libvndk_ext", ], }
إذا كانت وحدة البائع تعتمد على امتدادات VNDK ، يتم تثبيت امتدادات VNDK على /vendor/lib[64]/vndk[-sp]
تلقائيًا. إذا لم تعد الوحدة تعتمد على امتداد VNDK ، فقم بإضافة خطوة نظيفة إلى CleanSpec.mk
لإزالة المكتبة المشتركة. علي سبيل المثال:
$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)
الترجمة الشرطية
يصف هذا القسم كيفية التعامل مع الاختلافات الدقيقة (مثل إضافة أو إزالة ميزة من أحد المتغيرات) بين مكتبات VNDK المشتركة الثلاثة التالية:
- المتغير الأساسي (على سبيل المثال /system/lib [64] /
/system/lib[64]/libexample.so
) - متغير المورد (على سبيل المثال
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) - امتداد VNDK (على سبيل المثال
/vendor/lib[64]/vndk[-sp]/libexample.so
)
أعلام المترجم الشرطي
يعرّف نظام إنشاء Android __ANDROID_VNDK__
لمتغيرات البائع وامتدادات VNDK افتراضيًا. يمكنك حماية الكود باستخدام حراس المعالج الأولي C:
void all() { } #if !defined(__ANDROID_VNDK__) void framework_only() { } #endif #if defined(__ANDROID_VNDK__) void vndk_only() { } #endif
بالإضافة إلى __ANDROID_VNDK__
، قد يتم تحديد cppflags
أو cflags
مختلفة في Android.bp
. cflags
أو cppflags
المحددة في target.vendor
خاصة بمتغير البائع.
على سبيل المثال ، يعرّف Android.bp
التالي libexample
و libexample_ext
:
cc_library { name: "libexample", srcs: ["src/example.c"], vendor_available: true, vndk: { enabled: true, }, target: { vendor: { cflags: ["-DLIBEXAMPLE_ENABLE_VNDK=1"], }, }, } cc_library { name: "libexample_ext", srcs: ["src/example.c"], vendor: true, vndk: { enabled: true, extends: "libexample", }, cflags: [ "-DLIBEXAMPLE_ENABLE_VNDK=1", "-DLIBEXAMPLE_ENABLE_VNDK_EXT=1", ], }
وهذا هو رمز قائمة src/example.c
:
void all() { } #if !defined(LIBEXAMPLE_ENABLE_VNDK) void framework_only() { } #endif #if defined(LIBEXAMPLE_ENABLE_VNDK) void vndk() { } #endif #if defined(LIBEXAMPLE_ENABLE_VNDK_EXT) void vndk_ext() { } #endif
وفقًا لهذين الملفين ، يُنشئ نظام الإنشاء مكتبات مشتركة بالرموز المصدرة التالية:
مسار التثبيت | الرموز المصدرة |
---|---|
/system/lib[64]/libexample.so | all ، framework_only |
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so | all ، vndk |
/vendor/lib[64]/vndk/libexample.so | all ، vndk ، vndk_ext |
متطلبات الرموز المصدرة
يقارن مدقق VNDK ABI متغيرات ABI لموردي VNDK وامتدادات VNDK بمرجع تفريغ ABI ضمن prebuilts/abi-dumps/vndk
.
- يجب أن تكون الرموز التي تم تصديرها بواسطة متغيرات بائع VNDK (مثل
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) متطابقة مع (وليس مجموعات فرعية) الرموز المحددة في عمليات تفريغ ABI. - يجب أن تكون الرموز التي تم تصديرها بواسطة امتدادات VNDK (على سبيل المثال
/vendor/lib[64]/vndk/libexample.so
) مجموعات كبيرة من الرموز المحددة في عمليات تفريغ ABI.
إذا فشلت متغيرات بائع VNDK أو امتدادات VNDK في اتباع المتطلبات المذكورة أعلاه ، فإن مدقق VNDK ABI يصدر أخطاء في البناء ويوقف البناء.
استبعاد الملفات المصدر أو المكتبات المشتركة من متغيرات البائع
لاستبعاد ملفات المصدر من متغير البائع ، قم بإضافتها إلى خاصية exclude_srcs
. وبالمثل ، للتأكد من أن المكتبات المشتركة غير مرتبطة بمتغير المورد ، أضف تلك المكتبات إلى خاصية " exclude_shared_libs
". علي سبيل المثال:
cc_library { name: "libexample_cond_exclude", srcs: ["fwk.c", "both.c"], shared_libs: ["libfwk_only", "libboth"], vendor_available: true, target: { vendor: { exclude_srcs: ["fwk.c"], exclude_shared_libs: ["libfwk_only"], }, }, }
في هذا المثال ، المتغير الأساسي لـ libexample_cond_exclude
يتضمن الكود من fwk.c
و both.c
ويعتمد على المكتبات المشتركة libfwk_only
و libboth
. يشتمل متغير البائع لـ libexample_cond_exclude
فقط على الكود من both.c
لأن fwk.c
مستثنى من قبل خاصية exclude_srcs
. وبالمثل ، يعتمد ذلك على libboth
للمكتبة المشتركة فقط لأنه يتم استبعاد libfwk_only
بواسطة خاصية exclude_shared_libs
.
تصدير الرؤوس من امتدادات VNDK
قد يضيف امتداد VNDK فئات جديدة أو وظائف جديدة إلى مكتبة VNDK المشتركة. يُقترح الاحتفاظ بهذه الإعلانات في رؤوس مستقلة وتجنب تغيير الرؤوس الموجودة.
على سبيل المثال ، يتم إنشاء ملف رأس جديد include-ext/example/ext/feature_name.h
لملحق libexample_ext
:
- Android.bp
- include-ext / example / ext / feature_name.h
- تضمين / مثال / example.h
- src / example.c
- src / ext / feature_name.c
في ملف Android.bp
التالي ، تشمل عمليات تصدير libexample
فقط ، بينما include
صادرات libexample_ext
كلاً من ext و include
include-ext
. هذا يضمن أن feature_name.h
لن يتم تضمينها بشكل غير صحيح من قبل مستخدمي libexample
:
cc_library { name: "libexample", srcs: ["src/example.c"], export_include_dirs: ["include"], vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libexample_ext", srcs: [ "src/example.c", "src/ext/feature_name.c", ], export_include_dirs: [ "include", "include-ext", ], vendor: true, vndk: { enabled: true, extends: "libexample", }, }
إذا كان فصل الامتدادات إلى ملفات رأس مستقلة غير ممكن ، فإن البديل هو إضافة #ifdef
guards. ومع ذلك ، تأكد من قيام جميع مستخدمي امتداد VNDK بإضافة علامات التعريف. يمكنك تحديد cc_defaults
لإضافة أعلام تعريف إلى cflags
وربط المكتبات المشتركة بـ shared_libs
.
على سبيل المثال ، لإضافة وظيفة عضو جديدة Example2::get_b()
إلى ملحق libexample2_ext
، يجب عليك تعديل ملف الرأس الحالي وإضافة حارس #ifdef
:
#ifndef LIBEXAMPLE2_EXAMPLE_H_ #define LIBEXAMPLE2_EXAMPLE_H_ class Example2 { public: Example2(); void get_a(); #ifdef LIBEXAMPLE2_ENABLE_VNDK_EXT void get_b(); #endif private: void *impl_; }; #endif // LIBEXAMPLE2_EXAMPLE_H_
يتم تعريف cc_defaults
المسمى libexample2_ext_defaults
لمستخدمي libexample2_ext
:
cc_library { name: "libexample2", srcs: ["src/example2.cpp"], export_include_dirs: ["include"], vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libexample2_ext", srcs: ["src/example2.cpp"], export_include_dirs: ["include"], vendor: true, vndk: { enabled: true, extends: "libexample2", }, cflags: [ "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1", ], } cc_defaults { name: "libexample2_ext_defaults", shared_libs: [ "libexample2_ext", ], cflags: [ "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1", ], }
قد يقوم مستخدمو libexample2_ext
ببساطة بتضمين libexample2_ext_defaults
في خاصية defaults
الخاصة بهم:
cc_binary { name: "example2_user_executable", defaults: ["libexample2_ext_defaults"], vendor: true, }
حزم المنتج
في نظام إنشاء Android ، يحدد المتغير PRODUCT_PACKAGES
الملفات التنفيذية أو المكتبات المشتركة أو الحزم التي يجب تثبيتها في الجهاز. يتم تثبيت التبعيات متعدية للوحدات النمطية المحددة بشكل ضمني في الجهاز أيضًا.
إذا تم تمكين BOARD_VNDK_VERSION
، فستحصل الوحدات النمطية مع vendor_available
أو vndk.enabled
على معاملة خاصة. إذا كانت وحدة إطار العمل تعتمد على وحدة نمطية مع vendor_available
أو vndk.enabled
، فسيتم تضمين المتغير الأساسي في مجموعة التثبيت متعدية. إذا كانت وحدة المورد تعتمد على وحدة مع vendor_available
، يتم تضمين متغير البائع في مجموعة التثبيت متعدية. ومع ذلك ، يتم تثبيت متغيرات البائع للوحدات النمطية مع vndk.enabled
سواء تم استخدامها بواسطة وحدات البائع أم لا.
عندما تكون التبعيات غير مرئية لنظام الإنشاء (مثل المكتبات المشتركة التي يمكن فتحها باستخدام dlopen()
في وقت التشغيل) ، يجب عليك تحديد أسماء الوحدات في PRODUCT_PACKAGES
لتثبيت هذه الوحدات بشكل صريح.
إذا كانت الوحدة تحتوي على vendor_available
أو vndk.enabled
، فإن اسم الوحدة يعني المتغير الأساسي الخاص بها. لتحديد متغير المورد بشكل صريح في PRODUCT_PACKAGES
، .vendor
لاحقة البائع باسم الوحدة النمطية. علي سبيل المثال:
cc_library { name: "libexample", srcs: ["example.c"], vendor_available: true, }
في هذا المثال ، يرمز libexample
إلى /system/lib[64]/libexample.so
و libexample.vendor
يرمز إلى /vendor/lib[64]/libexample.so
. لتثبيت /vendor/lib[64]/libexample.so
، أضف libexample.vendor
إلى PRODUCT_PACKAGES
:
PRODUCT_PACKAGES += libexample.vendor