অ্যাপ্লিকেশন বাইনারি ইন্টারফেস (ABI) স্থিতিশীলতা শুধুমাত্র ফ্রেমওয়ার্ক-ভিত্তিক আপডেটের জন্য একটি পূর্বশর্ত, কারণ ভেন্ডর মডিউলগুলো সিস্টেম পার্টিশনে থাকা ভেন্ডর নেটিভ ডেভেলপমেন্ট কিট (VNDK) শেয়ার্ড লাইব্রেরির উপর নির্ভর করতে পারে। একটি অ্যান্ড্রয়েড রিলিজের মধ্যে, নতুন করে বিল্ড করা VNDK শেয়ার্ড লাইব্রেরিগুলোকে অবশ্যই পূর্বে প্রকাশিত VNDK শেয়ার্ড লাইব্রেরিগুলোর সাথে ABI-সামঞ্জস্যপূর্ণ হতে হবে, যাতে ভেন্ডর মডিউলগুলো পুনরায় কম্পাইলেশন এবং রানটাইম ত্রুটি ছাড়াই সেই লাইব্রেরিগুলোর সাথে কাজ করতে পারে। অ্যান্ড্রয়েড রিলিজগুলোর মধ্যে VNDK লাইব্রেরিগুলো পরিবর্তিত হতে পারে এবং এক্ষেত্রে কোনো ABI নিশ্চয়তা থাকে না।
ABI সামঞ্জস্যতা নিশ্চিত করতে সাহায্য করার জন্য, অ্যান্ড্রয়েড ৯-এ একটি হেডার ABI চেকার অন্তর্ভুক্ত রয়েছে, যা পরবর্তী বিভাগগুলিতে বর্ণনা করা হয়েছে।
VNDK এবং ABI সম্মতি সম্পর্কে
VNDK হলো লাইব্রেরির একটি সীমাবদ্ধ সেট, যার সাথে ভেন্ডর মডিউলগুলো লিঙ্ক করতে পারে এবং যা শুধুমাত্র ফ্রেমওয়ার্ক-ভিত্তিক আপডেট সক্ষম করে। ABI কমপ্লায়েন্স বলতে একটি শেয়ার্ড লাইব্রেরির নতুন সংস্করণের সাথে ডাইনামিকভাবে লিঙ্ক করা কোনো মডিউলের প্রত্যাশিতভাবে কাজ করার ক্ষমতাকে বোঝায় (অর্থাৎ, এটি লাইব্রেরির পুরোনো সংস্করণের মতোই কাজ করে)।
রপ্তানিকৃত প্রতীক সম্পর্কে
একটি এক্সপোর্টেড সিম্বল (যা গ্লোবাল সিম্বল নামেও পরিচিত) বলতে এমন একটি সিম্বলকে বোঝায় যা নিম্নলিখিত সব শর্ত পূরণ করে:
- একটি শেয়ার্ড লাইব্রেরির পাবলিক হেডার দ্বারা এক্সপোর্ট করা হয়।
- শেয়ার্ড লাইব্রেরির সাথে সম্পর্কিত
.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; |
| অ্যান্ড্রয়েড.বিপি |
|---|
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 মধ্যে foo_t টাইপের একটি মেম্বার mfoo রয়েছে, যা 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&g<t;/BINDER_BITNES<S>/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এটিকে দেওয়া একটি ভার্সন স্ক্রিপ্ট অথবা শেয়ার্ড লাইব্রেরির সংশ্লিষ্ট.soফাইল ব্যবহার করে.sdumpফাইলগুলোকে প্রসেস করে একটি.lsdumpফাইল তৈরি করে, যা শেয়ার্ড লাইব্রেরির সমস্ত ABI তথ্য লগ করে।
চিত্র ২. .lsdumpফাইল তৈরি করা -
header-abi-diffএকটি.lsdumpফাইলকে একটি রেফারেন্স.lsdumpফাইলের সাথে তুলনা করে একটি ডিফারেন্স রিপোর্ট তৈরি করে, যা দুটি লাইব্রেরির ABI-গুলোর মধ্যেকার পার্থক্য তুলে ধরে।
চিত্র ৩. পার্থক্য প্রতিবেদন তৈরি করা
হেডার-এবিআই-ডাম্পার
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> #inclu<de foo_exported.h> bool Foo(int id, bar_t *bar_ptr) { if (i&&d > 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 সোর্স ফাইল foo.cpp এবং পাবলিক হেডারগুলো দ্বারা এক্সপোর্ট করা ABI তথ্য থাকে, উদাহরণস্বরূপ,
-
record_typesবলতে পাবলিক হেডারে সংজ্ঞায়িত স্ট্রাক্ট, ইউনিয়ন বা ক্লাসকে বোঝায়। প্রতিটি রেকর্ড টাইপে তার ফিল্ড, আকার, অ্যাক্সেস স্পেসিফায়ার, যে হেডার ফাইলে এটি সংজ্ঞায়িত করা হয়েছে এবং অন্যান্য অ্যাট্রিবিউট সম্পর্কে তথ্য থাকে। -
pointer_types। পাবলিক হেডারে থাকা এক্সপোর্ট করা রেকর্ড/ফাংশন দ্বারা প্রত্যক্ষ বা পরোক্ষভাবে ব্যবহৃত পয়েন্টার টাইপগুলো উল্লেখ করুন, সাথে পয়েন্টারটি যে টাইপকে নির্দেশ করে সেটিও (type_infoএরreferenced_typeফিল্ডের মাধ্যমে)। কোয়ালিফাইড টাইপ, বিল্ট-ইন C/C++ টাইপ, অ্যারে টাইপ এবং lvalue ও rvalue রেফারেন্স টাইপের জন্য অনুরূপ তথ্য.sdumpফাইলে লগ করা হয়। এই ধরনের তথ্য রিকার্সিভ ডিফারেন্সিং-এর সুযোগ করে দেয়। -
functionsপাবলিক হেডার দ্বারা এক্সপোর্ট করা ফাংশনগুলোকে বোঝায়। এগুলোতে ফাংশনের ম্যাঙ্গলড নাম, রিটার্ন টাইপ, প্যারামিটারগুলোর টাইপ, অ্যাক্সেস স্পেসিফায়ার এবং অন্যান্য অ্যাট্রিবিউট সম্পর্কিত তথ্যও থাকে।
হেডার-এবিআই-লিঙ্কার
header-abi-linker টুলটি header-abi-dumper দ্বারা উৎপাদিত অন্তর্বর্তী ফাইলগুলোকে ইনপুট হিসেবে গ্রহণ করে এবং তারপর সেই ফাইলগুলোকে লিঙ্ক করে:
| ইনপুট |
|
|---|---|
| আউটপুট | একটি ফাইল যা কোনো শেয়ার্ড লাইব্রেরির ABI বর্ণনা করে (উদাহরণস্বরূপ, libfoo.so.lsdump ফাইলটি libfoo এর ABI নির্দেশ করে)। |
টুলটি এটিকে দেওয়া সমস্ত ইন্টারমিডিয়েট ফাইলের টাইপ গ্রাফগুলিকে একত্রিত করে, এবং এক্ষেত্রে এটি বিভিন্ন ট্রান্সলেশন ইউনিটের মধ্যেকার এক-সংজ্ঞা (একই সম্পূর্ণ যোগ্য নাম সহ বিভিন্ন ট্রান্সলেশন ইউনিটে থাকা ব্যবহারকারী-সংজ্ঞায়িত টাইপ, যা শব্দার্থগতভাবে ভিন্ন হতে পারে) পার্থক্যগুলিও বিবেচনা করে। এরপর টুলটি এক্সপোর্ট করা সিম্বলগুলির একটি তালিকা তৈরি করার জন্য একটি ভার্সন স্ক্রিপ্ট অথবা শেয়ার্ড লাইব্রেরির ( .so ফাইল) .dynsym টেবিল পার্স করে।
উদাহরণস্বরূপ, libfoo foo.cpp এবং bar.cpp রয়েছে। libfoo এর সম্পূর্ণ লিঙ্ক করা ABI ডাম্প তৈরি করতে header-abi-linker নিম্নরূপে আহ্বান করা যেতে পারে:
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 এর চূড়ান্তভাবে তৈরি হওয়া ABI ডাম্প।
হেডার-এবিআই-ডিফ
header-abi-diff টুলটি দুটি লাইব্রেরির ABI-কে প্রতিনিধিত্বকারী দুটি .lsdump ফাইলের মধ্যে তুলনা করে এবং দুটি ABI-এর মধ্যকার পার্থক্য উল্লেখ করে একটি ডিফারেন্স রিপোর্ট তৈরি করে।
| ইনপুট |
|
|---|---|
| আউটপুট | তুলনা করা দুটি শেয়ার্ড লাইব্রেরির প্রদত্ত ABI-গুলোর মধ্যেকার পার্থক্য উল্লেখ করে একটি ডিফারেন্স রিপোর্ট। |
ABI diff ফাইলটি প্রোটোবাফ টেক্সট ফরম্যাটে রয়েছে। ভবিষ্যতের রিলিজগুলোতে এই ফরম্যাট পরিবর্তিত হতে পারে।
উদাহরণস্বরূপ, আপনার কাছে 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 libfoolibfoo.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 কে নির্দেশ করে, যেটি এক্সপোর্ট করা হয়েছিল এবং পরিবর্তিত হয়েছে।
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