การสนับสนุนระบบบิลด์ของ VNDK

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

ตัวอย่างการสนับสนุนการสร้าง 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 ระบบจะเลือกโมดูลทั้งหมด เนื่องจากไม่มีกลไกในการขึ้นบัญชีดำหรืออนุญาตพิเศษให้กับโมดูลที่เป็นปัญหา คุณควรล้างทรัพยากร Dependency ที่ไม่จำเป็นทั้งหมดก่อนเพิ่ม 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

เวียดนาม

ใน Android 10 และเก่ากว่า มีการติดตั้งโมดูลที่มี vndk.enabled ใน /system/lib[64]/vndk[-sp]-${VER} ใน Android 11 ขึ้นไป ไลบรารี VNDK จะจัดอยู่ในรูปแบบ APEX และชื่อของ VNDK APEX คือ com.android.vndk.v${VER} VNDK APEX เป็นแบบรวมหรือไม่แยกเป็นหลายรายการ และพร้อมใช้งานจากเส้นทาง 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 แล้ว ระบบบิลด์ไม่อนุญาตทรัพยากร Dependency ระหว่างโมดูลของผู้ให้บริการและโมดูลเฟรมเวิร์ก รวมถึงจะแสดงข้อผิดพลาดในกรณีต่อไปนี้

  • โมดูลที่ไม่มี 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:
    *;
};

ระบบบิลด์จะสร้างไลบรารีที่ใช้ร่วมกันของสตับสำหรับโมดูลผู้ให้บริการ ซึ่งจะลิงก์กับไลบรารีเหล่านี้เมื่อเปิดใช้ BOARD_VNDK_VERSION โดยอิงตามไฟล์สัญลักษณ์ สัญลักษณ์จะรวมอยู่ในไลบรารีที่ใช้ร่วมกันของสตับเฉพาะในกรณีต่อไปนี้

  • ไม่ได้กำหนดไว้ในส่วนที่ลงท้ายด้วย _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 รายการ (หลักและเวนเดอร์) ควรถือว่าตัวแปรหลักเป็นโมดูลเฟรมเวิร์ก และควรถือว่าตัวแปรของผู้ให้บริการเป็นโมดูลของผู้ให้บริการ หากโมดูลเฟรมเวิร์กบางรายการใช้โมดูลนี้ ระบบจะสร้างตัวแปรหลัก หากโมดูลของผู้ให้บริการบางรายการขึ้นอยู่กับโมดูลนี้ ระบบจะสร้างตัวแปรของผู้ให้บริการ ระบบบิลด์จะบังคับใช้การตรวจสอบทรัพยากร Dependency ต่อไปนี้

  • ตัวแปรหลักจะเป็นเฟรมเวิร์กเท่านั้นและโมดูลของผู้ให้บริการจะเข้าถึงไม่ได้
  • โมดูลเฟรมเวิร์กจะเข้าถึงตัวแปรของผู้ให้บริการไม่ได้เสมอ
  • ทรัพยากรทั้งหมดของตัวแปรผู้ให้บริการที่ระบุใน 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-ONLY ระบบจะติดตั้งไลบรารีที่แชร์ใน /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

ใน 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-SP (หรือชื่อไลบรารีที่ใช้ร่วมกัน 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 ที่ใช้ร่วมกัน 3 รายการต่อไปนี้

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

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

ข้อกำหนดเกี่ยวกับสัญลักษณ์ที่ส่งออก

เครื่องมือตรวจสอบ VNDK ABI จะเปรียบเทียบ 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 ไม่เป็นไปตามข้อกำหนดข้างต้น เครื่องมือตรวจสอบ 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
  • รวม/ตัวอย่าง/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 ทุกคนเพิ่ม Flag กำหนดแล้ว คุณสามารถกำหนด cc_defaults เพื่อเพิ่ม Flag กำหนดให้กับ 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 ไม่ว่าจะมีการใช้โดยโมดูลของผู้ให้บริการหรือไม่ก็ตาม

เมื่อระบบบิลด์มองไม่เห็นทรัพยากร Dependency (เช่น ไลบรารีที่ใช้ร่วมกันซึ่งอาจเปิดด้วย 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