सिर्फ़ फ़्रेमवर्क अपडेट के लिए, ऐप्लिकेशन बाइनरी इंटरफ़ेस (एबीआई) का स्टेबल होना ज़रूरी है. ऐसा इसलिए, क्योंकि वेंडर मॉड्यूल, सिस्टम पार्टिशन में मौजूद वेंडर नेटिव डेवलपमेंट किट (वीएनडीके) की शेयर की गई लाइब्रेरी पर निर्भर हो सकते हैं. Android के किसी वर्शन में, नई वीएनडीके शेयर की गई लाइब्रेरी, पहले रिलीज़ की गई वीएनडीके शेयर की गई लाइब्रेरी के साथ एबीआई के हिसाब से काम करनी चाहिए. इससे वेंडर मॉड्यूल, उन लाइब्रेरी के साथ बिना फिर से कंपाइल किए और बिना रनटाइम की गड़बड़ियों के काम कर सकते हैं. Android के रिलीज़ के बीच, VNDK लाइब्रेरी बदली जा सकती हैं. साथ ही, एबीआई की कोई गारंटी नहीं होती.
एबीआई के साथ काम करने की सुविधा को पक्का करने के लिए, Android 9 में हेडर एबीआई की जांच करने वाला टूल शामिल है. इसके बारे में यहां बताया गया है.
वीएनडीके और एबीआई के नियमों का पालन करने के बारे में जानकारी
वीएनडीके, लाइब्रेरी का एक ऐसा सेट है जिस पर पाबंदी लगी होती है. वेंडर मॉड्यूल, इससे लिंक हो सकते हैं. साथ ही, इससे सिर्फ़ फ़्रेमवर्क को अपडेट किया जा सकता है. एबीआई के मुताबिक होना का मतलब है कि शेयर की गई लाइब्रेरी का नया वर्शन, उससे डाइनैमिक तरीके से लिंक किए गए मॉड्यूल के साथ उम्मीद के मुताबिक काम कर सकता है. इसका मतलब है कि यह लाइब्रेरी के पुराने वर्शन की तरह काम करता है.
एक्सपोर्ट किए गए सिंबल के बारे में जानकारी
एक्सपोर्ट किया गया सिंबल (इसे ग्लोबल सिंबल भी कहा जाता है) उस सिंबल को कहते हैं जो इन सभी शर्तों को पूरा करता है:
- इन्हें शेयर की गई लाइब्रेरी के पब्लिक हेडर से एक्सपोर्ट किया जाता है.
- शेयर की गई लाइब्रेरी से जुड़ी
.so
फ़ाइल की.dynsym
टेबल में दिखता है. - इसमें WEAK या GLOBAL बाइंडिंग है.
- विज़िबिलिटी DEFAULT या PROTECTED पर सेट हो.
- सेक्शन इंडेक्स 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 में बदलाव करने की अनुमति है.)
|
इसी तरह का ब्यौरा, बेस क्लास स्पेसिफ़ायर और टेंप्लेट पैरामीटर के ज़रिए ऐक्सेस किए जा सकने वाले टाइप के लिए भी दिया जा सकता है.
पक्का करें कि एबीआई का पालन किया गया हो
Android.bp
फ़ाइलों में, vendor_available: true
और vndk.enabled: true
के तौर पर मार्क की गई लाइब्रेरी के लिए, ABI का पालन करना ज़रूरी है. उदाहरण के लिए:
cc_library { name: "libvndk_example", vendor_available: true, vndk: { enabled: true, } }
एक्सपोर्ट किए गए फ़ंक्शन से सीधे या किसी दूसरे तरीके से ऐक्सेस किए जा सकने वाले डेटा टाइप के लिए, लाइब्रेरी में किए गए इन बदलावों को ABI-ब्रेकिंग के तौर पर क्लासिफ़ाई किया जाता है:
डेटा टाइप | ब्यौरा |
---|---|
स्ट्रक्चर और क्लास |
|
यूनियन |
|
इन्यूमरेशन |
|
ग्लोबल सिंबल |
|
* सार्वजनिक और निजी, दोनों तरह के सदस्य फ़ंक्शन में बदलाव नहीं किया जाना चाहिए और न ही उन्हें हटाया जाना चाहिए. ऐसा इसलिए, क्योंकि सार्वजनिक इनलाइन फ़ंक्शन, निजी सदस्य फ़ंक्शन का रेफ़रंस दे सकते हैं. निजी सदस्य फ़ंक्शन के सिंबल रेफ़रंस, कॉलर बाइनरी में रखे जा सकते हैं. शेयर की गई लाइब्रेरी से, सदस्यों के लिए उपलब्ध फ़ंक्शन में बदलाव करने या उन्हें हटाने से, बाइनरी फ़ाइलें पहले की तरह काम नहीं करेंगी.
** सार्वजनिक या निजी डेटा सदस्यों के ऑफ़सेट में बदलाव नहीं किया जाना चाहिए, क्योंकि इनलाइन फ़ंक्शन, अपने फ़ंक्शन बॉडी में इन डेटा सदस्यों का रेफ़रंस दे सकते हैं. डेटा मेंबर ऑफ़सेट बदलने से, बाइनरी के पिछले वर्शन के साथ काम न करने वाली बाइनरी बन सकती हैं.
*** इनसे टाइप के मेमोरी लेआउट में कोई बदलाव नहीं होता है. हालांकि, सिमैंटिक अंतर होते हैं. इनकी वजह से, लाइब्रेरी उम्मीद के मुताबिक काम नहीं कर सकती हैं.
एबीआई के मुताबिक काम करने वाले टूल का इस्तेमाल करना
जब कोई वीएनडीके लाइब्रेरी बनाई जाती है, तब लाइब्रेरी के एबीआई की तुलना, बनाए जा रहे वीएनडीके के वर्शन के एबीआई रेफ़रंस से की जाती है. रेफ़रंस एबीआई डंप यहां मौजूद हैं:
${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/<PLATFORM_VNDK_VERSION>/<BINDER_BITNESS>/<ARCH>/source-based
उदाहरण के लिए, एपीआई लेवल 27 पर x86 के लिए libfoo
बनाते समय,
libfoo
के अनुमानित ABI की तुलना, यहां दिए गए रेफ़रंस से की जाती है:
${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/27/64/x86/source-based/libfoo.so.lsdump
एबीआई के काम न करने की गड़बड़ी
एबीआई में बदलाव होने पर, बिल्ड लॉग में चेतावनियां दिखती हैं. इनमें चेतावनी का टाइप और abi-diff रिपोर्ट का पाथ होता है. उदाहरण के लिए, अगर libbinder
के ABI में कोई ऐसा बदलाव किया गया है जो काम नहीं करता है, तो बिल्ड सिस्टम गड़बड़ी का मैसेज दिखाता है. यह मैसेज कुछ इस तरह का होता है:
***************************************************** 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 ----
वीएनडीके लाइब्रेरी के एबीआई की जांच करना
वीएनडीके लाइब्रेरी बनाने पर:
header-abi-dumper
, वीएनडीके लाइब्रेरी बनाने के लिए कंपाइल की गई सोर्स फ़ाइलों को प्रोसेस करता है. इनमें लाइब्रेरी की अपनी सोर्स फ़ाइलें और स्टैटिक ट्रांज़िटिव डिपेंडेंसी से इनहेरिट की गई सोर्स फ़ाइलें शामिल होती हैं. इससे,.sdump
फ़ाइलें जनरेट होती हैं, जो हर सोर्स से जुड़ी होती हैं.
पहली इमेज. .sdump
फ़ाइलें बनाई जा रही हैं- इसके बाद,
header-abi-linker
,.sdump
फ़ाइलों को प्रोसेस करता है. इसके लिए, वह या तो उसे दी गई वर्शन स्क्रिप्ट का इस्तेमाल करता है या शेयर की गई लाइब्रेरी से जुड़ी.so
फ़ाइल का इस्तेमाल करता है. इससे.lsdump
फ़ाइल बनती है. इस फ़ाइल में, शेयर की गई लाइब्रेरी से जुड़ी सभी एबीआई जानकारी लॉग होती है.
दूसरी इमेज. .lsdump
फ़ाइल बनाई जा रही है header-abi-diff
,.lsdump
फ़ाइल की तुलना, पहचान वाली.lsdump
फ़ाइल से करता है. इससे एक अंतर रिपोर्ट जनरेट होती है. इस रिपोर्ट में, दोनों लाइब्रेरी के एबीआई में मौजूद अंतर के बारे में बताया जाता है.
तीसरी इमेज. डिफ़ रिपोर्ट बनाना
header-abi-dumper
header-abi-dumper
टूल, C/C++ सोर्स फ़ाइल को पार्स करता है. साथ ही, उस सोर्स फ़ाइल से अनुमानित एबीआई को इंटरमीडिएट फ़ाइल में डंप करता है. बिल्ड सिस्टम, कंपाइल की गई सभी सोर्स फ़ाइलों पर header-abi-dumper
को चलाता है. साथ ही, यह एक ऐसी लाइब्रेरी भी बनाता है जिसमें ट्रांज़िटिव डिपेंडेंसी की सोर्स फ़ाइलें शामिल होती हैं.
इनपुट |
|
---|---|
आउटपुट | ऐसी फ़ाइल जिसमें सोर्स फ़ाइल के एबीआई के बारे में जानकारी होती है. उदाहरण के लिए, foo.sdump , 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
को पार्स करे. साथ ही, exported
डायरेक्ट्री में मौजूद सार्वजनिक हेडर से एक्सपोर्ट की गई एबीआई की जानकारी को दिखाए. यहां दिया गया जवाब, header-abi-dumper
ने जनरेट किया है. foo.sdump
{ "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
में सोर्स फ़ाइल foo.cpp
से एक्सपोर्ट की गई एबीआई की जानकारी और सार्वजनिक हेडर शामिल होते हैं. उदाहरण के लिए,
record_types
. सार्वजनिक हेडर में तय किए गए स्ट्रक्चर, यूनियन या क्लास देखें. हर रिकॉर्ड टाइप में, उसके फ़ील्ड, साइज़, ऐक्सेस स्पेसिफ़ायर, हेडर फ़ाइल, और अन्य एट्रिब्यूट के बारे में जानकारी होती है.pointer_types
. सार्वजनिक हेडर में एक्सपोर्ट किए गए रिकॉर्ड/फ़ंक्शन से सीधे/अप्रत्यक्ष तौर पर रेफ़र किए गए पॉइंटर टाइप देखें. साथ ही, पॉइंटर जिस टाइप की ओर इशारा करता है उसे देखें. इसके लिए,type_info
में मौजूदreferenced_type
फ़ील्ड का इस्तेमाल करें. इसी तरह की जानकारी,.sdump
फ़ाइल में लॉग की जाती है. यह जानकारी, क्वालिफ़ाइड टाइप, बिल्ट-इन C/C++ टाइप, ऐरे टाइप, और lvalue और rvalue रेफ़रंस टाइप के लिए होती है. इस तरह की जानकारी से, बार-बार होने वाले अंतर की पहचान की जा सकती है.functions
. यह सार्वजनिक हेडर से एक्सपोर्ट किए गए फ़ंक्शन दिखाता है. इनमें फ़ंक्शन के मैंगल किए गए नाम, रिटर्न टाइप, पैरामीटर के टाइप, ऐक्सेस स्पेसिफ़ायर, और अन्य एट्रिब्यूट के बारे में भी जानकारी होती है.
header-abi-linker
header-abi-linker
टूल, header-abi-dumper
से मिली इंटरमीडिएट फ़ाइलों को इनपुट के तौर पर लेता है. इसके बाद, उन फ़ाइलों को लिंक करता है:
इनपुट |
|
---|---|
आउटपुट | यह फ़ाइल, शेयर की गई लाइब्रेरी के एबीआई के बारे में बताती है. उदाहरण के लिए, libfoo.so.lsdump रिप्रेजेंट libfoo का एबीआई.
|
यह टूल, इसे दी गई सभी इंटरमीडिएट फ़ाइलों में टाइप ग्राफ़ को मर्ज करता है. साथ ही, यह अनुवाद इकाइयों के बीच एक-डेफ़िनिशन (एक ही पूरी तरह से क्वालिफ़ाइड नाम वाली अलग-अलग अनुवाद इकाइयों में उपयोगकर्ता के तय किए गए टाइप, सिमैंटिक तौर पर अलग हो सकते हैं) के अंतर को ध्यान में रखता है. इसके बाद, टूल एक्सपोर्ट किए गए सिंबल की सूची बनाने के लिए, वर्शन स्क्रिप्ट या शेयर की गई लाइब्रेरी की .dynsym
टेबल (.so
फ़ाइल) को पार्स करता है.
उदाहरण के लिए, libfoo
में foo.cpp
और bar.cpp
शामिल हैं. header-abi-linker
को इस तरह से कॉल किया जा सकता है, ताकि libfoo
का पूरा लिंक किया गया ABI डंप बनाया जा सके:
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
) को लिंक करती है. साथ ही, डायरेक्ट्रीexported
में मौजूद हेडर में मौजूद ABI की जानकारी को फ़िल्टर करती है. - यह कुकी
libfoo.so
को पार्स करती है. साथ ही, लाइब्रेरी की.dynsym
टेबल के ज़रिए एक्सपोर्ट किए गए सिंबल के बारे में जानकारी इकट्ठा करती है. _Z3FooiP3bar
और_Z6FooBadiP3foo
को जोड़ता है.
libfoo.so.lsdump
, libfoo.so
का जनरेट किया गया फ़ाइनल एबीआई डंप है.
header-abi-diff
header-abi-diff
टूल, दो .lsdump
फ़ाइलों की तुलना करता है. ये फ़ाइलें, दो लाइब्रेरी के ABI को दिखाती हैं. साथ ही, यह एक अंतर वाली रिपोर्ट जनरेट करता है. इस रिपोर्ट में, दोनों ABI के बीच के अंतर के बारे में बताया जाता है.
इनपुट |
|
---|---|
आउटपुट | डिफ़ रिपोर्ट, जिसमें तुलना की गई दो शेयर की गई लाइब्रेरी के एबीआई में अंतर बताया गया हो. |
एबीआई डिफ़ फ़ाइल, protobuf टेक्स्ट फ़ॉर्मैट में होती है. आने वाली रिलीज़ में, इस फ़ॉर्मैट में बदलाव हो सकता है.
उदाहरण के लिए, आपके पास libfoo
के दो वर्शन हैं: 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
में, libfoo
में हुए सभी एबीआई ब्रेकिंग बदलावों की रिपोर्ट शामिल होती है. record_type_diffs
मैसेज से पता चलता है कि किसी रिकॉर्ड में बदलाव किया गया है. इसमें उन बदलावों की सूची दी गई होती है जो काम नहीं करते. इनमें ये शामिल हैं:
- रिकॉर्ड का साइज़
24
बाइट से बदलकर8
बाइट हो गया है. mfoo
के फ़ील्ड टाइप कोfoo
से बदलकरfoo *
किया गया है. इसमें सभी टाइपडेफ़ हटा दिए गए हैं.
type_stack
फ़ील्ड से पता चलता है कि header-abi-diff
, bar
में कैसे पहुंचा. इस फ़ील्ड को इस तरह से समझा जा सकता है कि Foo
एक एक्सपोर्ट किया गया फ़ंक्शन है, जो bar *
को पैरामीटर के तौर पर लेता है. यह bar
की ओर इशारा करता है, जिसे एक्सपोर्ट किया गया था और जिसमें बदलाव किया गया था.
एबीआई और एपीआई लागू करना
वीएनडीके की शेयर की गई लाइब्रेरी के एबीआई और एपीआई को लागू करने के लिए, एबीआई रेफ़रंस को ${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/
में चेक इन करना ज़रूरी है.
इन रेफ़रंस को बनाने के लिए, यह कमांड चलाएं:
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py
रेफ़रंस बनाने के बाद, सोर्स कोड में किया गया कोई भी ऐसा बदलाव जिसकी वजह से वीएनडीके लाइब्रेरी में एबीआई/एपीआई में बदलाव होता है, अब बिल्ड से जुड़ी गड़बड़ी के तौर पर दिखता है.
कुछ लाइब्रेरी के लिए, ABI रेफ़रंस अपडेट करने के लिए, यह कमांड चलाएं:
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l <lib1> -l <lib2>
उदाहरण के लिए, libbinder
के एबीआई रेफ़रंस अपडेट करने के लिए, यह कमांड चलाएं:
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l libbinder