গ্রেডেল নির্ভরতা রেজোলিউশন

আপনার বিল্ড ফাইলগুলি আপনার প্রত্যক্ষ নির্ভরতা নির্দিষ্ট করে, তবে এই নির্ভরতাগুলির প্রতিটিতে অন্যের প্রয়োজন হতে পারে। এই ট্রানজিটিভ নির্ভরতাগুলি আপনার সামগ্রিক নির্ভরতা গ্রাফকে দ্রুত বৃদ্ধি করে, প্রায়শই বিরোধপূর্ণ সংস্করণগুলির সাথে।

যখন minor (নতুন বৈশিষ্ট্য) বা patch (বাগ সংশোধন) অংশগুলি পরিবর্তিত হয়, তখনও লাইব্রেরিটি সামঞ্জস্যপূর্ণ হতে পারে এবং আপনার অ্যাপ্লিকেশনকে প্রভাবিত করার সম্ভাবনা কম থাকে।

উদাহরণস্বরূপ, ধরুন আপনার অ্যাপ্লিকেশনটি লাইব্রেরি A এবং লাইব্রেরি B এর উপর নির্ভর করে, যা লাইব্রেরি C এর বিভিন্ন সংস্করণের উপর নির্ভর করে।

আপনার অ্যাপ লাইব্রেরি A এবং লাইব্রেরি B-এর উপর নির্ভর করে, যা লাইব্রেরি C-এর বিভিন্ন সংস্করণের উপর নির্ভর করে। Gradle লাইব্রেরি C-এর নতুন সংস্করণ বেছে নেয়।
চিত্র 1. একটি ট্রানজিটিভ সংস্করণ দ্বন্দ্ব। Gradle নতুন সংস্করণে সমাধান করে (ডিফল্টরূপে)।

এই ক্ষেত্রে, গ্রেডল ডিফল্টরূপে লাইব্রেরি C-এর নতুন সংস্করণ বেছে নেয়, যা সংকলন বা রানটাইম সমস্যা সৃষ্টি করতে পারে। এই উদাহরণে, লাইব্রেরি সি 2.1.1 তে সমাধান করা হয়েছে, তবে মনে রাখবেন যে লাইব্রেরি A অনুরোধ করেছে লাইব্রেরি C 1.0.3। সংস্করণ নম্বরের প্রধান অংশ পরিবর্তিত হয়েছে, যা অসঙ্গতিপূর্ণ পরিবর্তনগুলি নির্দেশ করে, যেমন সরানো ফাংশন বা প্রকার। এর ফলে লাইব্রেরি A থেকে করা কলগুলি ক্র্যাশ হতে পারে।

আপনার অ্যাপে সরাসরি নির্ভরতা থাকতে পারে যা ট্রানজিটিভ নির্ভরতাও।

আপনার অ্যাপ লাইব্রেরি A এবং লাইব্রেরি C এর উপর নির্ভর করে। লাইব্রেরি A লাইব্রেরি C এর একটি নতুন সংস্করণের উপর নির্ভর করে। Gradle লাইব্রেরি C-এর নতুন সংস্করণ বেছে নেয়।
চিত্র 2. আরেকটি ট্রানজিটিভ সংস্করণ দ্বন্দ্ব। এখানে, Gradle ট্রানজিটিভ সংস্করণে সমাধান করে, এবং আপনার অ্যাপ্লিকেশন সেই নতুন সংস্করণটি দেখতে পায়।

এই ধরনের ক্ষেত্রে, নতুন ট্রানজিটিভ নির্ভরতা আপনার অ্যাপে সরাসরি অনুরোধ করা সংস্করণটিকে ওভাররাইড করতে পারে।

Gradle প্রতিটি নির্ভরতার নতুন সংস্করণ নির্ধারণ করতে গ্রাফে সমস্ত নির্ভরতার জন্য সমস্ত প্রার্থী সংস্করণ দেখে। প্রতিটি নির্ভরতা Gradle এর কোন সংস্করণগুলি সমাধান করেছে তা নির্ধারণ করতে আপনি প্রাথমিক Gradle কার্য এবং আরও উন্নত সরঞ্জাম ব্যবহার করতে পারেন। এই রেজোলিউশনের পরিবর্তনগুলির তুলনা করা আপনার আপগ্রেডের ঝুঁকিগুলি বোঝার এবং হ্রাস করার মূল চাবিকাঠি।

উদাহরণস্বরূপ, আপনি আপনার অ্যাপ মডিউল দ্বারা ব্যবহৃত সমস্ত নির্ভরতার একটি ট্রি প্রদর্শন করতে ./gradlew app:dependencies চালানোর মাধ্যমে Gradle dependencies কাজটি ব্যবহার করতে পারেন। চিত্র 2 এ দেখানো লাইব্রেরি ব্যবহার করে এমন একটি অ্যাপ্লিকেশনের বিরুদ্ধে এটি চালানো হচ্ছে, আমরা দেখতে পাচ্ছি

