एबीआई स्थिरता

एप्लिकेशन बाइनरी इंटरफ़ेस (एबीआई) स्थिरता फ्रेमवर्क-केवल अपडेट की एक शर्त है क्योंकि विक्रेता मॉड्यूल सिस्टम विभाजन में रहने वाले विक्रेता मूल विकास किट (वीएनडीके) साझा पुस्तकालयों पर निर्भर हो सकते हैं। एंड्रॉइड रिलीज़ के भीतर, नव-निर्मित VNDK साझा लाइब्रेरीज़ को पहले रिलीज़ की गई VNDK साझा लाइब्रेरीज़ के लिए ABI-संगत होना चाहिए ताकि विक्रेता मॉड्यूल उन लाइब्रेरीज़ के साथ बिना पुनर्संकलन और रनटाइम त्रुटियों के काम कर सकें। एंड्रॉइड रिलीज़ के बीच, VNDK लाइब्रेरीज़ को बदला जा सकता है और कोई ABI गारंटी नहीं है।

एबीआई अनुकूलता सुनिश्चित करने में मदद के लिए, एंड्रॉइड 9 में एक हेडर एबीआई चेकर शामिल है, जैसा कि निम्नलिखित अनुभागों में बताया गया है।

वीएनडीके और एबीआई अनुपालन के बारे में

वीएनडीके पुस्तकालयों का एक प्रतिबंधात्मक सेट है जिसे विक्रेता मॉड्यूल लिंक कर सकते हैं और जो केवल फ्रेमवर्क अपडेट को सक्षम करते हैं। एबीआई अनुपालन एक साझा लाइब्रेरी के नए संस्करण की उस मॉड्यूल के साथ अपेक्षित रूप से काम करने की क्षमता को संदर्भित करता है जो गतिशील रूप से इससे जुड़ा हुआ है (यानी लाइब्रेरी के पुराने संस्करण के रूप में काम करता है)।

निर्यातित प्रतीकों के बारे में

एक निर्यातित प्रतीक (जिसे वैश्विक प्रतीक के रूप में भी जाना जाता है) एक ऐसे प्रतीक को संदर्भित करता है जो निम्नलिखित सभी को संतुष्ट करता है:

  • साझा लाइब्रेरी के सार्वजनिक शीर्षलेखों द्वारा निर्यात किया गया।
  • साझा लाइब्रेरी के अनुरूप .so फ़ाइल की .dynsym तालिका में दिखाई देता है।
  • कमजोर या वैश्विक बंधन है।
  • दृश्यता डिफ़ॉल्ट या संरक्षित है.
  • अनुभाग सूचकांक अपरिभाषित नहीं है.
  • प्रकार या तो FUNC या OBJECT है।

एक साझा लाइब्रेरी के सार्वजनिक हेडर को साझा लाइब्रेरी के अनुरूप मॉड्यूल की Android.bp परिभाषाओं में export_include_dirs , export_header_lib_headers , export_static_lib_headers , export_shared_lib_headers और export_generated_headers विशेषताओं के माध्यम से अन्य पुस्तकालयों/बाइनरिज़ के लिए उपलब्ध हेडर के रूप में परिभाषित किया गया है।

पहुंच योग्य प्रकारों के बारे में

पहुंच योग्य प्रकार कोई भी 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.बीपी
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 * दूसरे फू पैरामीटर का प्रकार। bar_t * के माध्यम से, bar_t foo_exported.h के माध्यम से निर्यात किया जाता है।

bar_t foo_t प्रकार का एक सदस्य mfoo शामिल है, जिसे foo_exported.h के माध्यम से निर्यात किया जाता है, जिसके परिणामस्वरूप अधिक प्रकार निर्यात किए जाते हैं:
  • int : m1 का प्रकार है।
  • int * : m2 का प्रकार है।
  • foo_private_t * : mPfoo का प्रकार है।

हालाँकि, foo_private_t पहुंच योग्य नहीं है क्योंकि इसे foo_exported.h के माध्यम से निर्यात नहीं किया जाता है। ( foo_private_t * अपारदर्शी है, इसलिए foo_private_t में किए गए परिवर्तनों की अनुमति है।)

बेस क्लास स्पेसिफायर और टेम्पलेट पैरामीटर के माध्यम से पहुंच योग्य प्रकारों के लिए भी इसी तरह की व्याख्या दी जा सकती है।

एबीआई अनुपालन सुनिश्चित करना

संबंधित Android.bp फ़ाइलों में vendor_available: true और vndk.enabled: true चिह्नित पुस्तकालयों के लिए एबीआई अनुपालन सुनिश्चित किया जाना चाहिए। उदाहरण के लिए:

cc_library {
    name: "libvndk_example",
    vendor_available: true,
    vndk: {
        enabled: true,
    }
}

किसी निर्यातित फ़ंक्शन द्वारा प्रत्यक्ष या अप्रत्यक्ष रूप से पहुंच योग्य डेटा प्रकारों के लिए, लाइब्रेरी में निम्नलिखित परिवर्तनों को एबीआई-ब्रेकिंग के रूप में वर्गीकृत किया गया है:

डेटा प्रकार विवरण
संरचनाएं और कक्षाएं
  • क्लास प्रकार या संरचना प्रकार का आकार बदलें।
  • आधार वर्ग
    • बेस क्लास जोड़ें या हटाएँ।
    • वस्तुतः विरासत में मिली आधार कक्षाओं को जोड़ें या हटाएँ।
    • आधार वर्गों का क्रम बदलें.
  • सदस्य कार्य
    • सदस्य फ़ंक्शन हटाएं*।
    • सदस्य फ़ंक्शंस से तर्क जोड़ें या हटाएँ।
    • तर्क प्रकार या सदस्य फ़ंक्शन के रिटर्न प्रकार बदलें*।
    • वर्चुअल टेबल लेआउट बदलें.
  • डेटा सदस्य
    • स्थैतिक डेटा सदस्यों को हटाएँ.
    • गैर-स्थैतिक डेटा सदस्यों को जोड़ें या हटाएँ।
    • डेटा सदस्यों के प्रकार बदलें.
    • ऑफसेट को गैर-स्थैतिक डेटा सदस्यों में बदलें**।
    • डेटा सदस्यों के const , volatile , और/या restricted क्वालिफायर बदलें***।
    • डेटा सदस्यों के एक्सेस विनिर्देशकों को डाउनग्रेड करें***।
  • टेम्पलेट तर्क बदलें.
यूनियन
  • डेटा सदस्य जोड़ें या हटाएँ.
  • यूनियन प्रकार का आकार बदलें.
  • डेटा सदस्यों के प्रकार बदलें.
गणना
  • अंतर्निहित प्रकार बदलें.
  • प्रगणकों के नाम बदलें।
  • प्रगणकों के मान बदलें.
वैश्विक प्रतीक
  • सार्वजनिक शीर्षलेखों द्वारा निर्यात किए गए प्रतीकों को हटाएँ।
  • FUNC प्रकार के वैश्विक प्रतीकों के लिए
    • तर्क जोड़ें या हटाएँ.
    • तर्क प्रकार बदलें.
    • रिटर्न प्रकार बदलें.
    • एक्सेस विनिर्देशक को डाउनग्रेड करें***।
  • OBJECT प्रकार के वैश्विक प्रतीकों के लिए
    • संबंधित C/C++ प्रकार बदलें।
    • एक्सेस विनिर्देशक को डाउनग्रेड करें***।

* सार्वजनिक और निजी दोनों सदस्य कार्यों को बदला या हटाया नहीं जाना चाहिए क्योंकि सार्वजनिक इनलाइन फ़ंक्शन निजी सदस्य कार्यों को संदर्भित कर सकते हैं। निजी सदस्य कार्यों के प्रतीक संदर्भों को कॉलर बायनेरिज़ में रखा जा सकता है। साझा लाइब्रेरीज़ से निजी सदस्य फ़ंक्शंस को बदलने या हटाने के परिणामस्वरूप बैकवर्ड-असंगत बायनेरिज़ हो सकते हैं।

** सार्वजनिक या निजी डेटा सदस्यों के ऑफसेट को नहीं बदला जाना चाहिए क्योंकि इनलाइन फ़ंक्शन इन डेटा सदस्यों को उनके फ़ंक्शन बॉडी में संदर्भित कर सकते हैं। डेटा सदस्य ऑफ़सेट बदलने से पश्चगामी-असंगत बायनेरिज़ उत्पन्न हो सकते हैं।

*** हालांकि ये प्रकार के मेमोरी लेआउट को नहीं बदलते हैं, लेकिन अर्थ संबंधी अंतर हैं जो पुस्तकालयों को उम्मीद के मुताबिक काम नहीं करने का कारण बन सकते हैं।

एबीआई अनुपालन उपकरण का उपयोग करना

जब एक VNDK लाइब्रेरी बनाई जाती है, तो लाइब्रेरी के ABI की तुलना VNDK के बनाए जा रहे संस्करण के लिए संबंधित 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

एबीआई टूटने की त्रुटि

एबीआई टूटने पर, बिल्ड लॉग चेतावनी प्रकार और एबीआई-डिफ रिपोर्ट के पथ के साथ चेतावनियां प्रदर्शित करता है। उदाहरण के लिए, यदि 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 ----

