תמיכה בבניית מערכת 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 תלוי במודול שאינו 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, 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:
    *;
};

בהתבסס על קובץ הסמלים, מערכת ה-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. כדי לבנות סיומת extends , הגדר מודול נוסף עם המאפיין vendor:true ו-extensions:

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 :

  • המאפיין 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, המודול חייב לציין את השם של סיומת shared_libs במאפיין 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__ , ייתכן שיצוינו סמלי 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

לפי שני קבצים אלה, מערכת ה-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 (למשל /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 נוצר עבור סיומת 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 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