ความเสถียรของ Application Binary Interface (ABI) เป็นข้อกำหนดเบื้องต้นของการอัปเดตเฉพาะเฟรมเวิร์ก เนื่องจากโมดูลผู้ขายอาจขึ้นอยู่กับไลบรารีที่แชร์ของ Vendor Native Development Kit (VNDK) ที่อยู่ในพาร์ติชันระบบ ภายในรุ่น Android ไลบรารีที่ใช้ร่วมกัน VNDK ที่สร้างขึ้นใหม่จะต้องเข้ากันได้กับ ABI กับไลบรารีที่ใช้ร่วมกันของ VNDK ที่เผยแพร่ก่อนหน้านี้ ดังนั้นโมดูลผู้ขายจึงสามารถทำงานกับไลบรารีเหล่านั้นได้โดยไม่ต้องคอมไพล์ซ้ำและไม่มีข้อผิดพลาดรันไทม์ ระหว่างการเปิดตัว Android ไลบรารี VNDK สามารถเปลี่ยนแปลงได้และไม่มีการรับประกัน ABI
เพื่อช่วยให้แน่ใจว่า ABI เข้ากันได้ Android 9 มีตัวตรวจสอบ ABI ส่วนหัวตามที่อธิบายไว้ในส่วนต่อไปนี้
เกี่ยวกับการปฏิบัติตาม VNDK และ ABI
VNDK เป็นชุดของไลบรารีที่จำกัดซึ่งโมดูลผู้ขายอาจเชื่อมโยงและเปิดใช้งานการอัปเดตเฉพาะเฟรมเวิร์ก การ ปฏิบัติตาม ABI หมายถึงความสามารถของไลบรารีที่ใช้ร่วมกันเวอร์ชันใหม่กว่าในการทำงานตามที่คาดไว้กับโมดูลที่เชื่อมโยงกับไลบรารีแบบไดนามิก
เกี่ยวกับสัญลักษณ์ที่ส่งออก
สัญลักษณ์ที่ส่งออก (หรือเรียกอีกอย่างว่า สัญลักษณ์สากล ) หมายถึงสัญลักษณ์ที่ตรงตามเงื่อนไขต่อไปนี้ทั้งหมด:
- ส่งออกโดย ส่วนหัวสาธารณะ ของไลบรารีที่ใช้ร่วมกัน
- ปรากฏในตาราง
.dynsym
ของไฟล์ ..so
ที่สอดคล้องกับไลบรารีที่ใช้ร่วมกัน - มีการผูกมัดที่อ่อนแอหรือเป็นสากล
- การมองเห็นเป็นค่าเริ่มต้นหรือป้องกันไว้
- ดัชนีส่วนไม่ได้กำหนด
- ประเภทคือ FUNC หรือ OBJECT
ส่วนหัวสาธารณะ ของไลบรารีที่แบ่งใช้ถูกกำหนดให้เป็นส่วนหัวที่พร้อมใช้งานสำหรับไลบรารี/ไบนารีอื่นๆ ผ่าน export_include_dirs
, export_header_lib_headers
, export_static_lib_headers
, export_shared_lib_headers
และ export_generated_headers
ในนิยาม Android.bp
ของโมดูลที่สอดคล้องกับไลบรารีที่ใช้ร่วมกัน
เกี่ยวกับประเภทที่เข้าถึงได้
ชนิดที่ เข้าถึงได้คือชนิด C/C++ ที่มีอยู่ภายในหรือที่ผู้ใช้กำหนด ซึ่งสามารถเข้าถึงได้โดยตรงหรือโดยอ้อมผ่านสัญลักษณ์ที่ส่งออกและส่งออกผ่านส่วนหัวสาธารณะ ตัวอย่างเช่น libfoo.so
มีฟังก์ชัน Foo
ซึ่งเป็นสัญลักษณ์ส่งออกที่พบในตาราง . .dynsym
ไลบรารี libfoo.so
มีดังต่อไปนี้:
foo_exported.h | foo.private.h |
---|---|
typedef struct foo_private foo_private_t; typedef struct foo { int m1; int *m2; foo_private_t *mPfoo; } foo_t; typedef struct bar { foo_t mfoo; } bar_t; bool Foo(int id, bar_t *bar_ptr); | typedef struct foo_private { int m1; float mbar; } foo_private_t; |
Android.bp |
---|
cc_library { name : libfoo, vendor_available: true, vndk { enabled : true, } srcs : ["src/*.cpp"], export_include_dirs : [ "include" ], } |
.dynsym ตาราง | |||||||
---|---|---|---|---|---|---|---|
Num | Value | Size | Type | Bind | Vis | Ndx | Name |
1 | 0 | 0 | FUNC | GLOB | DEF | UND | dlerror@libc |
2 | 1ce0 | 20 | FUNC | GLOB | DEF | 12 | Foo |
ดูที่ Foo
ประเภทที่เข้าถึงได้โดยตรง/โดยอ้อม ได้แก่:
พิมพ์ | คำอธิบาย |
---|---|
bool | ประเภทการส่งคืนของ Foo |
int | ประเภทของพารามิเตอร์ Foo แรก |
bar_t * | ประเภทของพารามิเตอร์ Foo ที่สอง โดยวิธีการของ bar_t * bar_t จะถูกส่งออกผ่าน foo_exported.h bar_t มีสมาชิก mfoo ประเภท foo_t ซึ่งส่งออกผ่าน foo_exported.h ซึ่งส่งผลให้มีการส่งออกหลายประเภทมากขึ้น:
อย่างไรก็ตาม foo_private_t ไม่สามารถเข้าถึงได้เนื่องจากไม่ได้ส่งออกผ่าน foo_exported.h ( foot_private_t * เป็นสีทึบ ดังนั้นการเปลี่ยนแปลงที่ทำกับ foo_private_t จะได้รับอนุญาต) |
สามารถให้คำอธิบายที่คล้ายกันสำหรับประเภทที่เข้าถึงได้ผ่านตัวระบุคลาสพื้นฐานและพารามิเตอร์เทมเพลตเช่นกัน
สร้างความมั่นใจในการปฏิบัติตาม ABI
ต้องรับรองการปฏิบัติตาม ABI สำหรับไลบรารีที่ทำเครื่องหมาย vendor_available: true
และ vndk.enabled: true
ในไฟล์ Android.bp
ที่เกี่ยวข้อง ตัวอย่างเช่น:
cc_library { name: "libvndk_example", vendor_available: true, vndk: { enabled: true, } }
สำหรับชนิดข้อมูลที่สามารถเข้าถึงได้โดยตรงหรือโดยอ้อมโดยฟังก์ชันที่ส่งออก การเปลี่ยนแปลงต่อไปนี้ในไลบรารีถูกจัดประเภทเป็นการทำลาย ABI:
ประเภทข้อมูล | คำอธิบาย |
---|---|
โครงสร้างและชั้นเรียน |
|
สหภาพแรงงาน |
|
การแจงนับ |
|
สัญลักษณ์สากล |
|
* ต้องไม่เปลี่ยนหรือลบฟังก์ชันทั้งแบบสาธารณะและส่วนตัวของสมาชิก เนื่องจากฟังก์ชันแบบอินไลน์สาธารณะสามารถอ้างถึงฟังก์ชันของสมาชิกส่วนตัวได้ การอ้างอิงสัญลักษณ์ไปยังฟังก์ชันสมาชิกส่วนตัวสามารถเก็บไว้ในระบบไบนารีของผู้โทรได้ การเปลี่ยนหรือลบฟังก์ชันสมาชิกไพรเวตจากไลบรารีที่แบ่งใช้อาจส่งผลให้ไบนารีเข้ากันไม่ได้แบบย้อนหลัง
** ต้องไม่เปลี่ยนแปลงการชดเชยให้กับสมาชิกข้อมูลสาธารณะหรือส่วนตัวเนื่องจากฟังก์ชันอินไลน์สามารถอ้างถึงสมาชิกข้อมูลเหล่านี้ในเนื้อหาฟังก์ชันได้ การเปลี่ยนค่าชดเชยสมาชิกข้อมูลอาจส่งผลให้ไบนารีเข้ากันไม่ได้แบบย้อนหลัง
*** แม้ว่าสิ่งเหล่านี้จะไม่เปลี่ยนเลย์เอาต์หน่วยความจำของประเภท แต่ก็มีความแตกต่างทางความหมายที่อาจทำให้ไลบรารีไม่ทำงานตามที่คาดไว้
การใช้เครื่องมือที่สอดคล้องกับ ABI
เมื่อมีการสร้างไลบรารี VNDK ABI ของไลบรารีจะถูกเปรียบเทียบกับการอ้างอิง ABI ที่สอดคล้องกันสำหรับเวอร์ชันของ VNDK ที่กำลังสร้าง การถ่ายโอนข้อมูล ABI อ้างอิงอยู่ใน:
${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/(v)ndk/<${PLATFORM_VNDK_VERSION}>/<BINDER_BITNESS>/<ARCH_ARCH-VARIANT>/source-based
ตัวอย่างเช่น ในการสร้าง libfoo
สำหรับ API ระดับ 27 ของ VNDK นั้น ABI ที่อนุมานของ libfoo
จะถูกนำไปเปรียบเทียบกับข้อมูลอ้างอิงที่:
${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/(v)ndk/27/64/<ARCH_ARCH-VARIANT>/source-based/libfoo.so.lsdump
ข้อผิดพลาดการแตกหักของ ABI
ในการแตกของ ABI บันทึกการสร้างจะแสดงคำเตือนด้วยประเภทคำเตือนและเส้นทางไปยังรายงาน abi-diff ตัวอย่างเช่น หาก ABI ของ libbinder
มีการเปลี่ยนแปลงที่เข้ากันไม่ได้ ระบบบิลด์จะแสดงข้อผิดพลาดพร้อมข้อความที่คล้ายกับต่อไปนี้:
***************************************************** error: VNDK library: libbinder.so's ABI has INCOMPATIBLE CHANGES Please check compatibility report at: out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm64_armv8-a_cortex-a73_vendor_shared/libbinder.so.abidiff ****************************************************** ---- Please update abi references by running platform/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l libbinder ----
การสร้างห้องสมุด VNDK การตรวจสอบ ABI
เมื่อสร้างไลบรารี VNDK:
-
header-abi-dumper
ประมวลผลไฟล์ต้นฉบับที่คอมไพล์เพื่อสร้างไลบรารี VNDK (ไฟล์ต้นฉบับของไลบรารีเอง เช่นเดียวกับไฟล์ต้นฉบับที่สืบทอดผ่านการพึ่งพาสกรรมกริยาแบบคงที่) เพื่อสร้างไฟล์.sdump
ที่สอดคล้องกับแต่ละแหล่งที่มารูปที่ 1. การสร้างไฟล์ .sdump
-
header-abi-linker
ประมวลผลไฟล์.sdump
(โดยใช้สคริปต์เวอร์ชันที่มีให้หรือไฟล์.so
ที่สอดคล้องกับไลบรารีที่ใช้ร่วมกัน) เพื่อสร้างไฟล์.lsdump
ที่บันทึกข้อมูล ABI ทั้งหมดที่สอดคล้องกับไลบรารีที่ใช้ร่วมกันรูปที่ 2. การสร้างไฟล์ .lsdump
-
header-abi-diff
เปรียบเทียบไฟล์.lsdump
กับไฟล์อ้างอิง.lsdump
เพื่อสร้างรายงาน diff ที่สรุปความแตกต่างใน ABI ของทั้งสองไลบรารีรูปที่ 3 การสร้างรายงานส่วนต่าง
header-abi-dumper
เครื่องมือ header-abi-dumper
แยกวิเคราะห์ไฟล์ต้นฉบับ C/C++ และดัมพ์ ABI ที่อนุมานจากไฟล์ต้นทางนั้นลงในไฟล์ระดับกลาง ระบบบิลด์รัน header-abi-dumper
บนไฟล์ต้นฉบับที่คอมไพล์แล้วทั้งหมด ในขณะที่สร้างไลบรารีที่รวมไฟล์ต้นฉบับจากการพึ่งพาสกรรมกริยา
ปัจจุบันไฟล์ .sdump
มีรูปแบบเป็น Protobuf TextFormatted ซึ่งไม่รับประกันว่าจะมีเสถียรภาพในรุ่นต่อๆ ไป ดังนั้น การจัดรูปแบบไฟล์ .sdump
จึงควรถือเป็นรายละเอียดการใช้งานระบบบิลด์
ตัวอย่างเช่น libfoo.so
มีไฟล์ต้นฉบับ foo.cpp
ต่อไปนี้:
#include <stdio.h> #include <foo_exported.h> bool Foo(int id, bar_t *bar_ptr) { if (id > 0 && bar_ptr->mfoo.m1 > 0) { return true; } return false; }
คุณสามารถใช้ header-abi-dumper
เพื่อสร้างไฟล์ .sdump
ระดับกลางที่แสดงถึง ABI ที่นำเสนอโดยไฟล์ต้นฉบับโดยใช้:
$ header-abi-dumper foo.cpp -I exported -o foo.sdump -- -x c++
คำสั่งนี้บอกให้ header-abi-dumper
แยกวิเคราะห์ foo.cpp
และส่งข้อมูล ABI ที่เปิดเผยในส่วนหัวสาธารณะในไดเร็กทอรีที่ exported
นี่เป็นข้อความที่ตัดตอนมา (ไม่ใช่การแสดงทั้งหมด) จาก foo.sdump
ที่สร้างโดย header-abi-dumper
:
record_types { type_info { name: "foo" size: 12 alignment: 4 referenced_type: "type-1" source_file: "foo/include/foo_exported.h" linker_set_key: "foo" self_type: "type-1" } fields { referenced_type: "type-2" field_offset: 0 field_name: "m1" access: public_access } fields { referenced_type: "type-3" field_offset: 32 field_name: "m2" access: public_access } fields { referenced_type: "type-5" field_offset: 64 field_name: "mPfoo" access: public_access } access: public_access record_kind: struct_kind tag_info { unique_id: "_ZTS3foo" } } record_types { type_info { name: "bar" size: 12 alignment: 4 referenced_type: "type-6" … pointer_types { type_info { name: "bar *" size: 4 alignment: 4 referenced_type: "type-6" source_file: "foo/include/foo_exported.h" linker_set_key: "bar *" self_type: "type-8" } } builtin_types { type_info { name: "int" size: 4 alignment: 4 referenced_type: "type-2" source_file: "" linker_set_key: "int" self_type: "type-2" } is_unsigned: false is_integral: true } functions { return_type: "type-7" function_name: "Foo" source_file: "foo/include/foo_exported.h" parameters { referenced_type: "type-2" default_arg: false } parameters { referenced_type: "type-8" default_arg: false } linker_set_key: "_Z3FooiP3bar" access: public_access }
foo.sdump
มีข้อมูล ABI ที่เปิดเผยโดยไฟล์ต้นฉบับ foo.cpp
เช่น:
- บันทึก
record_types
อ้างถึงโครงสร้าง สหภาพแรงงาน หรือชั้นเรียนที่เปิดเผยโดยส่วนหัวสาธารณะ เร็กคอร์ดแต่ละประเภทมีข้อมูลเกี่ยวกับฟิลด์ ขนาด ตัวระบุการเข้าถึง ไฟล์ส่วนหัวที่เปิดเผย ฯลฯ -
pointer_types
อ้างถึงประเภทพอยน์เตอร์ที่อ้างอิงโดยตรง/โดยอ้อมโดยเร็กคอร์ด/ฟังก์ชันที่เปิดเผยโดยส่วนหัวสาธารณะ พร้อมกับประเภทที่ตัวชี้ชี้ไป (ผ่านฟิลด์referenced_type
ในtype_info
) ข้อมูลที่คล้ายกันถูกบันทึกไว้ในไฟล์.sdump
สำหรับประเภทที่ผ่านการรับรอง ประเภท C/C++ ในตัว ประเภทอาร์เรย์ และประเภทการอ้างอิง lvalue และ rvalue (ข้อมูลการบันทึกเกี่ยวกับประเภทดังกล่าวอนุญาตให้มี diffing แบบเรียกซ้ำ) -
functions
. แสดงถึงฟังก์ชันที่เปิดเผยโดยส่วนหัวสาธารณะ พวกเขายังมีข้อมูลเกี่ยวกับชื่อ mangled ของฟังก์ชัน ประเภทการส่งคืน ประเภทของพารามิเตอร์ ตัวระบุการเข้าถึง ฯลฯ
header-abi-linker
เครื่องมือ header-abi-linker
ใช้ไฟล์ระดับกลางที่สร้างโดย header-abi-dumper
เป็นอินพุต จากนั้นลิงก์ไฟล์เหล่านั้น:
อินพุต |
|
---|---|
เอาท์พุต | ไฟล์ที่บันทึก ABI ของไลบรารีที่ใช้ร่วมกัน (เช่น libfoo.so.lsdump แสดงถึง ABI ของ libfoo ) |
เครื่องมือนี้จะรวมกราฟประเภทในไฟล์ระดับกลางทั้งหมดที่มีให้ โดยคำนึงถึงความแตกต่างระหว่างหน่วยการแปลที่มีคำจำกัดความเดียว (ประเภทที่กำหนดโดยผู้ใช้ในหน่วยการแปลต่างๆ ที่มีชื่อเต็มเหมือนกัน อาจมีความหมายต่างกัน) ในแต่ละหน่วยการแปล จากนั้นเครื่องมือจะแยกวิเคราะห์สคริปต์เวอร์ชันหรือตาราง .dynsym
ของไลบรารีที่ใช้ร่วมกัน (ไฟล์ . .so
) เพื่อสร้างรายการสัญลักษณ์ที่เอ็กซ์พอร์ต
ตัวอย่างเช่น เมื่อ libfoo
เพิ่มไฟล์ bar.cpp
(ซึ่งแสดง bar
ฟังก์ชัน C) ในการคอมไพล์ สามารถเรียกใช้ header-abi-linker
เพื่อสร้าง ABI dump ที่ลิงก์โดยสมบูรณ์ของ libfoo
ได้ดังนี้:
header-abi-linker -I exported foo.sdump bar.sdump \ -o libfoo.so.lsdump \ -so libfoo.so \ -arch arm64 -api current
ตัวอย่างเอาต์พุตคำสั่งใน libfoo.so.lsdump
:
record_types { type_info { name: "foo" size: 24 alignment: 8 referenced_type: "type-1" source_file: "foo/include/foo_exported.h" linker_set_key: "foo" self_type: "type-1" } fields { referenced_type: "type-2" field_offset: 0 field_name: "m1" access: public_access } fields { referenced_type: "type-3" field_offset: 64 field_name: "m2" access: public_access } fields { referenced_type: "type-4" field_offset: 128 field_name: "mPfoo" access: public_access } access: public_access record_kind: struct_kind tag_info { unique_id: "_ZTS3foo" } } record_types { type_info { name: "bar" size: 24 alignment: 8 ... builtin_types { type_info { name: "void" size: 0 alignment: 0 referenced_type: "type-6" source_file: "" linker_set_key: "void" self_type: "type-6" } is_unsigned: false is_integral: false } functions { return_type: "type-19" function_name: "Foo" source_file: "foo/include/foo_exported.h" parameters { referenced_type: "type-2" default_arg: false } parameters { referenced_type: "type-20" default_arg: false } linker_set_key: "_Z3FooiP3bar" access: public_access } functions { return_type: "type-6" function_name: "FooBad" source_file: "foo/include/foo_exported_bad.h" parameters { referenced_type: "type-2" default_arg: false } parameters { referenced_type: "type-7" default_arg: false } linker_set_key: "_Z6FooBadiP3foo" access: public_access } elf_functions { name: "_Z3FooiP3bar" } elf_functions { name: "_Z6FooBadiP3foo" }
เครื่องมือ header-abi-linker
:
- ลิงก์ไฟล์
.sdump
ที่มีให้ (foo.sdump
และbar.sdump
) กรองข้อมูล ABI ที่ไม่มีอยู่ในส่วนหัวที่อยู่ในไดเร็กทอรี:exported
- แยกวิเคราะห์
libfoo.so
และรวบรวมข้อมูลเกี่ยวกับสัญลักษณ์ที่ส่งออกโดยไลบรารีผ่านตาราง ..dynsym
- เพิ่ม
_Z3FooiP3bar
และBar
libfoo.so.lsdump
เป็นการถ่ายโอนข้อมูล ABI ขั้นสุดท้ายของ libfoo.so
header-abi-diff
เครื่องมือ header-abi-diff
เปรียบเทียบไฟล์ .lsdump
สองไฟล์ที่แสดงถึง ABI ของสองไลบรารีและสร้างรายงาน diff ที่ระบุความแตกต่างระหว่าง ABI ทั้งสอง
อินพุต |
|
---|---|
เอาท์พุต | รายงานความแตกต่างที่ระบุความแตกต่างใน ABI ที่เสนอโดยไลบรารีที่แบ่งใช้สองแห่งเมื่อเปรียบเทียบ |
ไฟล์ diff ของ ABI ได้รับการออกแบบมาให้ละเอียดและอ่านง่ายที่สุด รูปแบบอาจมีการเปลี่ยนแปลงในรุ่นต่อๆ ไป ตัวอย่างเช่น คุณมี libfoo
สองเวอร์ชัน: libfoo_old.so
และ libfoo_new.so
ใน libfoo_new.so
ใน bar_t
คุณเปลี่ยนประเภทของ mfoo
จาก foo_t
เป็น foo_t *
เนื่องจาก bar_t
เป็นประเภทที่เข้าถึงได้โดยตรง จึงควรติดธงว่าเป็นการเปลี่ยนแปลงการทำลาย ABI โดย header-abi-diff
ในการเรียกใช้ header-abi-diff
:
header-abi-diff -old libfoo_old.so.lsdump \ -new libfoo_new.so.lsdump \ -arch arm64 \ -o libfoo.so.abidiff \ -lib libfoo
ตัวอย่างเอาต์พุตคำสั่งใน libfoo.so.abidiff
:
lib_name: "libfoo" arch: "arm64" record_type_diffs { name: "bar" type_stack: "Foo-> bar *->bar " type_info_diff { old_type_info { size: 24 alignment: 8 } new_type_info { size: 8 alignment: 8 } } fields_diff { old_field { referenced_type: "foo" field_offset: 0 field_name: "mfoo" access: public_access } new_field { referenced_type: "foo *" field_offset: 0 field_name: "mfoo" access: public_access } } }
libfoo.so.abidiff
มีรายงานการเปลี่ยนแปลงการละเมิด ABI ทั้งหมดใน libfoo
ข้อความ record_type_diffs
ระบุว่าเร็กคอร์ดมีการเปลี่ยนแปลงและแสดงรายการการเปลี่ยนแปลงที่เข้ากันไม่ได้ ซึ่งรวมถึง:
- ขนาดของเร็กคอร์ดเปลี่ยนจาก
24
ไบต์เป็น8
ไบต์ - ประเภทฟิลด์ของ
mfoo
เปลี่ยนจากfoo
เป็นfoo *
(typedefs ทั้งหมดถูกถอดออก)
ฟิลด์ type_stack
ระบุว่า header-abi-diff
ถึงประเภทที่เปลี่ยนแปลงอย่างไร ( bar
) ฟิลด์นี้อาจตีความได้ว่า Foo
เป็นฟังก์ชันที่ส่งออกซึ่งรับ bar *
เป็นพารามิเตอร์ ซึ่งชี้ไปที่ bar
ซึ่งส่งออกและเปลี่ยนแปลงแล้ว
การบังคับใช้ ABI/API
ในการบังคับใช้ ABI/API ของไลบรารีที่ใช้ร่วมกันของ VNDK และ LLNDK จะต้องตรวจสอบการอ้างอิง ABI ใน ${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/(v)ndk/
ในการสร้างข้อมูลอ้างอิงเหล่านี้ ให้รันคำสั่งต่อไปนี้:
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py
หลังจากสร้างข้อมูลอ้างอิง การเปลี่ยนแปลงใดๆ ที่ทำกับซอร์สโค้ดที่ส่งผลให้เกิดการเปลี่ยนแปลง ABI/API ที่เข้ากันไม่ได้ในไลบรารี VNDK หรือ LLNDK จะส่งผลให้เกิดข้อผิดพลาดในการสร้าง
ในการอัพเดตการอ้างอิง ABI สำหรับไลบรารีหลักของ VNDK ให้รันคำสั่งต่อไปนี้:
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l <lib1> -l <lib2>
ตัวอย่างเช่น ในการอัปเดตการอ้างอิง libbinder
ABI ให้เรียกใช้:
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l libbinder
เมื่อต้องการอัพเดตการอ้างอิง ABI สำหรับไลบรารี LLNDK เฉพาะ ให้รันคำสั่งต่อไปนี้:
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l <lib1> -l <lib2> --llndk
ตัวอย่างเช่น ในการอัพเดตการอ้างอิง libm
ABI ให้รัน:
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l libm --llndk