ความเสถียรของ Application Binary Interface (ABI) เป็นข้อกำหนดเบื้องต้นของการอัปเดตเฉพาะเฟรมเวิร์ก เนื่องจากโมดูลของผู้ให้บริการอาจขึ้นอยู่กับไลบรารีที่แชร์ของ Vendor Native Development Kit (VNDK) ซึ่งอยู่ในพาร์ติชันระบบ ในรุ่น Android ไลบรารีที่ใช้ร่วมกันของ VNDK ที่สร้างขึ้นใหม่ต้อง เข้ากันได้กับ ABI ของไลบรารีที่ใช้ร่วมกันของ VNDK ที่เผยแพร่ก่อนหน้านี้ เพื่อให้โมดูลของผู้ให้บริการ ทำงานกับไลบรารีเหล่านั้นได้โดยไม่ต้องคอมไพล์ใหม่และไม่มีข้อผิดพลาดรันไทม์ ไลบรารี VNDK สามารถเปลี่ยนแปลงได้ระหว่างการเปิดตัว Android และไม่มีการรับประกัน ABI
Android 9 มีเครื่องมือตรวจสอบ ABI ส่วนหัวตามที่อธิบายไว้ในส่วนต่อไปนี้ เพื่อช่วยให้มั่นใจว่า ABI เข้ากันได้
เกี่ยวกับ VNDK และการปฏิบัติตามข้อกำหนด ABI
VNDK เป็นชุดไลบรารีที่จำกัดซึ่งโมดูลของผู้ให้บริการอาจลิงก์ไปถึง และ ซึ่งช่วยให้มีการอัปเดตเฉพาะเฟรมเวิร์ก การปฏิบัติตามข้อกำหนด ABI หมายถึงความสามารถของไลบรารีที่ใช้ร่วมกันเวอร์ชันใหม่ในการทำงานตามที่คาดไว้กับโมดูลที่ลิงก์แบบไดนามิกกับไลบรารีนั้น (กล่าวคือ ทำงานเหมือนกับไลบรารีเวอร์ชันเก่า)
เกี่ยวกับสัญลักษณ์ที่ส่งออก
สัญลักษณ์ที่ส่งออก (หรือที่เรียกว่าสัญลักษณ์ส่วนกลาง) หมายถึงสัญลักษณ์ที่มีคุณสมบัติตรงตามเงื่อนไขต่อไปนี้ทั้งหมด
- ส่งออกจากส่วนหัวสาธารณะของไลบรารีที่ใช้ร่วมกัน
- ปรากฏใน
.dynsym
ตารางของไฟล์.so
ที่สอดคล้องกับไลบรารีที่ใช้ร่วมกัน - มีการเชื่อมโยง WEAK หรือ GLOBAL
- ระดับการแชร์เป็นค่าเริ่มต้นหรือได้รับการป้องกัน
- ดัชนีส่วนไม่ใช่ UNDEFINED
- ประเภทคือ 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 : [ "exported" ], } |
ตาราง .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 ที่ 2 โดย bar_t *
bar_t จะส่งออกผ่าน foo_exported.h
bar_t มีสมาชิก mfoo ประเภท
foo_t ซึ่งส่งออกผ่าน foo_exported.h
ซึ่งส่งผลให้มีการส่งออกประเภทอื่นๆ เพิ่มเติม ดังนี้
แต่เข้าถึง foo_private_t ไม่ได้เนื่องจากไม่ได้
ส่งออกผ่าน foo_exported.h (foo_private_t *
เป็นแบบทึบแสง จึงอนุญาตให้ทำการเปลี่ยนแปลงกับ foo_private_t )
|
คำอธิบายที่คล้ายกันนี้ใช้ได้กับประเภทที่เข้าถึงได้ผ่านตัวระบุคลาสฐาน และพารามิเตอร์เทมเพลตด้วย
ตรวจสอบการปฏิบัติตามข้อกำหนด ABI
ต้องตรวจสอบว่าไลบรารีที่ทำเครื่องหมาย vendor_available: true
และ vndk.enabled: true
ในไฟล์ Android.bp
ที่เกี่ยวข้องเป็นไปตาม ABI เช่น
cc_library { name: "libvndk_example", vendor_available: true, vndk: { enabled: true, } }
สําหรับประเภทข้อมูลที่เข้าถึงได้โดยตรงหรือโดยอ้อมด้วยฟังก์ชันที่ส่งออก การเปลี่ยนแปลงต่อไปนี้ในไลบรารีจะถือเป็นการเปลี่ยนแปลง ABI
ประเภทข้อมูล | คำอธิบาย |
---|---|
โครงสร้างและชั้นเรียน |
|
สหภาพ |
|
การแจงนับ |
|
สัญลักษณ์ทั่วโลก |
|
* ฟังก์ชันสมาชิกทั้งแบบสาธารณะและแบบส่วนตัวต้อง ไม่เปลี่ยนแปลงหรือนำออกเนื่องจากฟังก์ชันอินไลน์สาธารณะสามารถอ้างอิงถึง ฟังก์ชันสมาชิกแบบส่วนตัวได้ การอ้างอิงสัญลักษณ์ไปยังฟังก์ชันสมาชิกส่วนตัวจะ เก็บไว้ในไบนารีของผู้เรียกได้ การเปลี่ยนแปลงหรือการนำฟังก์ชันสมาชิกส่วนตัว ออกจากไลบรารีที่แชร์อาจส่งผลให้ไบนารีไม่เข้ากันแบบย้อนหลัง
** ออฟเซ็ตไปยังสมาชิกข้อมูลสาธารณะหรือส่วนตัวต้องไม่ เปลี่ยนแปลงเนื่องจากฟังก์ชันอินไลน์สามารถอ้างอิงสมาชิกข้อมูลเหล่านี้ใน เนื้อหาของฟังก์ชันได้ การเปลี่ยนออฟเซ็ตของสมาชิกข้อมูลอาจส่งผลให้ไบนารีไม่เข้ากันแบบย้อนหลัง
*** แม้ว่าการดำเนินการเหล่านี้จะไม่เปลี่ยนเลย์เอาต์หน่วยความจำ ของประเภท แต่ก็มีความแตกต่างเชิงความหมายที่อาจทำให้ไลบรารีทำงานไม่เป็นไปตาม ที่คาดไว้
ใช้เครื่องมือการปฏิบัติตามข้อกำหนด ABI
เมื่อสร้างไลบรารี VNDK ระบบจะเปรียบเทียบ ABI ของไลบรารีกับ การอ้างอิง ABI ที่เกี่ยวข้องสำหรับ VNDK เวอร์ชันที่กำลังสร้าง การอ้างอิง การดัมพ์ ABI อยู่ในตำแหน่งต่อไปนี้
${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/<PLATFORM_VNDK_VERSION>/<BINDER_BITNESS>/<ARCH>/source-based
เช่น ในการสร้าง libfoo
สำหรับ x86 ที่ API ระดับ 27
ระบบจะเปรียบเทียบ ABI ที่อนุมานของ libfoo
กับข้อมูลอ้างอิงที่
${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/27/64/x86/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 ----
สร้างการตรวจสอบ ABI ของไลบรารี VNDK
เมื่อสร้างไลบรารี VNDK
header-abi-dumper
จะประมวลผลไฟล์ต้นฉบับที่คอมไพล์เพื่อ สร้างไลบรารี VNDK (ไฟล์ต้นฉบับของไลบรารีเองรวมถึงไฟล์ต้นฉบับ ที่สืบทอดผ่านทรัพยากร Dependency แบบคงที่แบบทรานซิทีฟ) เพื่อสร้างไฟล์.sdump
ที่สอดคล้องกับแต่ละแหล่งที่มา
รูปที่ 1 สร้างไฟล์ .sdump
header-abi-linker
จากนั้นจะประมวลผลไฟล์.sdump
(โดยใช้สคริปต์เวอร์ชันที่ระบุไว้หรือไฟล์.so
ที่สอดคล้องกับไลบรารีที่ใช้ร่วมกัน) เพื่อสร้างไฟล์.lsdump
ที่บันทึกข้อมูล ABI ทั้งหมดที่สอดคล้องกับไลบรารีที่ใช้ร่วมกัน
รูปที่ 2 การสร้างไฟล์ .lsdump
header-abi-diff
จะเปรียบเทียบไฟล์.lsdump
กับไฟล์อ้างอิง.lsdump
เพื่อสร้างรายงาน Diff ที่ระบุความแตกต่างใน ABI ของไลบรารีทั้ง 2
รูปที่ 3 การสร้างรายงานความแตกต่าง
header-abi-dumper
header-abi-dumper
เครื่องมือจะแยกวิเคราะห์ไฟล์ต้นฉบับ C/C++ และทิ้ง
ABI ที่อนุมานจากไฟล์ต้นฉบับนั้นลงในไฟล์กลาง ระบบบิลด์จะเรียกใช้ header-abi-dumper
ในไฟล์ต้นฉบับที่คอมไพล์ทั้งหมด พร้อมทั้งสร้างไลบรารีที่มีไฟล์ต้นฉบับจากทรัพยากร Dependency แบบทรานซิทีฟ
อินพุต |
|
---|---|
เอาต์พุต | ไฟล์ที่อธิบาย ABI ของไฟล์ต้นฉบับ (เช่น
ABI ของ foo.sdump represents foo.cpp )
|
ปัจจุบันไฟล์ .sdump
อยู่ในรูปแบบ JSON ซึ่งไม่รับประกันว่าจะมีความเสถียรในรุ่นต่อๆ ไป ดังนั้น .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 -- -I exported -x c++
คำสั่งนี้จะบอก header-abi-dumper
ให้แยกวิเคราะห์
foo.cpp
ด้วยแฟล็กคอมไพเลอร์ที่อยู่หลัง --
และ
ปล่อยข้อมูล ABI ที่ส่งออกจากส่วนหัวสาธารณะในไดเรกทอรี exported
ต่อไปนี้คือ
foo.sdump
ที่สร้างโดย
header-abi-dumper
{ "array_types" : [], "builtin_types" : [ { "alignment" : 4, "is_integral" : true, "linker_set_key" : "_ZTIi", "name" : "int", "referenced_type" : "_ZTIi", "self_type" : "_ZTIi", "size" : 4 } ], "elf_functions" : [], "elf_objects" : [], "enum_types" : [], "function_types" : [], "functions" : [ { "function_name" : "FooBad", "linker_set_key" : "_Z6FooBadiP3foo", "parameters" : [ { "referenced_type" : "_ZTIi" }, { "referenced_type" : "_ZTIP3foo" } ], "return_type" : "_ZTI3bar", "source_file" : "exported/foo_exported.h" } ], "global_vars" : [], "lvalue_reference_types" : [], "pointer_types" : [ { "alignment" : 8, "linker_set_key" : "_ZTIP11foo_private", "name" : "foo_private *", "referenced_type" : "_ZTI11foo_private", "self_type" : "_ZTIP11foo_private", "size" : 8, "source_file" : "exported/foo_exported.h" }, { "alignment" : 8, "linker_set_key" : "_ZTIP3foo", "name" : "foo *", "referenced_type" : "_ZTI3foo", "self_type" : "_ZTIP3foo", "size" : 8, "source_file" : "exported/foo_exported.h" }, { "alignment" : 8, "linker_set_key" : "_ZTIPi", "name" : "int *", "referenced_type" : "_ZTIi", "self_type" : "_ZTIPi", "size" : 8, "source_file" : "exported/foo_exported.h" } ], "qualified_types" : [], "record_types" : [ { "alignment" : 8, "fields" : [ { "field_name" : "mfoo", "referenced_type" : "_ZTI3foo" } ], "linker_set_key" : "_ZTI3bar", "name" : "bar", "referenced_type" : "_ZTI3bar", "self_type" : "_ZTI3bar", "size" : 24, "source_file" : "exported/foo_exported.h" }, { "alignment" : 8, "fields" : [ { "field_name" : "m1", "referenced_type" : "_ZTIi" }, { "field_name" : "m2", "field_offset" : 64, "referenced_type" : "_ZTIPi" }, { "field_name" : "mPfoo", "field_offset" : 128, "referenced_type" : "_ZTIP11foo_private" } ], "linker_set_key" : "_ZTI3foo", "name" : "foo", "referenced_type" : "_ZTI3foo", "self_type" : "_ZTI3foo", "size" : 24, "source_file" : "exported/foo_exported.h" } ], "rvalue_reference_types" : [] }
foo.sdump
มีข้อมูล ABI ที่ส่งออกจากไฟล์ต้นฉบับ
foo.cpp
และส่วนหัวสาธารณะ เช่น
record_types
. อ้างอิงถึงโครงสร้าง ยูเนียน หรือคลาสที่กำหนด ในส่วนหัวสาธารณะ ประเภทบันทึกแต่ละประเภทจะมีข้อมูลเกี่ยวกับฟิลด์ ขนาด ตัวระบุการเข้าถึง ไฟล์ส่วนหัวที่กำหนดไว้ และแอตทริบิวต์อื่นๆpointer_types
อ้างอิงประเภทพอยน์เตอร์โดยตรง/โดยอ้อม ซึ่งบันทึก/ฟังก์ชันที่ส่งออกอ้างอิงในส่วนหัวสาธารณะ พร้อมด้วย ประเภทที่พอยน์เตอร์ชี้ไป (ผ่านฟิลด์referenced_type
ในtype_info
) ระบบจะบันทึกข้อมูลที่คล้ายกันในไฟล์.sdump
สำหรับประเภทที่มีคุณสมบัติ ประเภท C/C++ ในตัว ประเภทอาร์เรย์ และประเภทการอ้างอิง lvalue และ rvalue ข้อมูลดังกล่าวช่วยให้ การเปรียบเทียบแบบเรียกซ้ำfunctions
แสดงฟังก์ชันที่ส่งออกโดยส่วนหัวสาธารณะ นอกจากนี้ ยังมีข้อมูลเกี่ยวกับชื่อที่ดัดแปลงของฟังก์ชัน ประเภทการคืนค่า ประเภทของพารามิเตอร์ ตัวระบุการเข้าถึง และแอตทริบิวต์อื่นๆ
header-abi-linker
header-abi-linker
จะใช้ไฟล์กลางที่ header-abi-dumper
สร้างขึ้นเป็นอินพุต แล้วลิงก์ไฟล์เหล่านั้น
อินพุต |
|
---|---|
เอาต์พุต | ไฟล์ที่อธิบาย ABI ของไลบรารีที่ใช้ร่วมกัน (เช่น
libfoo.so.lsdump แสดงถึง ABI ของ libfoo )
|
เครื่องมือจะผสานกราฟประเภทในไฟล์กลางทั้งหมดที่ได้รับ
โดยคำนึงถึงความแตกต่างของคำจำกัดความเดียว (ประเภทที่ผู้ใช้กำหนดในหน่วยการแปลต่างๆ ที่มีชื่อที่ผ่านการรับรองแบบเต็มเดียวกันอาจมีความแตกต่างกันในเชิงความหมาย)
ในหน่วยการแปล จากนั้นเครื่องมือจะแยกวิเคราะห์ทั้ง
สคริปต์เวอร์ชันหรือ.dynsym
ตารางของไลบรารีที่ใช้ร่วมกัน
(ไฟล์ .so
) เพื่อสร้างรายการสัญลักษณ์ที่ส่งออก
เช่น libfoo
ประกอบด้วย foo.cpp
และ bar.cpp
header-abi-linker
สามารถเรียกใช้เพื่อสร้างการทิ้ง ABI ที่ลิงก์สมบูรณ์ของ libfoo
ได้ดังนี้
header-abi-linker -I exported foo.sdump bar.sdump \ -o libfoo.so.lsdump \ -so libfoo.so \ -arch arm64 -api current
ตัวอย่างเอาต์พุตคำสั่งใน libfoo.so.lsdump
{ "array_types" : [], "builtin_types" : [ { "alignment" : 1, "is_integral" : true, "is_unsigned" : true, "linker_set_key" : "_ZTIb", "name" : "bool", "referenced_type" : "_ZTIb", "self_type" : "_ZTIb", "size" : 1 }, { "alignment" : 4, "is_integral" : true, "linker_set_key" : "_ZTIi", "name" : "int", "referenced_type" : "_ZTIi", "self_type" : "_ZTIi", "size" : 4 } ], "elf_functions" : [ { "name" : "_Z3FooiP3bar" }, { "name" : "_Z6FooBadiP3foo" } ], "elf_objects" : [], "enum_types" : [], "function_types" : [], "functions" : [ { "function_name" : "Foo", "linker_set_key" : "_Z3FooiP3bar", "parameters" : [ { "referenced_type" : "_ZTIi" }, { "referenced_type" : "_ZTIP3bar" } ], "return_type" : "_ZTIb", "source_file" : "exported/foo_exported.h" }, { "function_name" : "FooBad", "linker_set_key" : "_Z6FooBadiP3foo", "parameters" : [ { "referenced_type" : "_ZTIi" }, { "referenced_type" : "_ZTIP3foo" } ], "return_type" : "_ZTI3bar", "source_file" : "exported/foo_exported.h" } ], "global_vars" : [], "lvalue_reference_types" : [], "pointer_types" : [ { "alignment" : 8, "linker_set_key" : "_ZTIP11foo_private", "name" : "foo_private *", "referenced_type" : "_ZTI11foo_private", "self_type" : "_ZTIP11foo_private", "size" : 8, "source_file" : "exported/foo_exported.h" }, { "alignment" : 8, "linker_set_key" : "_ZTIP3bar", "name" : "bar *", "referenced_type" : "_ZTI3bar", "self_type" : "_ZTIP3bar", "size" : 8, "source_file" : "exported/foo_exported.h" }, { "alignment" : 8, "linker_set_key" : "_ZTIP3foo", "name" : "foo *", "referenced_type" : "_ZTI3foo", "self_type" : "_ZTIP3foo", "size" : 8, "source_file" : "exported/foo_exported.h" }, { "alignment" : 8, "linker_set_key" : "_ZTIPi", "name" : "int *", "referenced_type" : "_ZTIi", "self_type" : "_ZTIPi", "size" : 8, "source_file" : "exported/foo_exported.h" } ], "qualified_types" : [], "record_types" : [ { "alignment" : 8, "fields" : [ { "field_name" : "mfoo", "referenced_type" : "_ZTI3foo" } ], "linker_set_key" : "_ZTI3bar", "name" : "bar", "referenced_type" : "_ZTI3bar", "self_type" : "_ZTI3bar", "size" : 24, "source_file" : "exported/foo_exported.h" }, { "alignment" : 8, "fields" : [ { "field_name" : "m1", "referenced_type" : "_ZTIi" }, { "field_name" : "m2", "field_offset" : 64, "referenced_type" : "_ZTIPi" }, { "field_name" : "mPfoo", "field_offset" : 128, "referenced_type" : "_ZTIP11foo_private" } ], "linker_set_key" : "_ZTI3foo", "name" : "foo", "referenced_type" : "_ZTI3foo", "self_type" : "_ZTI3foo", "size" : 24, "source_file" : "exported/foo_exported.h" } ], "rvalue_reference_types" : [] }
เครื่องมือ header-abi-linker
- ลิงก์ไฟล์
.sdump
ที่ระบุไว้ (foo.sdump
และbar.sdump
) โดยกรองข้อมูล ABI ที่ไม่มีใน ส่วนหัวที่อยู่ในไดเรกทอรีexported
- แยกวิเคราะห์
libfoo.so
และรวบรวมข้อมูลเกี่ยวกับสัญลักษณ์ ที่ไลบรารีส่งออกผ่านตาราง.dynsym
- เพิ่ม
_Z3FooiP3bar
และ_Z6FooBadiP3foo
libfoo.so.lsdump
คือการดัมพ์ ABI ที่สร้างขึ้นสุดท้ายของ
libfoo.so
header-abi-diff
เครื่องมือ header-abi-diff
จะเปรียบเทียบไฟล์ .lsdump
2 ไฟล์
ซึ่งแสดงถึง ABI ของไลบรารี 2 รายการ และสร้างรายงาน Diff ที่ระบุ
ความแตกต่างระหว่าง ABI ทั้ง 2 รายการ
อินพุต |
|
---|---|
เอาต์พุต | รายงาน Diff ที่ระบุความแตกต่างใน ABI ที่ไลบรารีที่ใช้ร่วมกัน 2 รายการ ที่เปรียบเทียบกัน |
ไฟล์ ABI diff อยู่ใน รูปแบบข้อความ protobuf รูปแบบอาจมีการเปลี่ยนแปลง ในรุ่นต่อๆ ไป
เช่น คุณมี libfoo
2 เวอร์ชัน ได้แก่ libfoo_old.so
และ libfoo_new.so
ใน libfoo_new.so
ใน
bar_t
คุณเปลี่ยนประเภทของ mfoo
จาก
foo_t
เป็น foo_t *
เนื่องจาก bar_t
เป็นประเภทที่เข้าถึงได้ header-abi-diff
จึงควรแจ้งว่าการเปลี่ยนแปลงนี้เป็นการเปลี่ยนแปลงที่ทำให้ ABI ใช้ไม่ได้
วิธีเรียกใช้ 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 *
(นำ typedef ทั้งหมดออก)
ฟิลด์ type_stack
ระบุวิธีที่ header-abi-diff
เข้าถึงประเภทที่เปลี่ยนแปลง (bar
) ฟิลด์นี้อาจ
ตีความได้ว่า Foo
เป็นฟังก์ชันที่ส่งออกซึ่งรับ
bar *
เป็นพารามิเตอร์ที่ชี้ไปยัง bar
ซึ่งส่งออกและ
เปลี่ยนแปลง
บังคับใช้ ABI และ API
หากต้องการบังคับใช้ ABI และ API ของไลบรารีที่ใช้ร่วมกันของ VNDK ต้องมีการเช็คอินการอ้างอิง ABI ไปยัง ${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/
หากต้องการสร้างข้อมูลอ้างอิงเหล่านี้ ให้เรียกใช้คำสั่งต่อไปนี้
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py
หลังจากสร้างข้อมูลอ้างอิงแล้ว การเปลี่ยนแปลงใดๆ ที่ทำกับซอร์สโค้ดซึ่งส่งผลให้เกิดการเปลี่ยนแปลง ABI/API ที่ไม่เข้ากันในไลบรารี VNDK จะทำให้เกิดข้อผิดพลาดในการสร้าง
หากต้องการอัปเดตการอ้างอิง ABI สำหรับไลบรารีที่เฉพาะเจาะจง ให้เรียกใช้คำสั่งต่อไปนี้
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l <lib1> -l <lib2>
เช่น หากต้องการอัปเดตการอ้างอิง ABI ของ libbinder
ให้เรียกใช้คำสั่งต่อไปนี้
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l libbinder