1: releaseRuntimeClasspath - Runtime classpath of /release.
2: +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0
3: |    +--- ... (omitted for brevity) ...
4: +--- com.sample:library.a:1.2.3
5: |    +--- com.sample:library.c:2.1.1
6: |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
7: |    \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
8: +--- com.sample:library.c:1.4.1 -> 2.1.1 (*)

প্রতিবেদনের এই অংশটি releaseRuntimeClasspath কনফিগারেশনের জন্য সমাধান করা কিছু নির্ভরতা দেখায়।

যখনই আপনি দেখেন -> আপনার নির্ভরতা প্রতিবেদনে, একজন অনুরোধকারী (আপনার অ্যাপ্লিকেশন বা অন্য লাইব্রেরি) সেই নির্ভরতার একটি সংস্করণ ব্যবহার করে যা এটি আশা করছে না। অনেক ক্ষেত্রে, এটি কোন সমস্যা সৃষ্টি করে না, কারণ বেশিরভাগ লাইব্রেরি পশ্চাদপদ সামঞ্জস্যের জন্য লেখা হয়। যাইহোক, কিছু লাইব্রেরি অসামঞ্জস্যপূর্ণ পরিবর্তন করতে পারে, এবং এই প্রতিবেদনটি আপনাকে আপনার অ্যাপ্লিকেশনের আচরণের সাথে নতুন সমস্যাগুলি কোথা থেকে আসছে তা নির্ধারণ করতে সহায়তা করতে পারে।

Gradle-এর নির্ভরতা রিপোর্টিং ব্যবহার করার বিষয়ে আরও বিশদ বিবরণ ভিউ এবং ডিবাগ ডিপেন্ডেন্সিতে পাওয়া যাবে।

আপনি অনুরোধ করা সংস্করণগুলি সরাসরি নির্দিষ্ট করতে পারেন, একটি সংস্করণ ক্যাটালগে বা একটি বিল অফ ম্যাটেরিয়ালস (BOM) এ।

সরাসরি সংস্করণ স্পেসিফিকেশন রেজোলিউশন

আপনার নির্দিষ্ট করা নির্ভরতার সংস্করণগুলি সংস্করণ রেজোলিউশনের জন্য প্রার্থী হয়ে ওঠে।

উদাহরণস্বরূপ, আপনার app/build.gradle.kts এ নির্ভরতা হিসাবে androidx.compose.ui:ui লাইব্রেরির সংস্করণ 1.7.3 অনুরোধ করতে:

dependencies {
    implementation("androidx.compose.ui:ui:1.7.3")
}

সংস্করণ 1.7.3 একটি প্রার্থী সংস্করণ হয়ে ওঠে। Gradle 1.7.3 এবং ট্রানজিটিভ নির্ভরতা দ্বারা অনুরোধ করা একই লাইব্রেরির অন্যান্য সংস্করণগুলির মধ্যে সর্বশেষ সংস্করণে সমাধান করে।

সংস্করণ ক্যাটালগ রেজোলিউশন

সংস্করণ ক্যাটালগ আপনার অ্যাপ্লিকেশন জুড়ে ব্যবহৃত নির্ভরতা সংস্করণ ট্র্যাক করতে ভেরিয়েবল সংজ্ঞায়িত করে। আপনি যদি সংস্করণ ক্যাটালগ থেকে একটি ভেরিয়েবল ব্যবহার করেন, তবে সেই ভেরিয়েবলের নির্দিষ্ট নির্ভরতাগুলি সংস্করণ রেজোলিউশনের প্রার্থীদের সাথে যোগ করা হয়। সংস্করণ ক্যাটালগে অব্যবহৃত ভেরিয়েবল উপেক্ষা করা হয়।

উদাহরণস্বরূপ, আপনার gradle/libs.versions.toml ফাইলে নির্ভরতা হিসাবে androidx.compose.ui:ui এর সংস্করণ 1.7.3 নির্দিষ্ট করতে:

[versions]
ui = "1.7.3"

[libraries]
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "ui" }

এটি লাইব্রেরির প্রতিনিধিত্ব করার জন্য libs.androidx.compose.ui নামের একটি ভেরিয়েবলকে সংজ্ঞায়িত করে। এই সংস্করণটিকে প্রার্থী হিসাবে বিবেচনা করা হয় না যদি না আপনি সেই ভেরিয়েবলটি একটি নির্ভরতা নির্দিষ্ট করতে ব্যবহার করেন।

আপনার app/build.gradle.kts এ লাইব্রেরি এবং এর সংস্করণের জন্য অনুরোধ করতে:

dependencies {
    implementation(libs.androidx.compose.ui)
}

Gradle সরাসরি স্পেসিফিকেশনের জন্য একইভাবে সমাধান করে।

বস্তুর বিল (BOM) রেজোলিউশন

