ABI স্থিতিশীলতা

অ্যাপ্লিকেশন বাইনারি ইন্টারফেস (ABI) স্থায়িত্ব হল ফ্রেমওয়ার্ক-শুধু আপডেটের পূর্বশর্ত কারণ ভেন্ডর মডিউলগুলি ভেন্ডর নেটিভ ডেভেলপমেন্ট কিট (VNDK) শেয়ার্ড লাইব্রেরির উপর নির্ভর করতে পারে যা সিস্টেম পার্টিশনে থাকে। একটি অ্যান্ড্রয়েড রিলিজের মধ্যে, নতুন-নির্মিত VNDK ভাগ করা লাইব্রেরিগুলি অবশ্যই পূর্বে প্রকাশিত VNDK ভাগ করা লাইব্রেরির সাথে ABI-সামঞ্জস্যপূর্ণ হতে হবে যাতে বিক্রেতা মডিউলগুলি পুনরায় সংকলন ছাড়াই এবং রানটাইম ত্রুটি ছাড়াই সেই লাইব্রেরির সাথে কাজ করতে পারে। অ্যান্ড্রয়েড রিলিজের মধ্যে, ভিএনডিকে লাইব্রেরি পরিবর্তন করা যেতে পারে এবং কোন ABI গ্যারান্টি নেই।

ABI সামঞ্জস্য নিশ্চিত করতে সাহায্য করার জন্য, Android 9-এ একটি শিরোনাম ABI চেকার রয়েছে, যা নিম্নলিখিত বিভাগে বর্ণিত হয়েছে।

VNDK এবং ABI সম্মতি সম্পর্কে

VNDK হল লাইব্রেরিগুলির একটি সীমাবদ্ধ সেট যেগুলির সাথে বিক্রেতা মডিউলগুলি লিঙ্ক করতে পারে এবং যা শুধুমাত্র ফ্রেমওয়ার্ক আপডেটগুলি সক্ষম করে৷ ABI সম্মতি বলতে একটি শেয়ার্ড লাইব্রেরির একটি নতুন সংস্করণের সাথে গতিশীলভাবে যুক্ত একটি মডিউলের সাথে প্রত্যাশিতভাবে কাজ করার ক্ষমতা বোঝায় (যেমন লাইব্রেরির পুরানো সংস্করণ হিসাবে কাজ করে)।

রপ্তানি প্রতীক সম্পর্কে

একটি রপ্তানিকৃত চিহ্ন (একটি বৈশ্বিক প্রতীক হিসাবেও পরিচিত) একটি চিহ্নকে বোঝায় যা নিম্নলিখিত সমস্তকে সন্তুষ্ট করে:

  • একটি শেয়ার্ড লাইব্রেরির পাবলিক হেডার দ্বারা রপ্তানি করা হয়েছে৷
  • শেয়ার করা লাইব্রেরির সাথে সম্পর্কিত .so ফাইলের .dynsym টেবিলে উপস্থিত হয়।
  • দুর্বল বা গ্লোবাল বাইন্ডিং আছে।
  • দৃশ্যমানতা ডিফল্ট বা সুরক্ষিত।
  • বিভাগ সূচক অনির্ধারিত নয়।
  • টাইপ হয় FUNC বা OBJECT।

শেয়ার্ড লাইব্রেরির পাবলিক হেডারগুলিকে export_header_lib_headers , এক্সপোর্ট_হেডার_লিব_হেডার , export_static_lib_headers , export_shared_lib_headers , এবং export_generated_headers বৈশিষ্ট্যগুলির মাধ্যমে অন্যান্য লাইব্রেরি/ export_include_dirs উপলব্ধ 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 : [
    "include"
  ],
}
.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 এর মাধ্যমে রপ্তানি করা হয়, যার ফলে আরও ধরনের রপ্তানি হয়:
  • int : m1 এর ধরন।
  • int * : m2 এর ধরন।
  • foo_private_t * : mPfoo ধরন।

