Gradle বিল্ড ওভারভিউ

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

বিল্ড কী?

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

টাস্ক কমান্ডকে এনক্যাপসুলেট করে যা তাদের ইনপুটকে আউটপুটে রূপান্তরিত করে। প্লাগ-ইন টাস্ক ও তার কনফিগারেশন নির্ধারণ করে। আপনার বিল্ডে প্লাগ-ইন প্রয়োগ করলে, এটি টাস্ক রেজিস্টার করে এবং ইনপুট ও আউটপুট ব্যবহার করে সেগুলিকে একসাথে যুক্ত করে। যেমন, আপনার বিল্ড ফাইলে Android Gradle প্লাগ-ইন (AGP) প্রয়োগ করলে, APK বা Android লাইব্রেরি তৈরি করার জন্য প্রয়োজনীয় সব টাস্ক রেজিস্টার হয়ে যাবে। java-library প্লাগ-ইন আপনাকে Java সোর্স কোড থেকে একটি jar তৈরি করতে দেয়। Kotlin ও অন্যান্য ভাষার জন্য একই ধরনের প্লাগ-ইন আছে, তবে অন্যান্য প্লাগ-ইন প্লাগ-ইন এক্সটেন্ড করার জন্য তৈরি করা হয়েছে। যেমন, protobuf প্লাগ-ইনটি AGP বা java-library-এর মতো আগে থেকে থাকা প্লাগ-ইনে protobuf সাপোর্ট যোগ করার জন্য তৈরি করা হয়েছে।

Gradle কনফিগারেশনের চেয়ে কনভেনশনকে বেশি গুরুত্ব দেয়, তাই প্লাগ-ইনগুলি বক্সের বাইরে ভাল ডিফল্ট মান সহ আসবে, তবে আপনি একটি ঘোষণামূলক ডোমেন-নির্দিষ্ট ভাষা (DSL)-এর মাধ্যমে বিল্ডটি আরও কনফিগার করতে পারেন। DSL এমনভাবে ডিজাইন করা হয়েছে যাতে আপনি কী তৈরি করতে চান তা নির্দিষ্ট করতে পারেন, কীভাবে তৈরি করবেন তা নয়। প্লাগ-ইনের লজিক "কীভাবে" তা ম্যানেজ করে। আপনার প্রোজেক্ট (এবং সাব-প্রোজেক্ট)-এর একাধিক বিল্ড ফাইল জুড়ে সেই কনফিগারেশন নির্দিষ্ট করা আছে।

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

Gradle আপনার বিল্ড ফাইলে ইচ্ছামতো কোড এবং টাস্ক ডিক্লারেশন লেখার সুবিধা দিলেও, এর ফলে টুলিংয়ের পক্ষে আপনার বিল্ড বোঝা এবং আপনার পক্ষে তা বজায় রাখা আরও কঠিন হয়ে যেতে পারে। যেমন, আপনি প্লাগ-ইনের মধ্যে কোডের জন্য টেস্ট লিখতে পারেন কিন্তু বিল্ড ফাইলে নয়। পরিবর্তে, আপনাকে বিল্ড লজিক এবং টাস্ক ডিক্লারেশন প্লাগ-ইনে (যা আপনি বা অন্য কেউ সংজ্ঞায়িত করেন) সীমাবদ্ধ করতে হবে এবং আপনার বিল্ড ফাইলে সেই লজিকটি কীভাবে ব্যবহার করতে চান তা ঘোষণা করতে হবে।

Gradle বিল্ড রান করলে কী হয়?

