ความเสถียรของอินเทอร์เฟซแบบไบนารีของแอปพลิเคชัน (ABI) เป็นข้อกำหนดเบื้องต้นของ การอัปเดตเฉพาะเฟรมเวิร์กเท่านั้นเนื่องจากโมดูลของผู้ให้บริการอาจขึ้นอยู่กับผู้ให้บริการ ไลบรารีที่ใช้ร่วมกันของ Development Kit (VNDK) ที่อยู่ในพาร์ติชันระบบ ภายในรุ่น Android ไลบรารีที่แชร์ VNDK ที่สร้างใหม่จะต้อง ABI ใช้งานได้กับไลบรารีที่แชร์ของ VNDK ที่เผยแพร่ก่อนหน้านี้ ดังนั้นโมดูลของผู้ให้บริการ สามารถทำงานกับไลบรารีเหล่านั้นได้โดยไม่ต้องทำการคอมไพล์ซ้ำและไม่มีข้อผิดพลาดรันไทม์ ระหว่าง Android รุ่นต่างๆ นั้น ไลบรารี VNDK จะเปลี่ยนแปลงได้และไม่มี ABI การรับประกันราคา
Android 9 มีความเข้ากันได้กับ ABI เครื่องมือตรวจสอบ ABI ส่วนหัวตามที่อธิบายไว้ในส่วนต่อไปนี้
เกี่ยวกับการปฏิบัติตามข้อกำหนดของ VNDK และ ABI
VNDK เป็นชุดไลบรารีแบบจำกัดซึ่งโมดูลของผู้ให้บริการอาจลิงก์ด้วยและ ซึ่งทำให้มีอัปเดตเฉพาะเฟรมเวิร์กเท่านั้น การปฏิบัติตามข้อกำหนดของ ABI หมายถึง ไลบรารีที่ใช้ร่วมกันเวอร์ชันใหม่กว่าจะทำงานได้ตามปกติด้วย ซึ่งลิงก์แบบไดนามิก (เช่น เป็นเวอร์ชันเก่าของ )
เกี่ยวกับสัญลักษณ์ที่ส่งออก
สัญลักษณ์ที่ส่งออก (หรือเรียกอีกอย่างว่าสัญลักษณ์ส่วนกลาง) หมายถึง สัญลักษณ์ที่เป็นไปตามทุกข้อต่อไปนี้
- ส่งออกโดยส่วนหัวสาธารณะของไลบรารีที่ใช้ร่วมกัน
- ปรากฏในตาราง
.dynsym
ของไฟล์.so
ที่สอดคล้องกับไลบรารีที่ใช้ร่วมกัน - มีการเชื่อมโยง WEAK หรือการเชื่อมโยงทั่วโลก
- ระดับการแชร์เป็น "ค่าเริ่มต้น" หรือ "ป้องกัน"
- ดัชนีส่วนไม่อยู่ในเกณฑ์
- ประเภทอาจเป็น 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
ต้องมีการปฏิบัติตามข้อกำหนดของ 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/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 ของ 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
อ้างอิงเพื่อสร้างรายงานความแตกต่าง ที่สรุปความแตกต่างใน ABI ของห้องสมุด 2 แห่ง
วันที่รูปที่ 3 การสร้างรายงานความแตกต่าง
ส่วนหัว Abi-Dumper
เครื่องมือ header-abi-dumper
จะแยกวิเคราะห์ไฟล์ต้นฉบับ C/C++ และดัมพ์
ABI ที่อนุมานจากไฟล์ต้นฉบับนั้นลงในไฟล์ตัวกลาง บิลด์
ระบบจะเรียกใช้ header-abi-dumper
ในไฟล์ต้นฉบับที่คอมไพล์ทั้งหมดในขณะที่
การสร้างไลบรารีที่มีไฟล์ต้นฉบับจากทรานซิทีฟ
ทรัพยากร Dependency
อินพุต |
|
---|---|
เอาต์พุต | ไฟล์ที่อธิบาย ABI ของไฟล์ต้นฉบับ (เช่น
foo.sdump เป็นตัวแทนของ ABI ของ 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
แสดงฟังก์ชันที่ส่งออกโดยส่วนหัวสาธารณะ และยังมีข้อมูลเกี่ยวกับชื่อที่เปลี่ยนแปลงของฟังก์ชัน ประเภทการแสดงผล ประเภทของพารามิเตอร์ ตัวระบุการเข้าถึง และแอตทริบิวต์อื่นๆ
ส่วนหัว-abi-linker
เครื่องมือ header-abi-linker
จะดำเนินการกับไฟล์กลางที่สร้างขึ้น
header-abi-dumper
เป็นอินพุตแล้วลิงก์ไฟล์เหล่านี้:
อินพุต |
|
---|---|
เอาต์พุต | ไฟล์ที่อธิบาย ABI ของไลบรารีที่ใช้ร่วมกัน (เช่น
libfoo.so.lsdump เป็นตัวแทนของ ABI ของ libfoo )
|
เครื่องมือจะรวมกราฟประเภทในไฟล์กลางทั้งหมดที่ให้มา
โดยพิจารณาจากคำนิยามเดียว (ประเภทที่ผู้ใช้กำหนดใน
หน่วยการแปลที่มีชื่อที่สมบูรณ์เหมือนกัน อาจมีความหมาย
แตกต่างกัน) แตกต่างกันในแต่ละหน่วยการแปล จากนั้นเครื่องมือจะแยกวิเคราะห์
สคริปต์เวอร์ชันหรือตาราง .dynsym
ของไลบรารีที่ใช้ร่วมกัน
(.so
) เพื่อสร้างรายการสัญลักษณ์ที่ส่งออก
ตัวอย่างเช่น libfoo
ประกอบด้วย foo.cpp
และ
bar.cpp
สามารถเรียกใช้ header-abi-linker
ไปยัง
สร้างไฟล์ Dump ของ 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
ส่วนหัว-abi-diff
เครื่องมือ header-abi-diff
จะเปรียบเทียบไฟล์ .lsdump
2 ไฟล์
เป็นตัวแทน ABI ของห้องสมุด 2 แห่ง และสร้างรายงานความแตกต่างที่ระบุถึง
ความแตกต่างระหว่าง ABI ทั้ง 2 ประเภท
อินพุต |
|
---|---|
เอาต์พุต | รายงานความแตกต่างที่ระบุความแตกต่างใน ABI ที่ทั้งสองนำเสนอ เปรียบเทียบไลบรารีที่ใช้ร่วมกัน |
ไฟล์ความแตกต่างของ ABI อยู่ใน protobuf ในรูปแบบข้อความ รูปแบบอาจมีการเปลี่ยนแปลง ในรุ่นต่อๆ ไป
ตัวอย่างเช่น คุณมี 2 เวอร์ชัน
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 *
(ตัด 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