যাইহোক, foo_private_t পৌঁছানো যায় না কারণ এটি foo_exported.h এর মাধ্যমে রপ্তানি হয় না। ( foot_private_t * অস্বচ্ছ, তাই foo_private_t এ করা পরিবর্তন অনুমোদিত।)

বেস ক্লাস স্পেসিফায়ার এবং টেমপ্লেট পরামিতিগুলির মাধ্যমেও পৌঁছানো যায় এমন ধরণের জন্য অনুরূপ ব্যাখ্যা দেওয়া যেতে পারে।

ABI সম্মতি নিশ্চিত করা

বিক্রেতা_available চিহ্নিত লাইব্রেরির জন্য ABI সম্মতি নিশ্চিত করতে হবে vendor_available: true এবং vndk.enabled: true সংশ্লিষ্ট Android.bp ফাইলগুলিতে সত্য। উদাহরণ স্বরূপ:

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

রপ্তানিকৃত ফাংশন দ্বারা প্রত্যক্ষ বা পরোক্ষভাবে পৌঁছানো ডেটা প্রকারের জন্য, একটি লাইব্রেরিতে নিম্নলিখিত পরিবর্তনগুলি ABI-ব্রেকিং হিসাবে শ্রেণীবদ্ধ করা হয়েছে:

ডেটা টাইপ বর্ণনা
স্ট্রাকচার এবং ক্লাস
  • ক্লাস টাইপ বা struct টাইপের আকার পরিবর্তন করুন।
  • বেস ক্লাস
    • বেস ক্লাস যোগ করুন বা সরান।
    • কার্যত উত্তরাধিকারসূত্রে প্রাপ্ত বেস ক্লাসগুলি যুক্ত করুন বা সরান৷
    • বেস ক্লাসের ক্রম পরিবর্তন করুন।
  • সদস্য ফাংশন
    • সদস্য ফাংশন সরান*.
    • সদস্য ফাংশন থেকে আর্গুমেন্ট যোগ করুন বা সরান।
    • যুক্তি প্রকারের ধরন বা সদস্যের ফাংশনগুলির রিটার্ন প্রকারগুলি পরিবর্তন করুন *।
    • ভার্চুয়াল টেবিল লেআউট পরিবর্তন করুন.
  • ডেটা সদস্য
    • স্ট্যাটিক ডেটা সদস্যদের সরান।
    • নন-স্ট্যাটিক ডেটা সদস্যদের যোগ করুন বা সরান।
    • ডেটা সদস্যদের ধরন পরিবর্তন করুন।
    • অফসেটগুলিকে নন-স্ট্যাটিক ডেটা সদস্যে পরিবর্তন করুন**।
    • const , volatile , এবং/অথবা ডেটা সদস্যদের restricted যোগ্যতা পরিবর্তন করুন***।
    • ডেটা সদস্যদের অ্যাক্সেস স্পেসিফায়ার ডাউনগ্রেড করুন***।
  • টেমপ্লেট আর্গুমেন্ট পরিবর্তন করুন.
ইউনিয়ন
  • ডেটা সদস্যদের যোগ করুন বা সরান।
  • ইউনিয়নের আকার পরিবর্তন করুন।
  • ডেটা সদস্যদের ধরন পরিবর্তন করুন।
  • ডেটা সদস্যদের ক্রম পরিবর্তন করুন।
গণনা
  • অন্তর্নিহিত প্রকার পরিবর্তন করুন.
  • গণনাকারীদের নাম পরিবর্তন করুন।
  • গণনাকারীর মান পরিবর্তন করুন।
গ্লোবাল সিম্বল
  • পাবলিক হেডার দ্বারা রপ্তানি করা প্রতীকগুলি সরান।
  • FUNC টাইপের গ্লোবাল চিহ্নের জন্য
    • যুক্তি যোগ করুন বা সরান.
    • যুক্তির ধরন পরিবর্তন করুন।
    • রিটার্ন টাইপ পরিবর্তন করুন।
    • অ্যাক্সেস স্পেসিফায়ার ডাউনগ্রেড করুন ***।
  • OBJECT টাইপের বৈশ্বিক চিহ্নের জন্য
    • সংশ্লিষ্ট C/C++ প্রকার পরিবর্তন করুন।
    • অ্যাক্সেস স্পেসিফায়ার ডাউনগ্রেড করুন ***।