Gradle বিল্ড তিনটি পর্যায়ে রান করে। এইসব ফেজের প্রত্যেকটি কোডের বিভিন্ন অংশ এক্সিকিউট করে যা আপনি নিজের বিল্ড ফাইলে উল্লেখ করেন।

  • ইনিশিয়ালাইজেশন নির্ধারণ করে যে কোন প্রোজেক্ট ও সাব-প্রোজেক্ট বিল্ডে অন্তর্ভুক্ত করা হয়েছে এবং আপনার বিল্ড ফাইল ও প্রয়োগ করা প্লাগ-ইন সহ ক্লাসপাথ সেট-আপ করে। এই ফেজে সেটিংস ফাইলের উপর ফোকাস করা হয় যেখানে আপনি প্রোজেক্ট তৈরি করার জন্য ঘোষণা করেন এবং প্লাগ-ইন ও লাইব্রেরি ফেচ করার জন্য লোকেশন উল্লেখ করেন।
  • কনফিগারেশন প্রতিটি প্রোজেক্টের জন্য টাস্ক রেজিস্টার করে এবং ব্যবহারকারীর বিল্ড স্পেসিফিকেশন প্রয়োগ করার জন্য বিল্ড ফাইল এক্সিকিউট করে। এটি বোঝা গুরুত্বপূর্ণ যে আপনার কনফিগারেশন কোডের কাছে এক্সিকিউশনের সময় তৈরি হওয়া ডেটা বা ফাইলের অ্যাক্সেস থাকবে না।
  • এক্সিকিউশন আপনার অ্যাপ্লিকেশনের আসল "বিল্ডিং" পারফর্ম করে। কনফিগারেশনের আউটপুট হল টাস্কের ডিরেক্টেড অ্যাসাইক্লিক গ্রাফ (DAG), যা ব্যবহারকারীর অনুরোধ করা সমস্ত প্রয়োজনীয় বিল্ড স্টেপকে উপস্থাপন করে (কমান্ড লাইনে বা বিল্ড ফাইলে ডিফল্ট হিসেবে প্রদান করা টাস্ক)। এই গ্রাফটি টাস্কের মধ্যে সম্পর্ককে উপস্থাপন করে, যা টাস্কের ঘোষণায় স্পষ্টভাবে বা এর ইনপুট এবং আউটপুটের উপর ভিত্তি করে। কোনও টাস্কে যদি এমন ইনপুট থাকে যা অন্য টাস্কের আউটপুট, তাহলে সেটি অবশ্যই অন্য টাস্কের পরে রান করতে হবে। এই ফেজ গ্রাফে উল্লেখ করা ক্রম অনুযায়ী মেয়াদ শেষ হয়ে যাওয়া টাস্ক রান করে; কোনও টাস্কের ইনপুট শেষবার এক্সিকিউট করার পর থেকে পরিবর্তন না হয়ে থাকলে, Gradle সেটি এড়িয়ে যাবে।

আরও তথ্যের জন্য Gradle বিল্ড লাইফসাইকেল দেখুন।

কনফিগারেশন DSL

বিল্ড কনফিগার করতে Gradle ডোমেন-নির্দিষ্ট ভাষা (DSL) ব্যবহার করে। এই ডিক্লারেটিভ অ্যাপ্রোচ ধাপে ধাপে (ইম্পারেটিভ) নির্দেশাবলী লেখার পরিবর্তে আপনার ডেটা নির্দিষ্ট করার উপর ফোকাস করে। আপনি Kotlin বা Groovy ব্যবহার করে আপনার বিল্ড ফাইল লিখতে পারেন, তবে আমরা Kotlin ব্যবহার করার জন্য বিশেষভাবে সাজেস্ট করি।

DSLs-এর লক্ষ্য হল, ডোমেন বিশেষজ্ঞ এবং প্রোগ্রামার সহ সকলের জন্য একটি প্রোজেক্টে অবদান রাখা সহজ করা, একটি ছোট ভাষা সংজ্ঞায়িত করা যা আরও স্বাভাবিক উপায়ে ডেটা উপস্থাপন করে। Gradle প্লাগ-ইন DSL-কে আরও বড় করতে পারে যাতে টাস্কের জন্য প্রয়োজনীয় ডেটা কনফিগার করা যায়।

যেমন, আপনার বিল্ডের Android অংশ কনফিগার করা এইরকম দেখতে হতে পারে:

Kotlin

