دعم نظام بناء VNDK

تنظيم صفحاتك في مجموعات يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.

في Android 8.1 والإصدارات الأحدث ، يحتوي نظام الإنشاء على دعم VNDK المدمج. عند تمكين دعم VNDK ، يتحقق نظام الإنشاء من التبعيات بين الوحدات ، ويبني متغيرًا خاصًا بالمورد لوحدات البائعين النمطية ، ويقوم تلقائيًا بتثبيت هذه الوحدات في أدلة معينة.

نموذج دعم بناء VNDK

في هذا المثال ، يعرّف تعريف الوحدة النمطية Android.bp مكتبة باسم libexample . تشير الخاصية vendor_available إلى وحدات إطار العمل وقد تعتمد وحدات البائع على libexample :

libexample vendor_available: true و vndk.enabled: true

الشكل 1. تمكين دعم VNDK

يعتمد كل من إطار العمل القابل للتنفيذ /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 APEX

في 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} .

VNDK APEX

الشكل 2. VNDK APEX

تعريف الوحدة

لإنشاء 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.

false

false

false

لا توجد متغيرات البائع. هذه الوحدة هي 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 property:

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 بين متغيرات بائع 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