* উভয় পাবলিক এবং প্রাইভেট সদস্য ফাংশন পরিবর্তন বা অপসারণ করা উচিত নয় কারণ পাবলিক ইনলাইন ফাংশন ব্যক্তিগত সদস্য ফাংশন উল্লেখ করতে পারে। ব্যক্তিগত সদস্য ফাংশন প্রতীক রেফারেন্স কলার বাইনারিগুলিতে রাখা যেতে পারে। শেয়ার্ড লাইব্রেরি থেকে ব্যক্তিগত সদস্য ফাংশন পরিবর্তন বা অপসারণের ফলে পিছিয়ে-বেমানান বাইনারি হতে পারে।

** সর্বজনীন বা ব্যক্তিগত ডেটা সদস্যদের অফসেটগুলি অবশ্যই পরিবর্তন করা উচিত নয় কারণ ইনলাইন ফাংশনগুলি তাদের ফাংশন বডিতে এই ডেটা সদস্যদের উল্লেখ করতে পারে। তথ্য সদস্য অফসেট পরিবর্তন ব্যাকওয়ার্ড-অসঙ্গতিপূর্ণ বাইনারি হতে পারে।

*** যদিও এগুলি টাইপের মেমরি লেআউট পরিবর্তন করে না, সেখানে শব্দার্থগত পার্থক্য রয়েছে যা লাইব্রেরিগুলি প্রত্যাশিতভাবে কাজ করতে পারে না।

ABI কমপ্লায়েন্স টুল ব্যবহার করা

যখন একটি VNDK লাইব্রেরি তৈরি করা হয়, তখন লাইব্রেরির ABI-কে VNDK-এর সংস্করণের জন্য সংশ্লিষ্ট ABI রেফারেন্সের সাথে তুলনা করা হয়। রেফারেন্স 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

ABI ভাঙ্গন ত্রুটি

এবিআই ব্রেকেজের ক্ষেত্রে, বিল্ড লগ সতর্কতার ধরন এবং এবি-ডিফ রিপোর্টের পথ সহ সতর্কতা প্রদর্শন করে। উদাহরণ স্বরূপ, যদি 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 তারপর একটি .lsdump ফাইল তৈরি করতে .sdump ফাইলগুলিকে প্রসেস করে (হয় এটিকে দেওয়া একটি সংস্করণ স্ক্রিপ্ট ব্যবহার করে বা শেয়ার করা লাইব্রেরির সাথে সম্পর্কিত .so ফাইলটি ব্যবহার করে) যা শেয়ার করা লাইব্রেরির সাথে সম্পর্কিত ABI তথ্য লগ করে।
    lsdump creation
    চিত্র 2. .lsdump ফাইল তৈরি করা হচ্ছে
  3. header-abi-diff .lsdump ফাইলটিকে একটি রেফারেন্স .lsdump ফাইলের সাথে তুলনা করে একটি ভিন্ন প্রতিবেদন তৈরি করে যা দুটি লাইব্রেরির ABI-এর মধ্যে পার্থক্যকে রূপরেখা দেয়।
    abi diff creation
    চিত্র 3. ডিফ রিপোর্ট তৈরি করা

হেডার-আবি-ডাম্পার

header-abi-dumper টুলটি একটি C/C++ সোর্স ফাইল পার্স করে এবং সেই সোর্স ফাইল থেকে অনুমান করা ABI একটি মধ্যবর্তী ফাইলে ডাম্প করে। বিল্ড সিস্টেমটি সমস্ত কম্পাইল করা সোর্স ফাইলে header-abi-dumper চালায় এবং একটি লাইব্রেরি তৈরি করে যাতে ট্রানজিটিভ নির্ভরতা থেকে সোর্স ফাইল অন্তর্ভুক্ত থাকে।

