การรองรับระบบการสร้าง VNDK

ใน Android 8.1 ขึ้นไป ระบบบิลด์จะรองรับ VNDK ในตัว เมื่อเปิดใช้การรองรับ VNDK ระบบบิลด์จะตรวจสอบการขึ้นต่อกันระหว่างโมดูล สร้างตัวแปรเฉพาะของผู้ให้บริการสำหรับโมดูลของผู้ให้บริการ และติดตั้งโมดูลเหล่านั้นลงในไดเรกทอรีที่กำหนดโดยอัตโนมัติ

ตัวอย่างการรองรับการสร้าง VNDK

ในตัวอย่างนี้ คำจำกัดความของโมดูล Android.bp จะกำหนดไลบรารีชื่อ libexample พร็อพเพอร์ตี้ vendor_available ระบุว่าโมดูลเฟรมเวิร์กและโมดูลของผู้ให้บริการอาจขึ้นอยู่กับ libexample

libexample vendor_available:true and vndk.enabled:true

เปิดใช้การรองรับ รูปที่ 1 แล้ว

ทั้งไฟล์ที่เรียกใช้งานได้ของเฟรมเวิร์ก /system/bin/foo และไฟล์ที่เรียกใช้งานได้ของผู้ให้บริการ /vendor/bin/bar ขึ้นอยู่กับ libexample และมี libexample ในพร็อพเพอร์ตี้ shared_libs

หากทั้งโมดูลเฟรมเวิร์กและโมดูลของผู้ให้บริการใช้ libexample ระบบจะสร้าง libexample 2 รูปแบบ โมเดลหลัก (ตั้งชื่อตาม libexample) ใช้โดยโมดูลเฟรมเวิร์ก และโมเดลของผู้ให้บริการ (ตั้งชื่อตาม libexample.vendor) ใช้โดยโมดูลของผู้ให้บริการ ระบบจะติดตั้งตัวแปรทั้ง 2 ไว้ในไดเรกทอรีที่แตกต่างกัน ดังนี้

  • ระบบจะติดตั้งตัวแปรหลักใน /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} APEX ของ VNDK จะรวมหรือไม่รวม และพร้อมใช้งานจากเส้นทาง Canonical /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 คือไลบรารีที่ใช้ร่วมกันซึ่งมี 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:
    *;
};

ระบบบิลด์จะสร้างไลบรารีที่ใช้ร่วมกันแบบ 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 3 รายการ ได้แก่ vendor_available, vndk.enabled และ vndk.support_system_process

หาก vendor_available หรือ vndk.enabled เป็น true ระบบอาจสร้างตัวแปร 2 รายการ (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 ระบบจะติดตั้ง Vendor Variant ลงใน VNDK APEX(com.android.vndk.v${VER})

ตารางด้านล่างสรุปวิธีที่ระบบบิลด์จัดการตัวแปรของผู้ให้บริการ

vendor_available vndk
enabled
vndk
support_system_process
คำอธิบายตัวแปรของผู้ให้บริการ
true false false รูปแบบของผู้ให้บริการเป็น VND เท่านั้น ระบบจะติดตั้งไลบรารีที่ใช้ร่วมกันใน /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 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)

การคอมไพล์แบบมีเงื่อนไข

ส่วนนี้จะอธิบายวิธีจัดการกับความแตกต่างเล็กๆ น้อยๆ (เช่น การเพิ่มหรือนำฟีเจอร์ออกจากตัวแปรใดตัวแปรหนึ่ง) ระหว่างไลบรารีที่ใช้ร่วมกัน 3 รายการของ VNDK ดังนี้

  • ตัวแปรหลัก (เช่น /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

ตามไฟล์ทั้ง 2 นี้ ระบบบิลด์จะสร้างไลบรารีที่ใช้ร่วมกัน โดยมีสัญลักษณ์ที่ส่งออกต่อไปนี้

เส้นทางการติดตั้ง สัญลักษณ์ที่ส่งออก
/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 dumps
  • สัญลักษณ์ที่ส่งออกจากส่วนขยาย VNDK (เช่น /vendor/lib[64]/vndk/libexample.so) ต้องเป็นซูเปอร์เซ็ตของ สัญลักษณ์ที่กำหนดไว้ในการดัมพ์ ABI

หากตัวแปรของผู้ให้บริการ VNDK หรือส่วนขยาย VNDK ไม่เป็นไปตาม ข้อกำหนดข้างต้น ตัวตรวจสอบ ABI ของ VNDK จะแสดงข้อผิดพลาดในการสร้างและหยุด การสร้าง

ยกเว้นไฟล์ต้นฉบับหรือไลบรารีที่แชร์จากตัวแปรของผู้ให้บริการ

หากต้องการยกเว้นไฟล์ต้นฉบับจากตัวแปรของผู้ให้บริการ ให้เพิ่มไฟล์ลงในพร็อพเพอร์ตี้ 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 เนื่องจากพร็อพเพอร์ตี้ exclude_srcs ไม่รวม fwk.c ในทำนองเดียวกัน จะขึ้นอยู่กับเฉพาะไลบรารีที่แชร์ libboth เนื่องจากพร็อพเพอร์ตี้ exclude_shared_libs ยกเว้น libfwk_only

ส่งออกส่วนหัวจากส่วนขยาย 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 ซึ่งจะช่วยให้ผู้ใช้ libexample ไม่รวม feature_name.h โดยไม่ถูกต้อง

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