ב-Android מגרסה 8.1 ואילך, במערכת ה-build יש תמיכה מובנית ב-VNDK. מתי תמיכה ב-VNDK מופעלת, מערכת ה-build בודקת את יחסי התלות בין מודולים, יוצר וריאנט ספציפי לספק למודולים של ספקים יתקין את המודולים האלה באופן אוטומטי בספריות ייעודיות.
דוגמה לתמיכה ב-build של VNDK
בדוגמה הזו, הגדרת המודול Android.bp
מגדירה
ספרייה בשם libexample
. vendor_available
מציין שמודולים של framework ומודולים של ספקים עשויים להיות תלויים
libexample
:
איור 1. התמיכה מופעלת.
גם קובץ ההפעלה של המסגרת /system/bin/foo
וגם הספק
קובצי ההפעלה /vendor/bin/bar
תלויים ב-libexample
וב-
יש libexample
בנכסים שלהם ב-shared_libs
.
אם משתמשים ב-libexample
גם במודולים של framework וגם בספק
של libexample
, נוצרים שתי גרסאות. הווריאנט העיקרי
(נקרא אחרי libexample
) משמש במודולים של framework
הווריאנט של הספק (שנקרא אחרי libexample.vendor
) משמש את הספק
מודולים. שתי הווריאציות מותקנות בספריות שונות:
- הווריאנט העיקרי מותקן בתוך
/system/lib[64]/libexample.so
- וריאנט הספק מותקן ב-VNDK APEX כי
vndk.enabled
היאtrue
.
פרטים נוספים זמינים במאמר הגדרת המודול.
הגדרת התמיכה ב-build
כדי להפעיל תמיכה מלאה במערכת build למכשיר מוצר, צריך להוסיף
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}
.
איור 2. VNDK APEX.
הגדרת המודול
כדי לפתח את Android באמצעות BOARD_VNDK_VERSION
, צריך לשנות את
הגדרת המודול ב-Android.mk
או
Android.bp
. בקטע הזה מתוארים סוגים שונים של מודולים
הגדרות, מספר מאפייני מודולים שקשורים ל-VNDK ובדיקות תלות
הטמענו במערכת ה-build.
מודולים של ספקים
מודולים של ספקים הם קובצי הפעלה ספציפיים לספק או ספריות משותפות
חייב להיות מותקן במחיצת ספק. ב-Android.bp
קבצים,
במודולים של ספקים צריך להגדיר את הנכס של הספק או של הנכס ל-true
.
ב-Android.mk
קבצים, צריך להגדיר מודולים של ספקים
LOCAL_VENDOR_MODULE
או LOCAL_PROPRIETARY_MODULE
אל
true
אם מגדירים את BOARD_VNDK_VERSION
, מערכת ה-build אוסרת
או יחסי התלות בין מודולים של ספקים למודולים של framework, ויוצרת שגיאות אם:
- מודול ללא
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 הן ספריות משותפות עם ממשקי 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: *; };
בהתבסס על קובץ הסמל, מערכת ה-build יוצרת ספרייה משותפת מסוג stub עבור
של ספקים, שמקשרים לספריות האלה
התכונה BOARD_VNDK_VERSION
מופעלת. יש סמל ב-stub
לספרייה המשותפת רק אם:
- לא מוגדר בקטע שמסתיים בספרות
_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
, שתי וריאציות (ליבה וספק) יכולות להיות
של BERT. יש להתייחס לווריאנט העיקרי כמודול של framework ולספק
יש להתייחס אל וריאנט כאל מודול ספק. אם חלק מהמודולים של framework תלויים
במודול הזה, הווריאנט המרכזי נוצר. אם חלק מהמודולים של הספקים
בהתאם למודול הזה, הווריאנט של הספק בנוי. מערכת ה-build אוכפת
את בדיקות התלות הבאות:
- הווריאנט העיקרי תמיד זמין ל-framework בלבד ואין לו גישה לספק מודולים.
- תמיד אי אפשר לגשת לווריאנט של הספק למודולים של framework.
- כל יחסי התלות של הווריאנט של הספק, שמפורטים
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}
).
- אם הערך של
הטבלה הבאה מסכמת את האופן שבו מערכת ה-build מטפלת בווריאציות של הספק:
ספק_זמין | vndk מופעל |
vndk support_same_process |
תיאורי הווריאציות של הספק |
---|---|---|---|
true |
false |
false |
הווריאציות של הספק הן רק VND. הספריות המשותפות הן
הותקנה אל /vendor/lib[64] . |
true |
לא חוקי (שגיאת Build) | ||
true |
false |
הווריאציות של הספק הן VNDK. ספריות משותפות מותקנות אל VNDK APEX. | |
true |
הווריאציות של הספק הן VNDK-SP. הספריות המשותפות הן מותקנת ב-VNDK APEX. | ||
|
|
|
אין וריאציות של הספק. מודול זה הוא FWK בלבד. |
true |
לא חוקי (שגיאת Build) | ||
true |
false |
הווריאציות של הספק הן VNDK-Private. הספריות המשותפות הן מותקנת ב-VNDK APEX. הערכים האלה לא יכולים להיות משמש ישירות במודולים של ספקים. | |
true |
הווריאציות של הספק הן VNDK-SP-Private. הספריות המשותפות הן מותקנת ב-VNDK APEX. הערכים האלה לא יכולים להיות משמש ישירות במודולים של ספקים. |
תוספי VNDK
תוספי VNDK הם ספריות משותפות של VNDK עם ממשקי API נוספים. התוספים הם
מותקנת ב-/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
אם מודול הספק תלוי בממשקי API נוספים שהוגדרו על ידי תוספי 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
)
דגלים מהדר מותנים
מערכת ה-build של 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
לפי שני הקבצים האלה, מערכת ה-build יוצרת ספריות משותפות עם הסמלים המיוצאים הבאים:
נתיב התקנה | סמלים שיוצאו |
---|---|
/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
) חייב להיות זהה לסמלים שמוגדרים ב-dumps של ABI (ולא לקבוצות-על של). - סמלים שיוצאו על ידי תוספי VNDK (למשל,
/vendor/lib[64]/vndk/libexample.so
) חייב להיות קבוצות-על של שמוגדרים ב-dumps של ABI.
אם אין מעקב אחר וריאציות של ספק VNDK או תוספי VNDK את הדרישות שצוינו למעלה, בודק ה-ABI של VNDK פולט שגיאות build ומפסיק build.
החרגה של קובצי מקור או ספריות משותפות בווריאנטים של הספק
כדי להחריג קובצי מקור מהווריאנט של הספק, מוסיפים אותם אל
נכס 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
הבאים, 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, }
חבילות מוצרים
במערכת ה-build של Android, המשתנה PRODUCT_PACKAGES
מציין את קובצי ההפעלה, הספריות המשותפות או החבילות
במכשיר. יחסי התלות המעבריים של
וגם מותקנים במרומז את המכשיר.
אם המדיניות BOARD_VNDK_VERSION
מופעלת, מודולים עם
vendor_available
או vndk.enabled
יש לך הזדמנות מיוחדת
לטיפול. אם מודול framework תלוי במודול עם
vendor_available
או vndk.enabled
, הווריאנט העיקרי
נכלל בקבוצת ההתקנה הטרנזית. אם מודול של ספק
תלוי במודול עם vendor_available
, וריאציית הספק
נכללים בקבוצת ההתקנה הטרנזית. עם זאת, וריאציות של מודולים של ספק
עם vndk.enabled
מותקנות גם במודולים של ספקים וגם אם לא.
כשיחסי התלות לא גלויים למערכת ה-build (למשל, ספריות משותפות)
שאפשר לפתוח באמצעות 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