বর্তমানে .sdump ফাইলগুলিকে Protobuf TextFormatted হিসাবে ফর্ম্যাট করা হয়েছে, যা ভবিষ্যতের রিলিজগুলিতে স্থিতিশীল হওয়ার নিশ্চয়তা নেই৷ যেমন, .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 ব্যবহার করতে পারেন যা ব্যবহার করে উৎস ফাইল দ্বারা উপস্থাপিত ABI প্রতিনিধিত্ব করে:

$ header-abi-dumper foo.cpp -I exported -o foo.sdump -- -x c++

এই কমান্ড header-abi-dumper foo.cpp পার্স করতে এবং exported ডিরেক্টরিতে পাবলিক হেডারে প্রকাশিত ABI তথ্য নির্গত করতে বলে। এটি 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 এ ABI তথ্য রয়েছে foo.cpp সোর্স ফাইল দ্বারা উন্মুক্ত করা হয়েছে, যেমন:

  • record_types পাবলিক হেডার দ্বারা উদ্ভাসিত structs, ইউনিয়ন, বা ক্লাস পড়ুন। প্রতিটি রেকর্ডের ধরন এর ক্ষেত্র, এর আকার, অ্যাক্সেস স্পেসিফায়ার, যে হেডার ফাইলে এটি উন্মুক্ত করা হয়েছিল ইত্যাদি সম্পর্কে তথ্য থাকে।
  • pointer_types । সর্বজনীন শিরোনাম দ্বারা উন্মোচিত রেকর্ড/ফাংশন দ্বারা প্রত্যক্ষ/পরোক্ষভাবে নির্দেশিত পয়েন্টার প্রকারগুলি দেখুন, সাথে পয়েন্টার পয়েন্টার যে ধরনের নির্দেশ করে ( type_inforeferenced_type ক্ষেত্রের মাধ্যমে)। অনুরূপ তথ্য .sdump ফাইলে যোগ্য ধরনের, অন্তর্নির্মিত C/C++ প্রকার, অ্যারে প্রকার, এবং lvalue এবং rvalue রেফারেন্স প্রকারের জন্য লগ করা হয় (প্রকার সম্পর্কে যেমন লগিং তথ্য পুনরাবৃত্তিমূলক পার্থক্যের জন্য অনুমতি দেয়)।
  • functions পাবলিক হেডার দ্বারা উন্মুক্ত ফাংশন প্রতিনিধিত্ব করুন. তাদের কাছে ফাংশনের ম্যাঙ্গলড নাম, রিটার্নের ধরন, প্যারামিটারের ধরন, অ্যাক্সেস স্পেসিফায়ার ইত্যাদি সম্পর্কে তথ্য রয়েছে।

হেডার-অবি-লিঙ্কার

header-abi-linker টুলটি header-abi-dumper দ্বারা উত্পাদিত মধ্যবর্তী ফাইলগুলিকে ইনপুট হিসাবে নেয় তারপর সেই ফাইলগুলিকে লিঙ্ক করে:

ইনপুট
  • header-abi-dumper দ্বারা উত্পাদিত মধ্যবর্তী ফাইল
  • সংস্করণ স্ক্রিপ্ট/মানচিত্র ফাইল (ঐচ্ছিক)
  • তাই শেয়ার করা লাইব্রেরির ফাইল
আউটপুট একটি ফাইল যা একটি ভাগ করা লাইব্রেরির ABI লগ করে (যেমন libfoo.so.lsdump libfoo এর ABI প্রতিনিধিত্ব করে)।