BOM-এ উপস্থিত সমস্ত লাইব্রেরির সংস্করণগুলি সংস্করণ রেজোলিউশনের প্রার্থী হয়ে ওঠে। মনে রাখবেন যে লাইব্রেরিগুলিকে নির্ভরতা হিসাবে ব্যবহার করা হয় শুধুমাত্র যদি প্রত্যক্ষ বা পরোক্ষ হিসাবে নির্দিষ্ট করা হয়। BOM-এর অন্যান্য লাইব্রেরি উপেক্ষা করা হয়।

BOM সংস্করণগুলি আপনার সরাসরি নির্ভরতা এবং সেইসাথে BOM-এ উপস্থিত সমস্ত ট্রানজিটিভ নির্ভরতাকে প্রভাবিত করে।

উদাহরণস্বরূপ, আপনার app/build.gradle.ktsপ্ল্যাটফর্ম নির্ভরতা হিসাবে একটি BOM নির্দিষ্ট করুন:

dependencies {
    implementation(platform("androidx.compose:compose-bom:2024.10.00"))
    implementation("androidx.compose.ui:ui")
}

আপনি নির্ভরতা হিসাবে ব্যবহার করতে চান এমন যেকোন লাইব্রেরিগুলির সংস্করণ স্পেসিফিকেশনের প্রয়োজন নেই; অনুরোধ করা সংস্করণ BOM থেকে আসে।

মনে রাখবেন যে আপনি BOM এবং লাইব্রেরির জন্য ভেরিয়েবল তৈরি করতে একটি সংস্করণ ক্যাটালগও ব্যবহার করতে পারেন। BOM নির্ভরতায় প্রদর্শিত লাইব্রেরির সংস্করণ ক্যাটালগে সংস্করণ নম্বরগুলি বাদ দিন।

উদাহরণস্বরূপ, আপনার সংস্করণ ক্যাটালগে BOM এবং এর সংস্করণ নম্বর রয়েছে, কিন্তু আপনি BOM থেকে উল্লেখ করা লাইব্রেরির জন্য একটি সংস্করণ নির্দিষ্ট করে না:

[versions]
composeBom = "2024.10.00"

[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }

আপনার app/build.gradle.kts সংস্করণ ক্যাটালগে সংজ্ঞায়িত ভেরিয়েবল ব্যবহার করে BOM এবং লাইব্রেরি উল্লেখ করে:

dependencies {
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.compose.ui)
}

BOM-এ নির্দিষ্ট করা সেই লাইব্রেরির সংস্করণটি Gradle এর রেজোলিউশনের প্রার্থী হয়ে ওঠে। আরও, BOM-এ নির্দিষ্ট করা অন্যান্য সমস্ত লাইব্রেরি সংস্করণ প্রার্থী সংস্করণে পরিণত হয়, আপনি সরাসরি নির্ভরতা হিসাবে ব্যবহার করুন বা না করুন।

উদাহরণ স্বরূপ, ধরুন একটি BOM লাইব্রেরি A, B, এবং C-এর জন্য সংস্করণ নির্দিষ্ট করে। আপনার অ্যাপ্লিকেশন সরাসরি লাইব্রেরি Aকে নির্ভরতা হিসেবে ব্যবহার করতে চায়, সেইসাথে লাইব্রেরি D। লাইব্রেরি D লাইব্রেরি Bকে নির্ভরতা হিসেবে ব্যবহার করে। কিছুই লাইব্রেরি সি ব্যবহার করে না।

একটি BOM লাইব্রেরি A, B, এবং C এর সংস্করণ অন্তর্ভুক্ত করে। আপনার অ্যাপ্লিকেশন নির্ভরতা হিসাবে A এবং D লাইব্রেরি ব্যবহার করে। লাইব্রেরি ডি নির্ভরতা হিসাবে লাইব্রেরি বি ব্যবহার করে। লাইব্রেরি সি এই অ্যাপ্লিকেশনটিতে প্রত্যক্ষ বা পরোক্ষভাবে ব্যবহার করা হয় না।
চিত্র 3. BOM দৃশ্যকল্প।

লাইব্রেরি A, B এবং D হল অ্যাপ্লিকেশনে নির্ভরশীলতা; লাইব্রেরি সি উপেক্ষা করা হয়। Gradle প্রার্থী হিসাবে BOM-এ নির্দিষ্ট করা A এবং B-এর সংস্করণগুলি ব্যবহার করে, যদিও আপনি সরাসরি নির্ভরতা হিসাবে লাইব্রেরি B নির্দিষ্ট করেন না।

যদি লাইব্রেরি D 2.0.1-এর চেয়ে কম লাইব্রেরি B-এর একটি সংস্করণের জন্য অনুরোধ করে, Gradle 2.0.1-এ সমাধান করে। যদি লাইব্রেরি D লাইব্রেরি B-এর একটি উচ্চতর সংস্করণের অনুরোধ করে, Gradle সেই সংস্করণে সমাধান করে।