গ্রেডল বিল্ড ওভারভিউ, গ্রেডল বিল্ড ওভারভিউ

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

বিল্ড বলতে কী বোঝায়?

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

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

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

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

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

যখন একটি গ্রেডল বিল্ড চলে তখন কী ঘটে?

গ্রেডল বিল্ড তিনটি ধাপে চলে। এই ধাপগুলোর প্রতিটি আপনার বিল্ড ফাইলে সংজ্ঞায়িত কোডের বিভিন্ন অংশ কার্যকর করে।

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

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

কনফিগারেশন ডিএসএল

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

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

উদাহরণস্বরূপ, আপনার বিল্ডের অ্যান্ড্রয়েড অংশটি কনফিগার করার পদ্ধতিটি দেখতে এইরকম হতে পারে:

কোটলিন

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)
        }
        // ...
    }
}

নেপথ্যে, ডিএসএল কোডটি নিম্নরূপ:

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 Artifact-গুলিকে গ্রুপের নাম (কোম্পানি, ডেভেলপার, ইত্যাদি), আর্টিফ্যাক্টের নাম (লাইব্রেরির নাম) এবং সেই আর্টিফ্যাক্টের ভার্সন দ্বারা চিহ্নিত করা হয়। এটিকে সাধারণত group:artifact:version হিসেবে উপস্থাপন করা হয়।

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

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

'Add build dependencies' অংশে আমরা ডিপেন্ডেন্সিগুলো কীভাবে নির্দিষ্ট করতে হয় সে সম্পর্কে আরও বিস্তারিত আলোচনা করব।

বিভিন্ন নির্মাণ

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

বিল্ড টাইপগুলো ঘোষিত বিল্ড অপশন অনুযায়ী ভিন্ন হয়। ডিফল্টরূপে, AGP 'রিলিজ' এবং 'ডিবাগ' বিল্ড টাইপ সেট আপ করে, কিন্তু আপনি সেগুলো পরিবর্তন করতে এবং আরও যোগ করতে পারেন (সম্ভবত স্টেজিং বা অভ্যন্তরীণ পরীক্ষার জন্য)।

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

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

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

AGP প্রতিটি বিল্ড টাইপ এবং প্রোডাক্ট ফ্লেভারের সমন্বয়ের জন্য ভ্যারিয়েন্ট তৈরি করে। আপনি যদি ফ্লেভার নির্ধারণ না করেন, তাহলে ভ্যারিয়েন্টগুলোর নামকরণ করা হয় বিল্ড টাইপের নামানুসারে। আর যদি আপনি উভয়ই নির্ধারণ করেন, তাহলে ভ্যারিয়েন্টটির নাম হয় <flavor><Buildtype> >। উদাহরণস্বরূপ, release ' ও debug বিল্ড টাইপ এবং demofull ফ্লেভারের ক্ষেত্রে, AGP নিম্নলিখিত ভ্যারিয়েন্টগুলো তৈরি করবে:

  • demoRelease
  • demoDebug
  • fullRelease
  • fullDebug

পরবর্তী পদক্ষেপ

এখন যেহেতু আপনি বিল্ডের ধারণাগুলো দেখেছেন, আপনার প্রোজেক্টের অ্যান্ড্রয়েড বিল্ড কাঠামোটি দেখুন।