ফ্রেমওয়ার্ক-অনলি আপডেটের জন্য অ্যাপ্লিকেশন বাইনারি ইন্টারফেস (ABI) স্টেবিলিটি একটি পূর্বশর্ত, কারণ ভেন্ডর মডিউল, সিস্টেম পার্টিশনে থাকা ভেন্ডর নেটিভ ডেভেলপমেন্ট কিট (VNDK) শেয়ারড লাইব্রেরির উপর নির্ভর করতে পারে। Android রিলিজের মধ্যে, নতুন করে তৈরি করা VNDK শেয়ারড লাইব্রেরিগুলিকে অবশ্যই আগে রিলিজ করা VNDK শেয়ারড লাইব্রেরির সাথে ABI-মানানসই হতে হবে, যাতে ভেন্ডর মডিউল পুনঃকম্পাইলেশন ও রানটাইম এরর ছাড়াই সেইসব লাইব্রেরির সাথে কাজ করতে পারে। Android রিলিজের মধ্যে, VNDK লাইব্রেরি পরিবর্তন করা যেতে পারে এবং কোনও ABI গ্যারান্টি নেই।
ABI কম্প্যাটিবিলিটি নিশ্চিত করতে সাহায্য করতে, Android 9-এ একটি হেডার ABI চেকার অন্তর্ভুক্ত আছে, যা নিম্নলিখিত বিভাগে বর্ণনা করা হয়েছে।
VNDK ও ABI মেনে চলা সম্পর্কে
VNDK হল লাইব্রেরির একটি সীমাবদ্ধ সেট যা ভেন্ডর মডিউল লিঙ্ক করতে পারে এবং যা শুধুমাত্র ফ্রেমওয়ার্ক আপডেট চালু করে। ABI কমপ্লায়েন্স বলতে বোঝায় যে কোনও শেয়ার করা লাইব্রেরির নতুন ভার্সন সেটির সাথে ডায়নামিক লিঙ্ক করা মডিউলের সাথে প্রত্যাশিতভাবে কাজ করতে পারে (অর্থাৎ, এটি লাইব্রেরির পুরনো ভার্সনের মতো কাজ করে)।
এক্সপোর্ট করা চিহ্ন সম্পর্কে
এক্সপোর্ট করা সিম্বল (গ্লোবাল সিম্বল নামেও পরিচিত) বলতে বোঝায় এমন সিম্বল যা নিম্নলিখিত সবগুলি শর্ত পূরণ করে:
- শেয়ার করা লাইব্রেরির পাবলিক হেডার এক্সপোর্ট করে।
- শেয়ার করা লাইব্রেরির সাথে সম্পর্কিত
.soফাইলে.dynsymটেবিলে দেখা যায়। - 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 মেনে চলা নিশ্চিত করা
সংশ্লিষ্ট Android.bp ফাইলে
vendor_available: true এবং vndk.enabled: true হিসেবে চিহ্নিত লাইব্রেরির জন্য
ABI সম্মতি নিশ্চিত করতে হবে। যেমন:
cc_library { name: "libvndk_example", vendor_available: true, vndk: { enabled: true, } }
এক্সপোর্ট করা ফাংশনের মাধ্যমে সরাসরি বা পরোক্ষভাবে অ্যাক্সেস করা যায় এমন ডেটার ধরনের জন্য, লাইব্রেরিতে করা নিম্নলিখিত পরিবর্তনগুলিকে ABI-ব্রেকিং হিসেবে শ্রেণীবদ্ধ করা হয়:
| ডেটার ধরন | বর্ণনা |
|---|---|
| স্ট্রাকচার ও ক্লাস |
|
| ইউনিয়ন |
|
| গণনা |
|
| গ্লোবাল চিহ্ন |
|
* সর্বজনীন ও ব্যক্তিগত মেম্বার ফাংশন, দু'টিকেই পরিবর্তন বা সরানো যাবে না, কারণ সর্বজনীন ইনলাইন ফাংশন ব্যক্তিগত মেম্বার ফাংশনকে রেফার করতে পারে। প্রাইভেট মেম্বার ফাংশনের সিম্বল রেফারেন্স কলার বাইনারিতে রাখা যেতে পারে। শেয়ার করা লাইব্রেরি থেকে ব্যক্তিগত মেম্বার ফাংশন পরিবর্তন বা সরিয়ে দিলে এর ফলে ব্যাকওয়ার্ড-ইনকম্প্যাটিবল বাইনারি হতে পারে।
** পাবলিক বা ব্যক্তিগত ডেটা মেম্বারদের অফসেট পরিবর্তন করা যাবে না কারণ ইনলাইন ফাংশন তাদের ফাংশন বডিতে এইসব ডেটা মেম্বারদের রেফার করতে পারে। ডেটা মেম্বার অফসেট পরিবর্তন করলে ব্যাকওয়ার্ড-ইনকম্প্যাটিবল বাইনারি তৈরি হতে পারে।
*** এগুলি টাইপের মেমরি লেআউট পরিবর্তন না করলেও সেম্যান্টিক পার্থক্য আছে যা লাইব্রেরি প্রত্যাশিতভাবে কাজ না করার কারণ হতে পারে।
ABI-এর বিধিনিয়ম মেনে চলা সংক্রান্ত টুল ব্যবহার করা
VNDK লাইব্রেরি তৈরি করা হলে, লাইব্রেরির ABI-কে তৈরি করা হচ্ছে এমন VNDK-এর ভার্সনের সংশ্লিষ্ট ABI রেফারেন্সের সাথে তুলনা করা হয়। রেফারেন্স ABI ডাম্প এখানে আছে:
${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/<PLATFORM_VNDK_VERSION>/<BINDER_BITNESS>/<ARCH>/source-based
যেমন, API লেভেল ২৭-এ x86-এর জন্য libfoo তৈরি করার সময়,
libfoo-এর ইনফার করা ABI-কে এর রেফারেন্সের সাথে তুলনা করা হয়:
${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/27/64/x86/source-based/libfoo.so.lsdump
ABI ব্রেकेज সংক্রান্ত সমস্যা
ABI ব্রেकेज হলে, বিল্ড লগে সতর্কতার ধরন ও 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 ----
VNDK লাইব্রেরি ABI চেক তৈরি করুন
VNDK লাইব্রেরি তৈরি করা হলে:
header-abi-dumperVNDK লাইব্রেরি (লাইব্রেরির নিজস্ব সোর্স ফাইল এবং স্ট্যাটিক ট্রানজিটিভ ডিপেন্ডেন্সির মাধ্যমে ইনহেরিট করা সোর্স ফাইল) তৈরি করতে কম্পাইল করা সোর্স ফাইল প্রসেস করে। এর ফলে.sdumpফাইল তৈরি হয় যা প্রতিটি সোর্সের সাথে সম্পর্কিত।
ছবি ১. .sdumpটি ফাইল তৈরি করা হচ্ছেheader-abi-linkerতারপর.sdumpফাইল (এর জন্য প্রদত্ত ভার্সন স্ক্রিপ্ট বা শেয়ার করা লাইব্রেরির সাথে সম্পর্কিত.soফাইল ব্যবহার করে) প্রসেস করে.lsdumpফাইল তৈরি করে, যা শেয়ার করা লাইব্রেরির সাথে সম্পর্কিত সমস্ত ABI তথ্য লগ করে।
ছবি ২. তৈরি করা হচ্ছে.lsdumpফাইলheader-abi-diff,.lsdumpফাইলের সাথে রেফারেন্স.lsdumpফাইলের তুলনা করে একটি ডিফারেন্স রিপোর্ট তৈরি করে যা দুটি লাইব্রেরির ABI-এর মধ্যে পার্থক্যগুলি তুলে ধরে।
ছবি ৩. ডিফারেন্স রিপোর্ট তৈরি করা হচ্ছে
header-abi-dumper
header-abi-dumper টুলটি একটি C/C++ সোর্স ফাইল পার্স করে এবং সেই সোর্স ফাইল থেকে পাওয়া ABI
একটি ইন্টারমিডিয়েট ফাইলে ডাম্প করে। বিল্ড
সিস্টেম সব কম্পাইল করা সোর্স ফাইলে 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; }
আপনি 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 ডিরেক্টরিতে থাকা পাবলিক হেডার দ্বারা এক্সপোর্ট করা ABI তথ্য
এমিট করতে হবে। নিচে
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 সোর্স ফাইল থেকে এক্সপোর্ট করা ABI তথ্য থাকে
foo.cpp এবং সর্বজনীন হেডার, যেমন,
record_types. পাবলিক হেডারে সংজ্ঞায়িত স্ট্রাক্ট, ইউনিয়ন বা ক্লাস দেখুন। প্রতিটি রেকর্ডের ধরন তার ফিল্ড, সাইজ, অ্যাক্সেস স্পেসিফায়ার, হেডার ফাইল যেখানে এটি সংজ্ঞায়িত করা হয়েছে এবং অন্যান্য অ্যাট্রিবিউট সম্পর্কে তথ্য প্রদান করে।pointer_types. পাবলিক হেডারে এক্সপোর্ট করা রেকর্ড/ফাংশন দ্বারা প্রত্যক্ষ/পরোক্ষভাবে রেফারেন্স করা পয়েন্টার টাইপগুলি দেখুন, সাথে পয়েন্টারটি যে টাইপকে নির্দেশ করে (type_info-এreferenced_typeফিল্ডের মাধ্যমে)। একই ধরনের তথ্য কোয়ালিফায়েড টাইপ, বিল্ট-ইন C/C++ টাইপ, অ্যারে টাইপ এবং lvalue ও rvalue রেফারেন্স টাইপের জন্য.sdumpফাইলে লগ করা হয়। এই ধরনের তথ্য রিকার্সিভ ডিফিঙের অনুমতি দেয়।functions. পাবলিক হেডার দ্বারা এক্সপোর্ট করা ফাংশনগুলি উপস্থাপন করে। এছাড়াও, ফাংশনের ম্যাঙ্গেল করা নাম, রিটার্নের ধরন, প্যারামিটারের ধরন, অ্যাক্সেস স্পেসিফায়ার এবং অন্যান্য অ্যাট্রিবিউট সম্পর্কে তথ্য থাকে।
header-abi-linker
header-abi-linker টুল header-abi-dumper-এর মাধ্যমে তৈরি করা ইন্টারমিডিয়েট ফাইল ইনপুট হিসেবে নেয়
এবং তারপর সেইসব ফাইল লিঙ্ক করে:
| ইনপুট |
|
|---|---|
| আউটপুট | শেয়ার করা লাইব্রেরির ABI বর্ণনা করে এমন ফাইল (যেমন,
libfoo.so.lsdump libfoo-এর ABI)।
|
টুলটি সেটিকে দেওয়া সমস্ত ইন্টারমিডিয়েট ফাইলে থাকা টাইপ গ্রাফ মার্জ করে,
এর সাথে সাথে ট্রান্সলেশন ইউনিট জুড়ে থাকা এক-সংজ্ঞা (একই সম্পূর্ণ কোয়ালিফায়েড নাম সহ বিভিন্ন
ট্রান্সলেশন ইউনিটে ব্যবহারকারী-সংজ্ঞায়িত ধরন, যা শব্দার্থগতভাবে
আলাদা হতে পারে) সংক্রান্ত পার্থক্যও বিবেচনা করে। তারপরে, টুলটি এক্সপোর্ট করা প্রতীকের তালিকা তৈরি করতে
একটি ভার্সন স্ক্রিপ্ট বা শেয়ার করা লাইব্রেরির .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), ডিরেক্টরিতে থাকা হেডার থেকে ABI তথ্য ফিল্টার করে দেয়:exported। libfoo.soপার্স করে এবং লাইব্রেরি তার.dynsymটেবিলের মাধ্যমে যে প্রতীক এক্সপোর্ট করে সেগুলি সম্পর্কে তথ্য সংগ্রহ করে।_Z3FooiP3barও_Z6FooBadiP3fooযোগ করে।
libfoo.so.lsdump হল libfoo.so-এর
চূড়ান্ত জেনারেট করা ABI ডাম্প।
header-abi-diff
header-abi-diff টুল দুটি .lsdump ফাইলের তুলনা করে
যা দুটি লাইব্রেরির ABI-কে দেখায় এবং দুটি ABI-এর মধ্যে পার্থক্য উল্লেখ করে
একটি ডিফারেন্স রিপোর্ট তৈরি করে।
| ইনপুট |
|
|---|---|
| আউটপুট | দুটি শেয়ার করা লাইব্রেরির মধ্যে তুলনা করে পাওয়া পার্থক্যগুলি উল্লেখ করে একটি ডিফারেন্স রিপোর্ট তৈরি করা হয়। |
ABI ডিফারেন্স ফাইলটি প্রোটোকল বাফার টেক্সট ফর্ম্যাটে আছে। ভবিষ্যতে রিলিজের ক্ষেত্রে ফর্ম্যাটে পরিবর্তন করা হতে পারে।
যেমন, আপনার কাছে
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-এর সমস্ত ABI ব্রেকিং পরিবর্তনের
রিপোর্ট রয়েছে। record_type_diffs মেসেজ
থেকে বোঝা যায় যে রেকর্ড পরিবর্তন করা হয়েছে এবং এতে অসামঞ্জস্যপূর্ণ পরিবর্তনের তালিকা থাকে, যার মধ্যে
রয়েছে:
- রেকর্ডের সাইজ
24বাইট থেকে পরিবর্তন হয়ে8বাইট হয়েছে। mfoo-এর ফিল্ড টাইপfooথেকেfoo *-এ পরিবর্তন করা হচ্ছে (সব typedef বাদ দেওয়া হয়েছে)।
type_stack ফিল্ড থেকে বোঝা যায় যে কীভাবে header-abi-diff
পরিবর্তিত হওয়া টাইপে (bar) পৌঁছেছে। এই ফিল্ডকে
এইভাবে ব্যাখ্যা করা যেতে পারে যে Foo হল একটি এক্সপোর্ট করা ফাংশন যা
bar *-কে প্যারামিটার হিসেবে নেয় এবং bar-এর দিকে পয়েন্ট করে, যা
এক্সপোর্ট করা ও পরিবর্তিত হয়েছে।
ABI এবং API এনফোর্স করুন
VNDK শেয়ার করা লাইব্রেরির ABI ও API এনফোর্স করতে, ABI রেফারেন্স অবশ্যই
${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/-এ চেক করতে হবে।
এইসব রেফারেন্স তৈরি করতে, নিম্নলিখিত কমান্ড রান করুন:
${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py
রেফারেন্স তৈরি করার পরে, সোর্স কোডে করা যেকোনও পরিবর্তন যার ফলে VNDK লাইব্রেরিতে ABI/API সংক্রান্ত কোনও ইনকম্প্যাটিবল পরিবর্তন হয়, এখন তার ফলে বিল্ড সংক্রান্ত সমস্যা হয়।
নির্দিষ্ট লাইব্রেরির জন্য 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