في 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
.
في إن دي كيه أبيكس
في نظام التشغيل 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 المشتركة هي مكتبات مشتركة ذات واجهات ABI مستقرة. تشترك كل من وحدات الإطار والبائعين في نفس التنفيذ وأحدثه. لكل مكتبة LL-NDK مشتركة، تحتوي cc_library
على خاصية llndk
مع ملف رمز:
cc_library { name: "libvndksupport", llndk: { 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*
أو أن العلامة تتطابق مع الهدف.
فندك
في ملفات 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
).
يتم تحديد مسار التثبيت الافتراضي لـ cc_library
أو cc_library_shared
وفقًا للقواعد التالية:
- تم تثبيت المتغير الأساسي على
/system/lib[64]
. - قد يختلف مسار التثبيت المتغير للمورد:
- إذا كانت
vndk.enabled
false
، فسيتم تثبيت متغير البائع في/vendor/lib[64]
. - إذا كانت
vndk.enabled
true
، فسيتم تثبيت متغير البائع في VNDK APEX(com.android.vndk.v${VER}
).
- إذا كانت
يلخص الجدول أدناه كيفية تعامل نظام البناء مع متغيرات البائع:
بائع_متوفر | vndk ممكن | vndk support_same_process | أوصاف متغيرات البائع |
---|---|---|---|
true | false | false | متغيرات البائع هي VND-ONLY . يتم تثبيت المكتبات المشتركة في /vendor/lib[64] . |
true | غير صالح (خطأ في الإنشاء) | ||
true | false | متغيرات البائع هي VNDK . تم تثبيت المكتبات المشتركة على VNDK APEX. | |
true | متغيرات البائع هي VNDK-SP . تم تثبيت المكتبات المشتركة على VNDK APEX. | ||
| | | لا توجد متغيرات البائع. هذه الوحدة هي FWK فقط . |
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 المشتركة الأساسي (أو اسم مكتبة 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]/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__
، قد يتم تحديد cflags
أو cppflags
مختلفة في 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
لامتداد VNDK libexample_ext
:
- Android.bp
- include-ext/example/ext/feature_name.h
- include/example/example.h
- src/example.c
- src/ext/feature_name.c
في Android.bp
التالي، include
صادرات libexample
فقط، بينما يصدر libexample_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
. ومع ذلك، تأكد من أن جميع مستخدمي امتداد VNDK يضيفون علامات التعريف. يمكنك تعريف cc_defaults
لإضافة علامات تعريف إلى cflags
وربط المكتبات المشتركة بـ shared_libs
.
على سبيل المثال، لإضافة وظيفة عضو جديدة Example2::get_b()
إلى ملحق VNDK 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