android {
    namespace = "com.example.app"
    compileSdk {
        version = release(36) {
            minorApiLevel = 1
        }
    }
    // ...

    defaultConfig {
        applicationId = "com.example.app"
        minSdk {
            version = release(23)
        }
        targetSdk {
            version = release(36)
        }
        // ...
    }
}

গ্ৰুভি

android {
    namespace = 'com.example.app'
    compileSdk {
        version = release(36) {
            minorApiLevel = 1
        }
    }
    // ...

    defaultConfig {
        applicationId = 'com.example.app'
        minSdk {
            version = release(23)
        }
        targetSdk {
            version = release(36)
        }
        // ...
    }
}

নেপথ্যে, DSL কোডটি এর মতো:

fun Project.android(configure: ApplicationExtension.() -> Unit) {
    ...
}

interface ApplicationExtension {
    var namespace: String?

    fun compileSdk(configure: CompileSdkSpec.() -> Unit) {
        ...
    }

    val defaultConfig: DefaultConfig

    fun defaultConfig(configure: DefaultConfig.() -> Unit) {
        ...
    }
}

DSL-এর প্রতিটি ব্লক একটি ফাংশন দ্বারা উপস্থাপিত হয় যা এটি কনফিগার করার জন্য একটি ল্যাম্বডা নেয় এবং এটি অ্যাক্সেস করার জন্য একই নামের একটি প্রপার্টি। এর ফলে আপনার বিল্ড ফাইলের কোড আরও বেশি ডেটা স্পেসিফিকেশনের মতো মনে হয়।

এক্সটার্নাল ডিপেন্ডেন্সি

Maven বিল্ড সিস্টেম একটি নির্ভরতা স্পেসিফিকেশন, স্টোরেজ এবং ম্যানেজমেন্ট সিস্টেম চালু করেছে। লাইব্রেরিগুলি রিপোজিটরি (সার্ভার বা ডিরেক্টরি)-তে স্টোর করা হয়, যার মধ্যে মেটাডেটা সহ তাদের ভার্সন এবং অন্যান্য লাইব্রেরির উপর নির্ভরতা থাকে। আপনি নির্দিষ্ট করে দেন যে কোন রিপোজিটরি সার্চ করতে হবে, ডিপেন্ডেন্সির কোন ভার্সন আপনি ব্যবহার করতে চান এবং বিল্ড সিস্টেম বিল্ড করার সময় সেগুলি ডাউনলোড করে।

Maven আর্টিফ্যাক্ট গ্রুপের নাম (কোম্পানি, ডেভেলপার ইত্যাদি), আর্টিফ্যাক্টের নাম (লাইব্রেরির নাম) এবং সেই আর্টিফ্যাক্টের ভার্সন দ্বারা শনাক্ত করা হয়। এটি সাধারণত group:artifact:version হিসেবে দেখানো হয়।

এই পদ্ধতি বিল্ড ম্যানেজমেন্টকে উল্লেখযোগ্যভাবে উন্নত করে। আপনি প্রায়ই এই ধরনের রিপোজিটরিকে "Maven রিপোজিটরি" নামে উল্লেখ করতে শুনবেন, তবে এটি আর্টিফ্যাক্ট প্যাকেজ ও প্রকাশ করার পদ্ধতির উপর নির্ভর করে। এইসব রিপোজিটরি ও মেটাডেটা Gradle (এবং Gradle এইসব রিপোজিটরিতে প্রকাশ করতে পারে) সহ একাধিক বিল্ড সিস্টেমে আবার ব্যবহার করা হয়েছে। সর্বজনীন রিপোজিটরি সবাইকে শেয়ার করার অনুমতি দেয় এবং কোম্পানির রিপোজিটরি ইন্টার্নাল ডিপেন্ডেন্সি ইন-হাউস রাখে।

