پشتیبانی سیستم ساخت VNDK

در Android 8.1 و بالاتر، سیستم ساخت از پشتیبانی VNDK داخلی برخوردار است. وقتی پشتیبانی از VNDK فعال باشد، سیستم ساخت وابستگی‌های بین واحدها را بررسی می‌کند، گونه‌ای مختص فروشنده برای واحدهای فروشنده می‌سازد، و آن واحدها را به‌طور خودکار در دایرکتوری‌های تعیین‌شده نصب می‌کند.

نمونه پشتیبانی ساخت VNDK

در این مثال، تعریف واحد Android.bp کتابخانه‌ای به‌نام libexample را تعریف می‌کند. دارایی vendor_available نشان می‌دهد که واحدهای چارچوب و واحدهای فروشنده ممکن است به libexample بستگی داشته باشند:

libexample vendor_available:true و vndk.enabled:true

پشتیبانی از شکل ۱ فعال شد.

هم فایل اجرایی چارچوب /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

شکل ۲. ‫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 کتابخانه‌های مشترکی با رابط‌های باینری کاربردی پایدار هستند. هم چارچوب و هم واحدهای فروشنده از پیاده‌سازی یکسان و جدید استفاده می‌کنند. برای هر کتابخانه مشترک 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 باشد، ممکن است دو نسخه متفاوت (core و vendor) ساخته شود. با گونه اصلی باید به‌عنوان یک ماژول چارچوب و با گونه فروشنده باید به‌عنوان یک ماژول فروشنده رفتار شود. اگر برخی‌از پیمانه‌های چارچوب به این پیمانه وابسته باشند، گونه اصلی ساخته می‌شود. اگر برخی‌از واحدهای فروشنده به این واحد وابسته باشند، گونه فروشنده ساخته می‌شود. سیستم ساخت این بررسی‌های وابستگی را اعمال می‌کند:

  • گونه اصلی همیشه فقط چارچوب است و واحدهای فروشنده نمی‌توانند به آن دسترسی داشته باشند.
  • گونه فروشنده همیشه برای واحدهای چارچوب غیرقابل‌دسترس است.
  • همه وابستگی‌های گونه فروشنده، که در 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}) نصب می‌شود.

جدول زیر نحوه مدیریت انواع فروشنده توسط سیستم ساخت را خلاصه می‌کند:

vendor_available ‫vndk
فعال شد
vndk
support_system_process
توضیحات متغیر فروشنده
true false false گونه‌های فروشنده فقط به دونگ ویتنام است. کتابخانه‌های مشترک در /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 با APIهای اضافی هستند. افزونه‌ها در /vendor/lib[64]/vndk[-sp] (بدون پسوند نسخه) نصب می‌شوند و کتابخانه‌های مشترک VNDK اصلی را در زمان اجرا ملغی می‌کنند.

تعریف افزونه‌های VNDK

در Android نسخه ۹ و بالاتر، 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_ext.so،‏ libvndk.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)

ترجمه شرطی

این بخش نحوه برخورد با تفاوت‌های ظریف (برای نمونه، افزودن یا برداشتن ویژگی از یکی از گونه‌ها) بین سه کتابخانه مشترک زیر را توضیح می‌دهد:

  • متغیر اصلی (مثلاً /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

الزامات مربوط به نمادهای صادرشده

بررسی‌کننده ABI مربوط به 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‏ VNDK ایجاد می‌شود:

  • Android.bp
  • include-ext/example/ext/feature_name.h
  • include/example/example.h
  • src/example.c
  • src/ext/feature_name.c

در Android.bp زیر، libexample فقط include را صادر می‌کند، درحالی‌که 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