תמיכה בבניית מערכת VNDK

באנדרואיד 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

באנדרואיד 10 ומטה, מודולים עם vndk.enabled הותקנו ב- /system/lib[64]/vndk[-sp]-${VER} . באנדרואיד 11 ומעלה, ספריות VNDK ארוזות בפורמט APEX והשם של VNDK APEX הוא com.android.vndk.v${VER} . בהתאם לתצורת המכשיר, VNDK APEX משוטח או לא משטח וזמין מהנתיב הקנוני /apex/com.android.vndk.v${VER} .

VNDK APEX

איור 2. VNDK APEX

הגדרת מודול

כדי לבנות אנדרואיד עם BOARD_VNDK_VERSION , עליך לשנות את הגדרת המודול ב- Android.mk או Android.bp . סעיף זה מתאר סוגים שונים של הגדרות מודול, מספר מאפייני מודול הקשורים ל-VNDK ובדיקות תלות המיושמות במערכת הבנייה.

מודולים של ספקים

מודולי ספק הם קובצי הפעלה ספציפיים לספק או ספריות משותפות שיש להתקין במחיצת ספק. בקבצי Android.bp , מודולי ספק חייבים להגדיר את הספק או המאפיין הקנייני ל- true . בקבצי Android.mk , מודולי הספק חייבים להגדיר את LOCAL_VENDOR_MODULE או LOCAL_PROPRIETARY_MODULE ל- true .

אם BOARD_VNDK_VERSION מוגדרת, מערכת ה-build אוסרת תלות בין מודולי ספק ומודול מסגרת ופולטת שגיאות אם:

  • מודול ללא vendor:true תלוי במודול עם vendor:true , או
  • מודול עם vendor:true תלוי במודול non- 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 מייצרת ספרייה משותפת של קטעים עבור מודולי ספקים, אשר מקשרים עם ספריות אלו כאשר 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 , ניתן לבנות שתי גרסאות ( ליבה וספק ). יש להתייחס לוריאנט הליבה כמודול מסגרת ולגרסת הספק יש להתייחס כמודול ספק. אם מודולי מסגרת מסוימים תלויים במודול זה, גרסת הליבה נבנית. אם מודולי ספק מסוימים תלויים במודול זה, וריאנט הספק נבנה. מערכת ה-build אוכפת את בדיקות התלות הבאות:

  • גרסת הליבה היא תמיד מסגרת בלבד ואינה נגישה למודולי הספק.
  • גרסת הספק תמיד לא נגישה למודולי מסגרת.
  • כל התלות של גרסת הספק, המצוינת ב- 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_same_process
תיאורי וריאציות של ספקים
true false false גרסאות הספק הן VND בלבד . ספריות משותפות מותקנות ב- /vendor/lib[64] .
true לא חוקי (שגיאת בנייה)
true false גרסאות הספק הן VNDK . ספריות משותפות מותקנות ב-VNDK APEX.
true גרסאות הספק הן VNDK-SP . ספריות משותפות מותקנות ב-VNDK APEX.

false

false

false

אין גרסאות של ספקים. מודול זה מיועד ל-FWK בלבד .

true לא חוקי (שגיאת בנייה)
true false גרסאות הספק הן VNDK-Private . ספריות משותפות מותקנות ב-VNDK APEX. אין להשתמש בהם ישירות על ידי מודולי הספק.
true גרסאות הספק הן VNDK-SP-Private . ספריות משותפות מותקנות ב-VNDK APEX. אין להשתמש בהם ישירות על ידי מודולי הספק.

הרחבות VNDK

הרחבות VNDK הן ספריות משותפות של VNDK עם ממשקי API נוספים. הרחבות מותקנות ב- /vendor/lib[64]/vndk[-sp] (ללא סיומת גרסה) ועוקפות את הספריות המשותפות המקוריות של VNDK בזמן ריצה.

הגדרת הרחבות VNDK

באנדרואיד 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_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 dumps הייחוס תחת prebuilts/abi-dumps/vndk .

  • סמלים המיוצאים על ידי גרסאות של ספקים של VNDK (למשל /apex/com.android.vndk.v${VER}/lib[64]/libexample.so ) חייבים להיות זהים לסמלים המוגדרים ב-ABI dumps (לא לערכות העל של ה-VNDK).
  • סמלים המיוצאים על ידי הרחבות VNDK (למשל /vendor/lib[64]/vndk/libexample.so ) חייבים להיות ערכות-על של הסמלים המוגדרים ב-ABI dumps.

אם גרסאות הספק של 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 הבא, יצוא 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 guards. עם זאת, ודא שכל משתמשי תוסף VNDK מוסיפים את הדגלים המגדירים. אתה יכול להגדיר cc_defaults כדי להוסיף דגלים להגדיר ל- cflags ולקשר ספריות משותפות עם shared_libs .

לדוגמה, כדי להוסיף פונקציית חבר חדשה Example2::get_b() לסיומת VNDK libexample2_ext , עליך לשנות את קובץ הכותרת הקיים ולהוסיף #ifdef guard:

#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 מקבלים טיפול מיוחד. אם מודול מסגרת תלוי במודול עם 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