वीएनडीके लाइब्रेरी एबीआई जांच का निर्माण

जब VNDK लाइब्रेरी बनाई जाती है:

  1. header-abi-dumper VNDK लाइब्रेरी (लाइब्रेरी की अपनी स्रोत फ़ाइलों के साथ-साथ स्थैतिक ट्रांजिटिव निर्भरता के माध्यम से विरासत में मिली स्रोत फ़ाइलों) के निर्माण के लिए संकलित स्रोत फ़ाइलों को संसाधित करता है, ताकि प्रत्येक स्रोत के अनुरूप .sdump फ़ाइलों का उत्पादन किया जा सके।
    sdump creation
    चित्र 1. .sdump फ़ाइलें बनाना
  2. header-abi-linker फिर .sdump फ़ाइल बनाने के लिए .lsdump फ़ाइलों (या तो इसे प्रदान की गई संस्करण स्क्रिप्ट या साझा लाइब्रेरी से संबंधित .so फ़ाइल का उपयोग करके) को संसाधित करता है जो साझा लाइब्रेरी से संबंधित सभी ABI जानकारी को लॉग करता है।
    lsdump creation
    चित्र 2. .lsdump फ़ाइल बनाना
  3. header-abi-diff एक भिन्न रिपोर्ट तैयार करने के लिए .lsdump फ़ाइल की तुलना संदर्भ .lsdump फ़ाइल से करता है जो दो पुस्तकालयों के एबीआई में अंतर को रेखांकित करता है।
    abi diff creation
    चित्र 3. भिन्न रिपोर्ट बनाना

हेडर-अबी-डम्पर

header-abi-dumper टूल एक सी/सी++ स्रोत फ़ाइल को पार्स करता है और उस स्रोत फ़ाइल से अनुमानित एबीआई को एक मध्यवर्ती फ़ाइल में डंप करता है। बिल्ड सिस्टम सभी संकलित स्रोत फ़ाइलों पर header-abi-dumper चलाता है, साथ ही एक लाइब्रेरी भी बनाता है जिसमें ट्रांजिटिव निर्भरता से स्रोत फ़ाइलें शामिल होती हैं।

इनपुट
  • एसी/सी++ स्रोत फ़ाइल
  • निर्यात की गई निर्देशिकाएँ शामिल हैं
  • संकलक झंडे
उत्पादन एक फ़ाइल जो स्रोत फ़ाइल के ABI का वर्णन करती है (उदाहरण के लिए, foo.sdump foo.cpp के ABI का प्रतिनिधित्व करती है)।

वर्तमान में .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;
}

आप मध्यवर्ती .sdump फ़ाइल उत्पन्न करने के लिए header-abi-dumper उपयोग कर सकते हैं जो स्रोत फ़ाइल द्वारा प्रस्तुत एबीआई का प्रतिनिधित्व करता है:

$ 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 और सार्वजनिक हेडर द्वारा निर्यात की गई ABI जानकारी शामिल है, उदाहरण के लिए,

  • record_types । सार्वजनिक शीर्षलेखों में परिभाषित संरचनाओं, यूनियनों या वर्गों का संदर्भ लें। प्रत्येक रिकॉर्ड प्रकार में उसके फ़ील्ड, उसके आकार, एक्सेस विनिर्देशक, उसमें परिभाषित हेडर फ़ाइल और अन्य विशेषताओं के बारे में जानकारी होती है।
  • pointer_types । सार्वजनिक हेडर में निर्यात किए गए रिकॉर्ड/फ़ंक्शंस द्वारा प्रत्यक्ष/अप्रत्यक्ष रूप से संदर्भित पॉइंटर प्रकारों का संदर्भ लें, साथ ही पॉइंटर जिस प्रकार की ओर इशारा करता है ( type_info में referenced_type फ़ील्ड के माध्यम से)। योग्य प्रकार, अंतर्निहित C/C++ प्रकार, सरणी प्रकार, और lvalue और rvalue संदर्भ प्रकारों के लिए .sdump फ़ाइल में समान जानकारी लॉग की जाती है। ऐसी जानकारी पुनरावर्ती भिन्नता की अनुमति देती है।
  • functions . सार्वजनिक शीर्षलेखों द्वारा निर्यात किए गए फ़ंक्शन का प्रतिनिधित्व करें। उनके पास फ़ंक्शन के उलझे हुए नाम, रिटर्न प्रकार, पैरामीटर के प्रकार, एक्सेस विनिर्देशक और अन्य विशेषताओं के बारे में भी जानकारी है।

हेडर-अबी-लिंकर

header-abi-linker टूल header-abi-dumper द्वारा निर्मित मध्यवर्ती फ़ाइलों को इनपुट के रूप में लेता है और फिर उन फ़ाइलों को लिंक करता है:

इनपुट
  • header-abi-dumper द्वारा निर्मित मध्यवर्ती फ़ाइलें
  • संस्करण स्क्रिप्ट/मानचित्र फ़ाइल (वैकल्पिक)
  • साझा लाइब्रेरी की .so फ़ाइल
  • निर्यात की गई निर्देशिकाएँ शामिल हैं
उत्पादन एक फ़ाइल जो साझा लाइब्रेरी के ABI का वर्णन करती है (उदाहरण के लिए, libfoo.so.lsdump libfoo के ABI का प्रतिनिधित्व करती है)।

उपकरण इसे दी गई सभी मध्यवर्ती फ़ाइलों में प्रकार ग्राफ़ को मर्ज करता है, अनुवाद इकाइयों में एक-परिभाषा (एक ही पूर्णतः योग्य नाम के साथ विभिन्न अनुवाद इकाइयों में उपयोगकर्ता-परिभाषित प्रकार, शब्दार्थ रूप से भिन्न हो सकते हैं) को ध्यान में रखता है। उपकरण तब निर्यात किए गए प्रतीकों की एक सूची बनाने के लिए या तो एक संस्करण स्क्रिप्ट या साझा लाइब्रेरी ( .so फ़ाइल) की .dynsym तालिका को पार्स करता है।

उदाहरण के लिए, libfoo में foo.cpp और bar.cpp शामिल हैं। header-abi-linker निम्नानुसार 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 , libfoo.so का अंतिम जेनरेट किया गया ABI डंप है।

हेडर-अबी-डिफ

header-abi-diff टूल दो पुस्तकालयों के एबीआई का प्रतिनिधित्व करने वाली दो .lsdump फ़ाइलों की तुलना करता है और दो एबीआई के बीच अंतर बताते हुए एक अलग रिपोर्ट तैयार करता है।

इनपुट
  • .lsdump फ़ाइल एक पुरानी साझा लाइब्रेरी के ABI का प्रतिनिधित्व करती है।
  • .lsdump फ़ाइल एक नई साझा लाइब्रेरी के ABI का प्रतिनिधित्व करती है।
उत्पादन दो साझा पुस्तकालयों की तुलना में प्रस्तावित एबीआई में अंतर बताने वाली एक भिन्न रिपोर्ट।

एबीआई डिफ फाइल प्रोटोबफ टेक्स्ट फॉर्मेट में है। भविष्य में रिलीज़ में प्रारूप परिवर्तन के अधीन है।

उदाहरण के लिए, आपके पास libfoo के दो संस्करण हैं: libfoo_old.so और libfoo_new.solibfoo_new.so में, bar_t में, आप mfoo के प्रकार को foo_t से foo_t * में बदलते हैं। चूंकि bar_t एक पहुंच योग्य प्रकार है, इसलिए इसे 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 में libfoo में सभी ABI ब्रेकिंग परिवर्तनों की एक रिपोर्ट शामिल है। record_type_diffs संदेश इंगित करता है कि रिकॉर्ड बदल गया है और असंगत परिवर्तनों को सूचीबद्ध करता है, जिसमें शामिल हैं:

  • रिकॉर्ड का आकार 24 बाइट्स से 8 बाइट्स में बदल रहा है।
  • mfoo का फ़ील्ड प्रकार foo से foo * में बदल रहा है (सभी टाइपडिफ़ हटा दिए गए हैं)।

type_stack फ़ील्ड इंगित करता है कि header-abi-diff उस प्रकार तक कैसे पहुंचा जो बदल गया ( bar )। इस फ़ील्ड की व्याख्या इस प्रकार की जा सकती है कि Foo एक निर्यातित फ़ंक्शन है जो bar * को पैरामीटर के रूप में लेता है, जो bar की ओर इंगित करता है, जिसे निर्यात किया गया था और बदल दिया गया था।

एबीआई/एपीआई लागू करना

VNDK साझा पुस्तकालयों के ABI/API को लागू करने के लिए, ABI संदर्भों ${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/ में जांचना होगा। इन संदर्भों को बनाने के लिए, निम्न आदेश चलाएँ:

${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py

संदर्भ बनाने के बाद, स्रोत कोड में किए गए किसी भी बदलाव के परिणामस्वरूप वीएनडीके लाइब्रेरी में असंगत एबीआई/एपीआई परिवर्तन होता है, जिसके परिणामस्वरूप अब बिल्ड त्रुटि होती है।

विशिष्ट पुस्तकालयों के लिए एबीआई संदर्भों को अद्यतन करने के लिए, निम्नलिखित आदेश चलाएँ:

${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