এছাড়াও, আপনি নিজের প্রোজেক্টকে সাব-প্রোজেক্টে মডিউলারাইজ করতে পারবেন (Android Studio-তে "মডিউল" হিসেবেও পরিচিত), যা ডিপেন্ডেন্সি হিসেবেও ব্যবহার করা যেতে পারে। প্রতিটি সাবপ্রোজেক্ট আউটপুট (যেমন জার) তৈরি করে যা সাবপ্রোজেক্ট বা আপনার টপ-লেভেল প্রোজেক্ট ব্যবহার করতে পারে। এটি কোন অংশগুলি পুনর্নির্মাণ করতে হবে তা আলাদা করে বিল্ড টাইম উন্নত করতে পারে, পাশাপাশি অ্যাপ্লিকেশনে আরও ভাল আলাদা দায়িত্বও দিতে পারে।

বিল্ড ডিপেন্ডেন্সি যোগ করুন বিকল্পে কীভাবে ডিপেন্ডেন্সি নির্দিষ্ট করতে হয় সেই সম্পর্কে আমরা আরও বিস্তারিতভাবে আলোচনা করব।

বিল্ড ভ্যারিয়েন্ট

আপনি কোনও Android অ্যাপ্লিকেশন তৈরি করার সময়, সাধারণত একাধিক ভেরিয়েন্ট তৈরি করতে চাইবেন। ভ্যারিয়েন্টে আলাদা কোড থাকে বা আলাদা বিকল্প দিয়ে তৈরি করা হয় এবং বিল্ডের ধরন ও প্রোডাক্ট ফ্লেভার দিয়ে কম্পোজ করা হয়।

বিল্ডের ধরন ঘোষিত বিল্ড বিকল্পের থেকে আলাদা হয়। ডিফল্ট হিসেবে, AGP "রিলিজ" এবং "ডিবাগ" বিল্ডের ধরন সেট-আপ করে, তবে আপনি সেগুলি অ্যাডজাস্ট করতে এবং আরও যোগ করতে পারেন (সম্ভবত স্টেজিং বা ইন্টার্নাল টেস্টিংয়ের জন্য)।

ডিবাগ বিল্ট আপনার অ্যাপ্লিকেশনকে ছোট বা অস্পষ্ট করে না, এর বিল্টকে দ্রুত করে এবং সমস্ত চিহ্নকে যেমন আছে তেমনভাবে সংরক্ষণ করে। এটি অ্যাপ্লিকেশনটিকে "ডিবাগ করা যাবে" হিসেবে চিহ্নিত করে, একটি জেনেরিক ডিবাগ কী দিয়ে সাইন করে এবং ডিভাইসে ইনস্টল করা অ্যাপ্লিকেশন ফাইলগুলিতে অ্যাক্সেস চালু করে। এর ফলে, অ্যাপ্লিকেশন চালানোর সময় ফাইল ও ডেটাবেসে সেভ করা ডেটা এক্সপ্লোর করা সম্ভব হয়।

রিলিজ বিল্ড অ্যাপ্লিকেশন অপ্টিমাইজ করে, আপনার রিলিজ কী দিয়ে এটি সাইন করে এবং ইনস্টল করা অ্যাপ্লিকেশন ফাইল সুরক্ষিত রাখে।

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

AGP বিল্ড টাইপ ও প্রোডাক্ট ফ্লেভারের প্রতিটি কম্বিনেশনের জন্য ভ্যারিয়েন্ট তৈরি করে। আপনি ফ্লেভার নির্ধারণ না করলে, বিল্ডের ধরন অনুযায়ী ভেরিয়েন্টের নাম দেওয়া হয়। আপনি দুটিই সংজ্ঞায়িত করলে, ভেরিয়েন্টের নাম <flavor><Buildtype> হবে। যেমন, বিল্ডের ধরন release ও debug এবং ফ্লেভার demo ও full-এর ক্ষেত্রে AGP ভেরিয়েন্ট তৈরি করবে:

  • demoRelease
  • demoDebug
  • fullRelease
  • fullDebug

পরবর্তী ধাপ

এখন আপনি বিল্ড কনসেপ্ট দেখেছেন, আপনার প্রোজেক্টে Android বিল্ড স্ট্রাকচার দেখুন।