ความเสถียรของ 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
ที่สอดคล้องกับไลบรารีที่แบ่งใช้ - มีการเชื่อมโยง 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 ตัวที่สอง โดยวิธี 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-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 (ไฟล์ต้นฉบับของไลบรารีเองตลอดจนไฟล์ต้นฉบับที่สืบทอดผ่านการพึ่งพาสกรรมกริยาแบบคงที่) เพื่อสร้างไฟล์.sdump
ที่สอดคล้องกับแต่ละแหล่งรูปที่ 1 การสร้างไฟล์ .sdump
- จากนั้น
header-abi-linker
จะประมวลผลไฟล์.sdump
(โดยใช้สคริปต์เวอร์ชันที่จัดเตรียมไว้ให้หรือไฟล์.so
ที่สอดคล้องกับไลบรารีที่แบ่งใช้) เพื่อสร้างไฟล์.lsdump
ที่บันทึกข้อมูล ABI ทั้งหมดที่สอดคล้องกับไลบรารีที่แบ่งใช้รูปที่ 2 การสร้างไฟล์ .lsdump
-
header-abi-diff
จะเปรียบเทียบไฟล์.lsdump
กับไฟล์อ้างอิง.lsdump
เพื่อสร้างรายงานความแตกต่างที่สรุปความแตกต่างใน ABI ของทั้งสองไลบรารีรูปที่ 3 การสร้างรายงานความแตกต่าง
ส่วนหัว-abi-รถเท
เครื่องมือ header-abi-dumper
จะแยกวิเคราะห์ไฟล์ต้นฉบับ C/C++ และทิ้ง ABI ที่อนุมานจากไฟล์ต้นฉบับนั้นลงในไฟล์ระดับกลาง ระบบบิลด์รัน header-abi-dumper
บนไฟล์ต้นฉบับที่คอมไพล์ทั้งหมด ในขณะเดียวกันก็สร้างไลบรารีที่รวมไฟล์ต้นฉบับจากการพึ่งพาแบบสกรรมกริยา
อินพุต |
|
---|---|
เอาท์พุต | ไฟล์ที่อธิบาย 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
สามารถเรียกใช้เพื่อสร้างดัมพ์ 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
สองไฟล์ที่แสดงถึง ABI ของสองไลบรารี และสร้างรายงานที่แตกต่างที่ระบุความแตกต่างระหว่าง ABI ทั้งสอง
อินพุต |
|
---|---|
เอาท์พุต | รายงานที่แตกต่างที่ระบุความแตกต่างใน ABI ที่เสนอโดยไลบรารีที่แบ่งใช้ทั้งสองเมื่อเปรียบเทียบกัน |
ไฟล์ ABI diff อยู่ใน รูปแบบข้อความ protobuf รูปแบบอาจมีการเปลี่ยนแปลงในรุ่นต่อๆ ไป
ตัวอย่างเช่น คุณมี 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 การอ้างอิง 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>
ตัวอย่างเช่น หากต้องการอัพเดตการอ้างอิง libbinder
ABI ให้รัน:
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l libbinder