টুলটি একে প্রদত্ত সমস্ত মধ্যবর্তী ফাইলের টাইপ গ্রাফগুলিকে একত্রিত করে, এক-সংজ্ঞা (একই সম্পূর্ণ যোগ্য নামের সাথে বিভিন্ন অনুবাদ ইউনিটে ব্যবহারকারী-সংজ্ঞায়িত প্রকারগুলি, শব্দার্থগতভাবে ভিন্ন হতে পারে) অনুবাদ ইউনিটগুলির মধ্যে পার্থক্য বিবেচনা করে। টুলটি তখন হয় একটি সংস্করণ স্ক্রিপ্ট বা ভাগ করা লাইব্রেরির .dynsym টেবিলকে পার্স করে ( .so ফাইল) এক্সপোর্ট করা চিহ্নগুলির একটি তালিকা তৈরি করতে।

উদাহরণস্বরূপ, যখন libfoo তার bar.cpp ফাইল (যা একটি C ফাংশন bar প্রকাশ করে) যোগ করে, তখন libfoo-এর সম্পূর্ণ লিঙ্কযুক্ত ABI ডাম্প তৈরি করতে 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 এ কমান্ড আউটপুটের উদাহরণ:

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 ডাম্প।

হেডার-আবি-ডিফ

header-abi-diff এবি-ডিফ টুল দুটি লাইব্রেরির ABI প্রতিনিধিত্বকারী দুটি .lsdump ফাইলের তুলনা করে এবং দুটি ABI-এর মধ্যে পার্থক্য উল্লেখ করে একটি ভিন্ন প্রতিবেদন তৈরি করে।

ইনপুট
  • একটি পুরানো ভাগ করা লাইব্রেরির ABI প্রতিনিধিত্বকারী .lsdump ফাইল।
  • একটি নতুন ভাগ করা লাইব্রেরির ABI প্রতিনিধিত্বকারী .lsdump ফাইল।
আউটপুট তুলনা করা দুটি শেয়ার্ড লাইব্রেরি দ্বারা প্রদত্ত ABI-এর পার্থক্য উল্লেখ করে একটি ভিন্ন প্রতিবেদন।

ABI diff ফাইলটি যতটা সম্ভব verbose এবং পাঠযোগ্য হিসাবে ডিজাইন করা হয়েছে। ফরম্যাট ভবিষ্যতে রিলিজ পরিবর্তন সাপেক্ষে. উদাহরণস্বরূপ, আপনার libfoo এর দুটি সংস্করণ রয়েছে: libfoo_old.so এবং libfoo_new.solibfoo_new.so এ, bar_t এ, আপনি mfoo-এর ধরন 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.abidifflibfoo এ ABI-এর সমস্ত পরিবর্তনের একটি প্রতিবেদন রয়েছে। record_type_diffs বার্তাটি নির্দেশ করে যে একটি রেকর্ড পরিবর্তিত হয়েছে এবং অসঙ্গত পরিবর্তনগুলি তালিকাভুক্ত করে, যার মধ্যে রয়েছে:

  • রেকর্ডের আকার 24 বাইট থেকে 8 বাইটে পরিবর্তিত হচ্ছে।
  • mfoo এর ক্ষেত্রের ধরন foo থেকে foo * তে পরিবর্তিত হচ্ছে (সমস্ত টাইপডেফ বন্ধ করা হয়েছে)।

type_stack ক্ষেত্র নির্দেশ করে কিভাবে header-abi-diff এবি-ডিফ পরিবর্তিত প্রকারে পৌঁছেছে ( bar )। এই ক্ষেত্রটিকে ব্যাখ্যা করা যেতে পারে যে Foo হল একটি রপ্তানিকৃত ফাংশন যা bar * প্যারামিটার হিসাবে নেয়, যা bar নির্দেশ করে, যা রপ্তানি এবং পরিবর্তিত হয়েছিল।

ABI/API বলবৎ করা

VNDK এবং LLNDK ভাগ করা লাইব্রেরির ABI/API প্রয়োগ করতে, ABI রেফারেন্সগুলি অবশ্যই ${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

নির্দিষ্ট LLNDK লাইব্রেরির জন্য ABI রেফারেন্স আপডেট করতে, নিম্নলিখিত কমান্ডটি চালান:

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