অ্যান্ড্রয়েড ১২-এর বিল্ড সিস্টেমে এমন জাভা মডিউলগুলোর জন্য DEX ফাইলের (dexpreopt) কম্পাইলেশনে পরিবর্তন আনা হয়েছে, যেগুলোর <uses-library> ডিপেন্ডেন্সি রয়েছে। কিছু ক্ষেত্রে, এই বিল্ড সিস্টেমের পরিবর্তনগুলো বিল্ড ভেঙে দিতে পারে। এই ধরনের সমস্যার জন্য প্রস্তুত হতে এই পৃষ্ঠাটি ব্যবহার করুন এবং সেগুলো সমাধান ও প্রশমিত করতে এই পৃষ্ঠার পদ্ধতিগুলো অনুসরণ করুন।
Dexpreopt হলো জাভা লাইব্রেরি এবং অ্যাপের অ্যাহেড-অফ-টাইম কম্পাইলেশন প্রক্রিয়া। Dexpreopt বিল্ড টাইমে অন-হোস্ট-এ সম্পন্ন হয় ( dexopt-এর বিপরীতে, যা অন-ডিভাইস-এ সম্পন্ন হয়)। একটি জাভা মডিউল (একটি লাইব্রেরি বা একটি অ্যাপ) দ্বারা ব্যবহৃত শেয়ার্ড লাইব্রেরি ডিপেন্ডেন্সির কাঠামো তার ক্লাস লোডার কনটেক্সট (CLC) নামে পরিচিত। dexpreopt-এর সঠিকতা নিশ্চিত করার জন্য, বিল্ড-টাইম এবং রান-টাইম CLC অবশ্যই একই হতে হবে। বিল্ড-টাইম CLC হলো সেটি যা dex2oat কম্পাইলার dexpreopt-এর সময় ব্যবহার করে (এটি ODEX ফাইলগুলিতে রেকর্ড করা থাকে), এবং রান-টাইম CLC হলো সেই কনটেক্সট যেখানে প্রি-কম্পাইল করা কোড ডিভাইসে লোড করা হয়।
সঠিকতা এবং পারফরম্যান্স উভয় কারণেই এই বিল্ড-টাইম এবং রান-টাইম সিএলসি-গুলো অবশ্যই একই হতে হবে। সঠিকতার জন্য, ডুপ্লিকেট ক্লাসগুলো সামলানো প্রয়োজন। যদি রানটাইমের শেয়ার্ড লাইব্রেরি ডিপেন্ডেন্সিগুলো কম্পাইলেশনের জন্য ব্যবহৃত ডিপেন্ডেন্সিগুলো থেকে ভিন্ন হয়, তাহলে কিছু ক্লাস ভিন্নভাবে রিজলভ হতে পারে, যা সূক্ষ্ম রানটাইম বাগের কারণ হতে পারে। ডুপ্লিকেট ক্লাসের জন্য রানটাইম চেকের কারণে পারফরম্যান্সও প্রভাবিত হয়।
প্রভাবিত ব্যবহারের ক্ষেত্রসমূহ
এই পরিবর্তনগুলির দ্বারা প্রধানত প্রথম বুটই প্রভাবিত হয়: যদি ART বিল্ড-টাইম এবং রান-টাইম CLC-গুলির মধ্যে কোনো অমিল খুঁজে পায়, তবে এটি dexpreopt আর্টিফ্যাক্টগুলি বাতিল করে দেয় এবং তার পরিবর্তে dexopt চালায়। পরবর্তী বুটগুলির জন্য এটি ঠিক আছে, কারণ অ্যাপগুলিকে ব্যাকগ্রাউন্ডে ডিক্সপ্ট করে ডিস্কে সংরক্ষণ করা যায়।
অ্যান্ড্রয়েডের প্রভাবিত এলাকা
এর ফলে সেই সমস্ত জাভা অ্যাপ এবং লাইব্রেরি প্রভাবিত হয়, যেগুলোর রানটাইম নির্ভরতা অন্য জাভা লাইব্রেরির উপর রয়েছে। অ্যান্ড্রয়েডে হাজার হাজার অ্যাপ রয়েছে, এবং সেগুলোর মধ্যে শত শত অ্যাপ শেয়ার্ড লাইব্রেরি ব্যবহার করে। পার্টনাররাও এর দ্বারা প্রভাবিত হন, কারণ তাদের নিজস্ব লাইব্রেরি এবং অ্যাপ রয়েছে।
বিরতি পরিবর্তন
dexpreopt বিল্ড রুল তৈরি করার আগে বিল্ড সিস্টেমকে <uses-library> ডিপেন্ডেন্সিগুলো সম্পর্কে জানতে হয়। তবে, এটি সরাসরি ম্যানিফেস্ট অ্যাক্সেস করে এর ভেতরের <uses-library> ট্যাগগুলো পড়তে পারে না, কারণ বিল্ড রুল তৈরি করার সময় (পারফরম্যান্সের কারণে) বিল্ড সিস্টেমকে যথেচ্ছ ফাইল পড়ার অনুমতি দেওয়া হয় না। তাছাড়া, ম্যানিফেস্টটি একটি APK বা প্রি-বিল্ট-এর ভেতরে প্যাকেজ করা থাকতে পারে। সুতরাং, <uses-library> তথ্যটি অবশ্যই বিল্ড ফাইলগুলোতে ( Android.bp বা Android.mk ) উপস্থিত থাকতে হবে।
পূর্বে ART একটি বিকল্প পদ্ধতি ব্যবহার করত যা শেয়ার্ড লাইব্রেরির নির্ভরতাগুলোকে উপেক্ষা করত (যা &-classpath নামে পরিচিত)। এটি অনিরাপদ ছিল এবং সূক্ষ্ম বাগের কারণ হতো, তাই অ্যান্ড্রয়েড ১২-এ এই বিকল্প পদ্ধতিটি সরিয়ে ফেলা হয়েছে।
ফলস্বরূপ, যে জাভা মডিউলগুলো তাদের বিল্ড ফাইলে সঠিক <uses-library> তথ্য প্রদান করে না , সেগুলো বিল্ড ভেঙ্গেজ (বিল্ড-টাইম CLC অমিলের কারণে) অথবা ফার্স্ট-বুট টাইম রিগ্রেশন (বুট-টাইম CLC অমিলের পর dexopt-এর কারণে) ঘটাতে পারে।
অভিবাসন পথ
একটি ত্রুটিপূর্ণ বিল্ড ঠিক করতে এই ধাপগুলো অনুসরণ করুন:
একটি নির্দিষ্ট পণ্যের জন্য বিল্ড-টাইম চেক বিশ্বব্যাপী নিষ্ক্রিয় করতে সেটিং করুন
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := trueপ্রোডাক্ট মেকফাইলে। এটি বিল্ড ত্রুটিগুলি ঠিক করে (বিশেষ ক্ষেত্রগুলি ছাড়া, যা 'ত্রুটি সংশোধন ' বিভাগে তালিকাভুক্ত করা হয়েছে)। তবে, এটি একটি অস্থায়ী সমাধান, এবং এর ফলে বুট-টাইমে CLC অমিল এবং পরবর্তীতে dexopt হতে পারে।
আপনি বিশ্বব্যাপী বিল্ড-টাইম চেক নিষ্ক্রিয় করার আগে যে মডিউলগুলি ব্যর্থ হয়েছিল, সেগুলির বিল্ড ফাইলে প্রয়োজনীয়
<uses-library>তথ্য যোগ করে সেগুলি ঠিক করুন (বিস্তারিত জানার জন্য 'Fixing breakages ' দেখুন)। বেশিরভাগ মডিউলের জন্য এর জন্যAndroid.bpঅথবাAndroid.mkতে কয়েকটি লাইন যোগ করতে হয়।সমস্যাযুক্ত ক্ষেত্রগুলোর জন্য, প্রতিটি মডিউলের ভিত্তিতে বিল্ড-টাইম চেক এবং ডেক্সপ্রিঅপশন নিষ্ক্রিয় করুন। ডেক্সপ্রিঅপশন নিষ্ক্রিয় করুন, যাতে বুট করার সময় প্রত্যাখ্যাত হওয়া আর্টিফ্যাক্টগুলোর জন্য আপনার বিল্ডের সময় এবং স্টোরেজ নষ্ট না হয়।
ধাপ ১-এ সেট করা
PRODUCT_BROKEN_VERIFY_USES_LIBRARIESআনসেট করে বিল্ড-টাইম চেকটি বিশ্বব্যাপী পুনরায় সক্রিয় করুন; এই পরিবর্তনের পর বিল্ডটি ব্যর্থ হওয়া উচিত নয় (কারণ ধাপ ২ এবং ৩-এর জন্য)।ধাপ ৩-এ আপনি যে মডিউলগুলো নিষ্ক্রিয় করেছিলেন, সেগুলো এক এক করে ঠিক করুন, তারপর dexpreopt এবং
<uses-library>চেকটি পুনরায় সক্রিয় করুন। প্রয়োজনে বাগ রিপোর্ট করুন।
অ্যান্ড্রয়েড ১২-এ বিল্ড-টাইমে <uses-library> চেক বাধ্যতামূলক করা হয়েছে।
ভাঙা অংশ মেরামত করুন
নিম্নলিখিত বিভাগগুলিতে নির্দিষ্ট ধরণের ভাঙন মেরামত করার উপায় বলা হয়েছে।
বিল্ড ত্রুটি: CLC অমিল
বিল্ড সিস্টেম Android.bp বা Android.mk ফাইলের তথ্য এবং ম্যানিফেস্টের মধ্যে বিল্ড-টাইমে একটি সামঞ্জস্য পরীক্ষা করে। বিল্ড সিস্টেম ম্যানিফেস্ট পড়তে পারে না, কিন্তু এটি ম্যানিফেস্ট পড়ার জন্য (প্রয়োজনে একটি APK থেকে এটি এক্সট্র্যাক্ট করে) বিল্ড রুল তৈরি করতে পারে এবং ম্যানিফেস্টের <uses-library> ট্যাগগুলোকে বিল্ড ফাইলের <uses-library> তথ্যের সাথে তুলনা করতে পারে। যদি এই পরীক্ষা ব্যর্থ হয়, তাহলে এররটি দেখতে এইরকম হয়:
error: mismatch in the <uses-library> tags between the build system and the manifest:
- required libraries in build system: []
vs. in the manifest: [org.apache.http.legacy]
- optional libraries in build system: []
vs. in the manifest: [com.x.y.z]
- tags in the manifest (.../X_intermediates/manifest/AndroidManifest.xml):
<uses-library android:name="com.x.y.z"/>
<uses-library android:name="org.apache.http.legacy"/>
note: the following options are available:
- to temporarily disable the check on command line, rebuild with RELAX_USES_LIBRARY_CHECK=true (this will set compiler filter "verify" and disable AOT-compilation in dexpreopt)
- to temporarily disable the check for the whole product, set PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true in the product makefiles
- to fix the check, make build system properties coherent with the manifest
- see build/make/Changes.md for details
ত্রুটির বার্তা অনুযায়ী, জরুরি অবস্থার ওপর নির্ভর করে এর একাধিক সমাধান রয়েছে:
- সাময়িক সময়ের জন্য পুরো প্রোডাক্ট জুড়ে এই সমস্যার সমাধান করতে , প্রোডাক্টের মেকফাইলে
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := trueসেট করুন। বিল্ড-টাইম কোহেরেন্স চেক তখনও করা হয়, কিন্তু চেক ব্যর্থ হওয়ার অর্থ এই নয় যে বিল্ডও ব্যর্থ হবে। এর পরিবর্তে, চেক ব্যর্থ হলে বিল্ড সিস্টেম dex2oat কম্পাইলার ফিল্টারটিকে dexpreopt-এরverifyমোডে ডাউনগ্রেড করে, যা এই মডিউলের জন্য AOT-কম্পাইলেশন সম্পূর্ণরূপে নিষ্ক্রিয় করে দেয়। - দ্রুত এবং বিশ্বব্যাপী কমান্ড-লাইন সমাধানের জন্য,
RELAX_USES_LIBRARY_CHECK=trueএনভায়রনমেন্ট ভেরিয়েবলটি ব্যবহার করুন। এর প্রভাবPRODUCT_BROKEN_VERIFY_USES_LIBRARIESএর মতোই, কিন্তু এটি কমান্ড-লাইনে ব্যবহারের জন্য তৈরি। এই এনভায়রনমেন্ট ভেরিয়েবলটি প্রোডাক্ট ভেরিয়েবলকে ওভাররাইড করে। - ত্রুটির মূল কারণ সমাধান করার জন্য, ম্যানিফেস্টে থাকা
<uses-library>ট্যাগগুলো সম্পর্কে বিল্ড সিস্টেমকে অবহিত করুন। ত্রুটির বার্তাটি পরীক্ষা করলে বোঝা যায় কোন লাইব্রেরিগুলো সমস্যার কারণ (যেমনটিAndroidManifest.xmlঅথবা `aapt dump badging $APK | grep uses-libraryকমান্ড দিয়ে পরীক্ষা করা যায় এমন একটি APK-এর ভেতরের ম্যানিফেস্ট পরীক্ষা করেও জানা যায়)।
Android.bp মডিউলগুলির জন্য:
মডিউলের
libsপ্রপার্টিতে অনুপস্থিত লাইব্রেরিটি খুঁজুন। যদি এটি সেখানে থাকে, Soong সাধারণত এই বিশেষ ক্ষেত্রগুলি ছাড়া এই ধরনের লাইব্রেরি স্বয়ংক্রিয়ভাবে যোগ করে নেয়:- লাইব্রেরিটি কোনো SDK লাইব্রেরি নয় (এটি
java_sdk_libraryপরিবর্তেjava_libraryহিসেবে সংজ্ঞায়িত করা হয়েছে)। - লাইব্রেরিটির নাম (ম্যানিফেস্টে) এবং এর মডিউল নাম (বিল্ড সিস্টেমে) ভিন্ন।
সাময়িকভাবে এটি ঠিক করতে,
Android.bpলাইব্রেরি ডেফিনিশনেprovides_uses_lib: "<library-name>"যোগ করুন। দীর্ঘস্থায়ী সমাধানের জন্য, মূল সমস্যাটি সমাধান করুন: লাইব্রেরিটিকে একটি SDK লাইব্রেরিতে রূপান্তর করুন, অথবা এর মডিউলটির নাম পরিবর্তন করুন।- লাইব্রেরিটি কোনো SDK লাইব্রেরি নয় (এটি
যদি পূর্ববর্তী ধাপে কোনো সমাধান না হয়, তাহলে মডিউলের
Android.bpসংজ্ঞায় প্রয়োজনীয় লাইব্রেরির জন্যuses_libs: ["<library-module-name>"]অথবা ঐচ্ছিক লাইব্রেরির জন্যoptional_uses_libs: ["<library-module-name>"]যোগ করুন। এই প্রোপার্টিগুলো মডিউলের নামগুলোর একটি তালিকা গ্রহণ করে। তালিকায় লাইব্রেরিগুলোর আপেক্ষিক ক্রম অবশ্যই ম্যানিফেস্টের ক্রমের সাথে একই হতে হবে।
Android.mk মডিউলগুলির জন্য:
যাচাই করুন যে লাইব্রেরির ম্যানিফেস্টে থাকা লাইব্রেরির নামটি তার বিল্ড সিস্টেমের মডিউল নাম থেকে আলাদা কিনা। যদি তা হয়, তবে সাময়িকভাবে এর সমাধান করতে লাইব্রেরির
Android.mkফাইলেLOCAL_PROVIDES_USES_LIBRARY := <library-name>যোগ করুন, অথবা লাইব্রেরিরAndroid.bpফাইলেprovides_uses_lib: "<library-name>"যোগ করুন (উভয় ক্ষেত্রেই এটি সম্ভব, কারণ একটিAndroid.mkমডিউল একটিAndroid.bpলাইব্রেরির উপর নির্ভরশীল হতে পারে)। দীর্ঘমেয়াদী সমাধানের জন্য, মূল সমস্যাটি সমাধান করুন: লাইব্রেরি মডিউলটির নাম পরিবর্তন করুন।মডিউলের
Android.mkসংজ্ঞায়, প্রয়োজনীয় লাইব্রেরির জন্যLOCAL_USES_LIBRARIES := <library-module-name>এবং ঐচ্ছিক লাইব্রেরির জন্যLOCAL_OPTIONAL_USES_LIBRARIES := <library-module-name>যোগ করুন। এই প্রোপার্টিগুলো মডিউলের নামগুলোর একটি তালিকা গ্রহণ করে। তালিকায় লাইব্রেরিগুলোর আপেক্ষিক ক্রম অবশ্যই ম্যানিফেস্টের মতোই হতে হবে।
বিল্ড ত্রুটি: অজানা লাইব্রেরি পাথ
যদি বিল্ড সিস্টেম কোনো <uses-library> DEX জার-এর পাথ খুঁজে না পায় (হোস্টের বিল্ড-টাইম পাথ অথবা ডিভাইসের ইনস্টল পাথ), তবে এটি সাধারণত বিল্ডটি ব্যর্থ করে দেয়। পাথ খুঁজে না পাওয়ার অর্থ হতে পারে যে লাইব্রেরিটি কোনো অপ্রত্যাশিত উপায়ে কনফিগার করা হয়েছে। সমস্যাযুক্ত মডিউলটির জন্য dexpreopt নিষ্ক্রিয় করে সাময়িকভাবে বিল্ডটি ঠিক করুন।
Android.bp (মডিউল বৈশিষ্ট্য):
enforce_uses_libs: false,
dex_preopt: {
enabled: false,
},
Android.mk (মডিউল ভেরিয়েবল):
LOCAL_ENFORCE_USES_LIBRARIES := false
LOCAL_DEX_PREOPT := false
যেকোনো অসমর্থিত পরিস্থিতি তদন্ত করার জন্য একটি বাগ রিপোর্ট করুন।
বিল্ড ত্রুটি: লাইব্রেরি নির্ভরতা অনুপস্থিত
মডিউল Y-এর ম্যানিফেস্ট থেকে <uses-library> X-কে Y-এর বিল্ড ফাইলে যোগ করার চেষ্টা করলে, X নামক ডিপেন্ডেন্সিটি অনুপস্থিত থাকার কারণে একটি বিল্ড এরর হতে পারে।
এটি Android.bp মডিউলগুলির জন্য একটি নমুনা ত্রুটি বার্তা:
"Y" depends on undefined module "X"
এটি Android.mk মডিউলগুলির জন্য একটি নমুনা ত্রুটি বার্তা:
'.../JAVA_LIBRARIES/com.android.X_intermediates/dexpreopt.config', needed by '.../APPS/Y_intermediates/enforce_uses_libraries.status', missing and no known rule to make it
এই ধরনের ত্রুটির একটি সাধারণ কারণ হলো যখন কোনো লাইব্রেরির নাম বিল্ড সিস্টেমে থাকা তার সংশ্লিষ্ট মডিউলের নামের থেকে ভিন্ন হয়। উদাহরণস্বরূপ, যদি ম্যানিফেস্টের <uses-library> এন্ট্রিটি com.android.X হয়, কিন্তু লাইব্রেরি মডিউলের নাম শুধু X হয়, তবে এটি একটি ত্রুটির কারণ হয়। এই সমস্যাটি সমাধান করতে, বিল্ড সিস্টেমকে জানান যে X নামের মডিউলটি com.android.X নামের একটি <uses-library> প্রদান করে।
এটি Android.bp লাইব্রেরির (মডিউল প্রপার্টি) একটি উদাহরণ:
provides_uses_lib: “com.android.X”,
এটি Android.mk লাইব্রেরির (মডিউল ভেরিয়েবল) একটি উদাহরণ:
LOCAL_PROVIDES_USES_LIBRARY := com.android.X
বুট-টাইম সিএলসি অমিল
প্রথম বুট করার সময়, নিচে দেখানো অনুযায়ী CLC অমিল সম্পর্কিত বার্তাগুলির জন্য লগক্যাট অনুসন্ধান করুন:
$ adb wait-for-device && adb logcat \
| grep -E 'ClassLoaderContext [a-z ]+ mismatch' -A1
আউটপুটে এখানে দেখানো ধরনের বার্তা থাকতে পারে:
[...] W system_server: ClassLoaderContext shared library size mismatch Expected=..., found=... (PCL[]... | PCL[]...)
[...] I PackageDexOptimizer: Running dexopt (dexoptNeeded=1) on: ...
যদি আপনি একটি CLC অমিলের সতর্কতা পান, তাহলে ত্রুটিপূর্ণ মডিউলটির জন্য একটি dexopt কমান্ড খুঁজুন। এটি ঠিক করতে, নিশ্চিত করুন যে মডিউলটির জন্য বিল্ড-টাইম চেকটি সফল হয়েছে। যদি তাতেও কাজ না হয়, তাহলে আপনারটি হয়তো একটি বিশেষ ক্ষেত্র যা বিল্ড সিস্টেম দ্বারা সমর্থিত নয় (যেমন এমন একটি অ্যাপ যা কোনো লাইব্রেরি নয়, বরং অন্য একটি APK লোড করে)। বিল্ড সিস্টেম সব ক্ষেত্র সামলাতে পারে না, কারণ বিল্ড করার সময় এটা নিশ্চিতভাবে জানা অসম্ভব যে অ্যাপটি রানটাইমে কী লোড করবে।
ক্লাস লোডার প্রসঙ্গ
সিএলসি (CLC) হলো একটি বৃক্ষ-সদৃশ কাঠামো যা ক্লাস-লোডার ক্রমবিন্যাস বর্ণনা করে। বিল্ড সিস্টেম সিএলসি-কে একটি সংকীর্ণ অর্থে ব্যবহার করে (এটি শুধুমাত্র লাইব্রেরি অন্তর্ভুক্ত করে, এপিকে বা কাস্টম-ক্লাস লোডার নয়): এটি লাইব্রেরির একটি বৃক্ষ যা একটি লাইব্রেরি বা অ্যাপের সমস্ত <uses-library> নির্ভরতার ট্রানজিটিভ ক্লোজারকে উপস্থাপন করে। একটি সিএলসি-এর শীর্ষ-স্তরের উপাদানগুলো হলো ম্যানিফেস্টে (ক্লাসপাথ) নির্দিষ্ট করা সরাসরি <uses-library> নির্ভরতাগুলো। একটি সিএলসি বৃক্ষের প্রতিটি নোড হলো একটি <uses-library> নোড যার নিজস্ব <uses-library> সাব-নোড থাকতে পারে।
যেহেতু <uses-library> ডিপেন্ডেন্সিগুলো একটি ডিরেক্টেড অ্যাসাইক্লিক গ্রাফ, এবং অগত্যা একটি ট্রি নয়, তাই CLC-তে একই লাইব্রেরির জন্য একাধিক সাবট্রি থাকতে পারে। অন্য কথায়, CLC হলো ডিপেন্ডেন্সি গ্রাফের একটি ট্রি-তে "উন্মোচিত" রূপ। এই পুনরাবৃত্তি শুধুমাত্র যৌক্তিক স্তরে ঘটে; প্রকৃত অন্তর্নিহিত ক্লাস লোডারগুলোর কোনো পুনরাবৃত্তি হয় না (রানটাইমে প্রতিটি লাইব্রেরির জন্য একটিমাত্র ক্লাস লোডার ইনস্ট্যান্স থাকে)।
লাইব্রেরি বা অ্যাপ দ্বারা ব্যবহৃত জাভা ক্লাসগুলো রিজলভ করার সময়, CLC লাইব্রেরিগুলোর লুকআপ অর্ডার নির্ধারণ করে। এই লুকআপ অর্ডারটি গুরুত্বপূর্ণ, কারণ লাইব্রেরিতে সদৃশ ক্লাস থাকতে পারে এবং সেক্ষেত্রে ক্লাসটি প্রথম মিল খুঁজে পাওয়ার পর রিজলভ করা হয়।
ডিভাইসে (রান-টাইম) সিএলসি
PackageManager ( frameworks/base এ অবস্থিত) ডিভাইসে একটি জাভা মডিউল লোড করার জন্য একটি সিএলসি (CLC) তৈরি করে। এটি মডিউলের ম্যানিফেস্টের <uses-library> ট্যাগে তালিকাভুক্ত লাইব্রেরিগুলোকে শীর্ষ-স্তরের সিএলসি উপাদান হিসেবে যুক্ত করে।
প্রতিটি ব্যবহৃত লাইব্রেরির জন্য, PackageManager তার সমস্ত <uses-library> ডিপেন্ডেন্সি (যা সেই লাইব্রেরির ম্যানিফেস্টে ট্যাগ হিসেবে নির্দিষ্ট করা থাকে) সংগ্রহ করে এবং প্রতিটি ডিপেন্ডেন্সির জন্য একটি নেস্টেড সিএলসি (CLC) যোগ করে। এই প্রক্রিয়াটি পুনরাবৃত্তিমূলকভাবে চলতে থাকে যতক্ষণ না নির্মিত সিএলসি ট্রি-এর সমস্ত লিফ নোড <uses-library> ডিপেন্ডেন্সিবিহীন লাইব্রেরিতে পরিণত হয়।
PackageManager শুধুমাত্র শেয়ার্ড লাইব্রেরি সম্পর্কে অবগত। এই ক্ষেত্রে 'শেয়ার্ড'-এর সংজ্ঞা এর সাধারণ অর্থ থেকে ভিন্ন (যেমন শেয়ার্ড বনাম স্ট্যাটিক)। অ্যান্ড্রয়েডে, জাভা শেয়ার্ড লাইব্রেরি হলো সেইসব লাইব্রেরি যা ডিভাইসে ইনস্টল করা XML কনফিগে ( /system/etc/permissions/platform.xml ) তালিকাভুক্ত থাকে। প্রতিটি এন্ট্রিতে একটি শেয়ার্ড লাইব্রেরির নাম, তার DEX জার ফাইলের পাথ এবং ডিপেন্ডেন্সির একটি তালিকা থাকে (অন্যান্য শেয়ার্ড লাইব্রেরি যা এটি রানটাইমে ব্যবহার করে এবং এর ম্যানিফেস্টে <uses-library> ট্যাগে উল্লেখ করে)।
অন্য কথায়, তথ্যের দুটি উৎস রয়েছে যা PackageManager রানটাইমে সিএলসি (CLC) তৈরি করতে সাহায্য করে: ম্যানিফেস্টের <uses-library> ট্যাগ এবং এক্সএমএল (XML) কনফিগারেশনে থাকা শেয়ার্ড লাইব্রেরি নির্ভরতা।
অন-হোস্ট (বিল্ড-টাইম) সিএলসি
শুধুমাত্র কোনো লাইব্রেরি বা অ্যাপ লোড করার সময়ই নয়, কোনো কিছু কম্পাইল করার সময়েও CLC-এর প্রয়োজন হয়। কম্পাইলেশন ডিভাইসে (dexopt) অথবা বিল্ড চলাকালীন (dexpreopt) হতে পারে। যেহেতু dexopt ডিভাইসে সম্পন্ন হয়, তাই এটি PackageManager মতোই একই তথ্য (ম্যানিফেস্ট এবং শেয়ার্ড লাইব্রেরি ডিপেন্ডেন্সি) পায়। কিন্তু, Dexpreopt হোস্টে এবং সম্পূর্ণ ভিন্ন একটি পরিবেশে সম্পন্ন হয়, এবং এটিকে বিল্ড সিস্টেম থেকে একই তথ্য সংগ্রহ করতে হয়।
সুতরাং, dexpreopt দ্বারা ব্যবহৃত বিল্ড-টাইম CLC এবং PackageManager দ্বারা ব্যবহৃত রান-টাইম CLC একই জিনিস, কিন্তু দুটি ভিন্ন উপায়ে গণনা করা হয়।
বিল্ড-টাইম এবং রান-টাইম CLC অবশ্যই একই হতে হবে, অন্যথায় dexpreopt দ্বারা তৈরি AOT-কম্পাইল করা কোড বাতিল হয়ে যায়। বিল্ড-টাইম এবং রান-টাইম CLC-এর সমতা পরীক্ষা করার জন্য, dex2oat কম্পাইলার *.odex ফাইলগুলিতে (OAT ফাইল হেডারের classpath ফিল্ডে) বিল্ড-টাইম CLC রেকর্ড করে। সংরক্ষিত CLC খুঁজে পেতে, এই কমান্ডটি ব্যবহার করুন:
oatdump --oat-file=<FILE> | grep '^classpath = '
বুট করার সময় লগক্যাটে বিল্ড-টাইম এবং রান-টাইম CLC অমিলের রিপোর্ট করা হয়। এই কমান্ডটি দিয়ে এটি অনুসন্ধান করুন:
logcat | grep -E 'ClassLoaderContext [az ]+ mismatch'
অমিল পারফরম্যান্সের জন্য ক্ষতিকর, কারণ এটি লাইব্রেরি বা অ্যাপটিকে হয় ডিএক্সঅপশন করতে, অথবা অপটিমাইজেশন ছাড়াই চলতে বাধ্য করে (উদাহরণস্বরূপ, অ্যাপটির কোডকে APK থেকে মেমরিতে এক্সট্র্যাক্ট করার প্রয়োজন হতে পারে, যা একটি অত্যন্ত ব্যয়বহুল প্রক্রিয়া)।
একটি শেয়ার্ড লাইব্রেরি ঐচ্ছিক বা আবশ্যক হতে পারে। dexpreopt-এর দৃষ্টিকোণ থেকে, একটি আবশ্যক লাইব্রেরি বিল্ড করার সময় অবশ্যই উপস্থিত থাকতে হবে (এর অনুপস্থিতি একটি বিল্ড এরর)। একটি ঐচ্ছিক লাইব্রেরি বিল্ড করার সময় উপস্থিত বা অনুপস্থিত থাকতে পারে: যদি উপস্থিত থাকে, তবে এটিকে CLC-তে যোগ করা হয়, dex2oat-এ পাঠানো হয় এবং *.odex ফাইলে রেকর্ড করা হয়। যদি একটি ঐচ্ছিক লাইব্রেরি অনুপস্থিত থাকে, তবে এটিকে বাদ দেওয়া হয় এবং CLC-তে যোগ করা হয় না। যদি বিল্ড-টাইম এবং রান-টাইম স্ট্যাটাসের মধ্যে অমিল থাকে (যেমন, ঐচ্ছিক লাইব্রেরিটি এক ক্ষেত্রে উপস্থিত, কিন্তু অন্য ক্ষেত্রে নয়), তাহলে বিল্ড-টাইম এবং রান-টাইম CLC মেলে না এবং কম্পাইল করা কোডটি বাতিল হয়ে যায়।
উন্নত বিল্ড সিস্টেমের বিবরণ (ম্যানিফেস্ট ফিক্সার)
কখনও কখনও কোনো লাইব্রেরি বা অ্যাপের সোর্স ম্যানিফেস্টে <uses-library> ট্যাগগুলো অনুপস্থিত থাকে। উদাহরণস্বরূপ, এমনটা হতে পারে যদি লাইব্রেরি বা অ্যাপটির কোনো একটি ট্রানজিটিভ ডিপেন্ডেন্সি অন্য কোনো <uses-library> ট্যাগ ব্যবহার করা শুরু করে, এবং সেটিকে অন্তর্ভুক্ত করার জন্য লাইব্রেরি বা অ্যাপটির ম্যানিফেস্ট আপডেট করা না হয়।
Soong একটি নির্দিষ্ট লাইব্রেরি বা অ্যাপের জন্য কিছু অনুপস্থিত <uses-library> ট্যাগ স্বয়ংক্রিয়ভাবে গণনা করতে পারে, কারণ SDK লাইব্রেরিগুলো সেই লাইব্রেরি বা অ্যাপের ট্রানজিটিভ ডিপেন্ডেন্সি ক্লোজারের মধ্যে থাকে। এই ক্লোজারটি প্রয়োজন, কারণ লাইব্রেরিটি (বা অ্যাপটি) এমন একটি স্ট্যাটিক লাইব্রেরির উপর নির্ভর করতে পারে যা আবার একটি SDK লাইব্রেরির উপর নির্ভরশীল, এবং সম্ভবত এটি পরোক্ষভাবে অন্য কোনো লাইব্রেরির উপরও নির্ভর করতে পারে।
সব <uses-library> ট্যাগ এভাবে গণনা করা যায় না, কিন্তু যখন সম্ভব হয়, Soong-কে স্বয়ংক্রিয়ভাবে ম্যানিফেস্ট এন্ট্রি যোগ করতে দেওয়াই শ্রেয়; এতে ভুলের সম্ভাবনা কম থাকে এবং রক্ষণাবেক্ষণ সহজ হয়। উদাহরণস্বরূপ, যখন অনেক অ্যাপ একটি স্ট্যাটিক লাইব্রেরি ব্যবহার করে যা একটি নতুন <uses-library> ডিপেন্ডেন্সি যোগ করে, তখন সমস্ত অ্যাপ আপডেট করতে হয়, যা রক্ষণাবেক্ষণের জন্য কঠিন।