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

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

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

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

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

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

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

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

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

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

रीचेबल टाइप कोई भी सी/सी++ बिल्ट-इन या यूज़र-डिफ़ाइंड प्रकार होता है जो सीधे या परोक्ष रूप से एक निर्यातित प्रतीक के माध्यम से पहुंच योग्य होता है और सार्वजनिक शीर्षलेखों के माध्यम से निर्यात किया जाता है। उदाहरण के लिए, 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 : [
    "include"
  ],
}
डायनेसिम तालिका
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_t के माध्यम से निर्यात किया foo_exported.h है, जिसके परिणामस्वरूप अधिक प्रकार निर्यात किए जाते हैं:
  • int : m1 का प्रकार है।
  • int * : m2 का प्रकार है।
  • foo_private_t * : mPfoo प्रकार है।

हालांकि, foo_private_t पहुंच योग्य नहीं है क्योंकि इसे foo_exported.h के माध्यम से निर्यात नहीं किया जाता है। ( foot_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,
    }
}

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

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

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

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

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

ABI अनुपालन टूल का उपयोग करना

जब एक वीएनडीके पुस्तकालय बनाया जाता है, तो पुस्तकालय के एबीआई की तुलना वीएनडीके के संस्करण के लिए संबंधित एबीआई संदर्भ के साथ की जाती है। संदर्भ एबीआई डंप यहां स्थित हैं:

${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/(v)ndk/<${PLATFORM_VNDK_VERSION}>/<BINDER_BITNESS>/<ARCH_ARCH-VARIANT>/source-based

उदाहरण के लिए, libfoo के API स्तर 27 के लिए libfoo के निर्माण पर, libfoo के अनुमानित ABI की तुलना इसके संदर्भ से की जाती है:

${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/(v)ndk/27/64/<ARCH_ARCH-VARIANT>/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 पुस्तकालय का निर्माण ABI जाँच करता है

जब एक वीएनडीके पुस्तकालय बनाया जाता है:

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

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

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

वर्तमान में .sdump फाइलें प्रोटोबफ टेक्स्टफॉर्मेट के रूप में स्वरूपित हैं, जो भविष्य के रिलीज में स्थिर होने की गारंटी नहीं है। जैसे, .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 -- -x c++

यह आदेश header-abi-dumper को foo.cpp को पार्स करने और exported की गई निर्देशिका में सार्वजनिक शीर्षलेखों में उजागर होने वाली एबीआई जानकारी को उत्सर्जित करने के लिए कहता है। यह header-abi-dumper द्वारा उत्पन्न foo.sdump से एक अंश (पूर्ण प्रतिनिधित्व नहीं) है:

record_types {
  type_info {
    name: "foo"
    size: 12
    alignment: 4
    referenced_type: "type-1"
    source_file: "foo/include/foo_exported.h"
    linker_set_key: "foo"
    self_type: "type-1"
  }
  fields {
    referenced_type: "type-2"
    field_offset: 0
    field_name: "m1"
    access: public_access
  }
  fields {
    referenced_type: "type-3"
    field_offset: 32
    field_name: "m2"
    access: public_access
  }
  fields {
    referenced_type: "type-5"
    field_offset: 64
    field_name: "mPfoo"
    access: public_access
  }
  access: public_access
  record_kind: struct_kind
  tag_info {
    unique_id: "_ZTS3foo"
  }
}
record_types {
  type_info {
    name: "bar"
    size: 12
    alignment: 4
    referenced_type: "type-6"
…
pointer_types {
  type_info {
    name: "bar *"
    size: 4
    alignment: 4
    referenced_type: "type-6"
    source_file: "foo/include/foo_exported.h"
    linker_set_key: "bar *"
    self_type: "type-8"
  }
}
builtin_types {
  type_info {
    name: "int"
    size: 4
    alignment: 4
    referenced_type: "type-2"
    source_file: ""
    linker_set_key: "int"
    self_type: "type-2"
  }
  is_unsigned: false
  is_integral: true
}
functions {
  return_type: "type-7"
  function_name: "Foo"
  source_file: "foo/include/foo_exported.h"
  parameters {
    referenced_type: "type-2"
    default_arg: false
  }
  parameters {
    referenced_type: "type-8"
    default_arg: false
  }
  linker_set_key: "_Z3FooiP3bar"
  access: public_access
}

foo.sdump में स्रोत फ़ाइल foo.cpp द्वारा उजागर की गई ABI जानकारी है, जैसे:

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

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

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

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

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

उदाहरण के लिए, जब libfoo अपने संकलन में bar.cpp फ़ाइल (जो एक C फ़ंक्शन bar को उजागर करता है) जोड़ता है, तो 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 में उदाहरण कमांड आउटपुट:

record_types {
  type_info {
    name: "foo"
    size: 24
    alignment: 8
    referenced_type: "type-1"
    source_file: "foo/include/foo_exported.h"
    linker_set_key: "foo"
    self_type: "type-1"
  }
  fields {
    referenced_type: "type-2"
    field_offset: 0
    field_name: "m1"
    access: public_access
  }
  fields {
    referenced_type: "type-3"
    field_offset: 64
    field_name: "m2"
    access: public_access
  }
  fields {
    referenced_type: "type-4"
    field_offset: 128
    field_name: "mPfoo"
    access: public_access
  }
  access: public_access
  record_kind: struct_kind
  tag_info {
    unique_id: "_ZTS3foo"
  }
}
record_types {
  type_info {
    name: "bar"
    size: 24
    alignment: 8
...
builtin_types {
  type_info {
    name: "void"
    size: 0
    alignment: 0
    referenced_type: "type-6"
    source_file: ""
    linker_set_key: "void"
    self_type: "type-6"
  }
  is_unsigned: false
  is_integral: false
}
functions {
  return_type: "type-19"
  function_name: "Foo"
  source_file: "foo/include/foo_exported.h"
  parameters {
    referenced_type: "type-2"
    default_arg: false
  }
  parameters {
    referenced_type: "type-20"
    default_arg: false
  }
  linker_set_key: "_Z3FooiP3bar"
  access: public_access
}
functions {
  return_type: "type-6"
  function_name: "FooBad"
  source_file: "foo/include/foo_exported_bad.h"
  parameters {
    referenced_type: "type-2"
    default_arg: false
  }
parameters {
    referenced_type: "type-7"
    default_arg: false
  }
  linker_set_key: "_Z6FooBadiP3foo"
  access: public_access
}
elf_functions {
  name: "_Z3FooiP3bar"
}
elf_functions {
  name: "_Z6FooBadiP3foo"
}

header-abi-linker टूल:

  • इसे प्रदान की गई .sdump फ़ाइलों को लिंक करता है ( foo.sdump और bar.sdump ), निर्देशिका में रहने वाले हेडर में मौजूद ABI जानकारी को फ़िल्टर नहीं करता है: exported गया।
  • libfoo.so को पार्स करता है, और libfoo.so तालिका के माध्यम से पुस्तकालय द्वारा निर्यात किए गए प्रतीकों के बारे में जानकारी एकत्र .dynsym है।
  • _Z3FooiP3bar और Bar जोड़ता है।

libfoo.so.lsdump , libfoo.so का अंतिम उत्पन्न libfoo.so डंप है।

शीर्षलेख-अबी-अंतर

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

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

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

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

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

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

वीएनडीके और एलएलएनडीके साझा पुस्तकालयों के एबीआई/एपीआई को लागू करने के लिए, एबीआई संदर्भों को ${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/(v)ndk/ में चेक किया जाना चाहिए। इन संदर्भों को बनाने के लिए, निम्न आदेश चलाएँ:

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

संदर्भ बनाने के बाद, स्रोत कोड में किए गए किसी भी परिवर्तन के परिणामस्वरूप VNDK या LLNDK लाइब्रेरी में असंगत 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

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

${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l <lib1> -l <lib2> --llndk

उदाहरण के लिए, libm ABI संदर्भों को अद्यतन करने के लिए, चलाएँ:

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