প্যাকেজ এবং ক্রেট
মডিউল সিস্টেমের প্রথম যে অংশগুলো নিয়ে আমরা আলোচনা করব তা হলো প্যাকেজ এবং ক্রেট।
একটি ক্রেট (crate) হলো কোডের সবচেয়ে ছোট অংশ যা রাস্ট কম্পাইলার একবারে বিবেচনা করে। এমনকি যদি আপনি cargo
-র পরিবর্তে rustc
রান করেন এবং একটি মাত্র সোর্স কোড ফাইল পাস করেন (যেমনটা আমরা প্রথম অধ্যায়ের “একটি রাস্ট প্রোগ্রাম লেখা এবং রান করা” অংশে করেছিলাম), কম্পাইলার সেই ফাইলটিকে একটি ক্রেট হিসেবে বিবেচনা করে। ক্রেট-এর মধ্যে মডিউল থাকতে পারে, এবং সেই মডিউলগুলো অন্য ফাইলে ডিফাইন করা থাকতে পারে যা ক্রেটের সাথে কম্পাইল হয়, যা আমরা পরবর্তী বিভাগগুলিতে দেখব।
একটি ক্রেট দুই ধরনের হতে পারে: একটি বাইনারি ক্রেট অথবা একটি লাইব্রেরি ক্রেট। বাইনারি ক্রেট (Binary crates) হলো এমন প্রোগ্রাম যা আপনি একটি এক্সিকিউটেবল (executable) হিসেবে কম্পাইল করতে পারেন, যেমন একটি কমান্ড লাইন প্রোগ্রাম বা একটি সার্ভার। প্রতিটিতে অবশ্যই main
নামের একটি ফাংশন থাকতে হবে যা এক্সিকিউটেবল রান হলে কী ঘটবে তা নির্ধারণ করে। আমরা এখন পর্যন্ত যতগুলো ক্রেট তৈরি করেছি তার সবই বাইনারি ক্রেট।
লাইব্রেরি ক্রেট (Library crates)-এর কোনো main
ফাংশন নেই এবং এগুলো এক্সিকিউটেবল হিসেবে কম্পাইল হয় না। এর পরিবর্তে, তারা এমন ফাংশনালিটি ডিফাইন করে যা একাধিক প্রজেক্টের সাথে শেয়ার করার জন্য তৈরি। উদাহরণস্বরূপ, আমরা দ্বিতীয় অধ্যায়ে যে rand
ক্রেট ব্যবহার করেছি, তা র্যান্ডম নম্বর জেনারেট করার ফাংশনালিটি প্রদান করে। বেশিরভাগ সময় যখন Rustacean-রা “ক্রেট” বলেন, তখন তারা লাইব্রেরি ক্রেটকেই বোঝান, এবং তারা “ক্রেট” শব্দটিকে সাধারণ প্রোগ্রামিং ধারণা “লাইব্রেরি”-র সমার্থক হিসেবে ব্যবহার করেন।
ক্রেট রুট (crate root) হলো একটি সোর্স ফাইল যেখান থেকে রাস্ট কম্পাইলার কাজ শুরু করে এবং যা আপনার ক্রেটের রুট মডিউল তৈরি করে (আমরা মডিউল সম্পর্কে বিস্তারিতভাবে “স্কোপ এবং প্রাইভেসি নিয়ন্ত্রণের জন্য মডিউল ডিফাইন করা” বিভাগে ব্যাখ্যা করব)।
একটি প্যাকেজ (package) হলো এক বা একাধিক ক্রেটের একটি বান্ডিল যা একটি নির্দিষ্ট সেট অফ ফাংশনালিটি প্রদান করে। একটি প্যাকেজে একটি Cargo.toml ফাইল থাকে যা বর্ণনা করে কিভাবে সেই ক্রেটগুলো বিল্ড করতে হবে। কার্গো (Cargo) নিজেও আসলে একটি প্যাকেজ যা আপনার কোড বিল্ড করার জন্য ব্যবহৃত কমান্ড লাইন টুলের বাইনারি ক্রেট ধারণ করে। কার্গো প্যাকেজে একটি লাইব্রেরি ক্রেটও রয়েছে যার উপর বাইনারি ক্রেটটি নির্ভর করে। অন্যান্য প্রজেক্টগুলো কার্গো কমান্ড লাইন টুলের মতো একই লজিক ব্যবহার করার জন্য কার্গো লাইব্রেরি ক্রেটের উপর নির্ভর করতে পারে।
একটি প্যাকেজে আপনার ইচ্ছামত যত খুশি বাইনারি ক্রেট থাকতে পারে, কিন্তু সর্বোচ্চ একটি লাইব্রেরি ক্রেট থাকতে পারে। একটি প্যাকেজে অবশ্যই কমপক্ষে একটি ক্রেট থাকতে হবে, তা লাইব্রেরি হোক বা বাইনারি।
চলুন দেখি একটি প্যাকেজ তৈরি করলে কী ঘটে। প্রথমে আমরা cargo new my-project
কমান্ডটি প্রবেশ করাই:
$ cargo new my-project
Created binary (application) `my-project` package
$ ls my-project
Cargo.toml
src
$ ls my-project/src
main.rs
cargo new my-project
চালানোর পর, কার্গো কী তৈরি করেছে তা দেখার জন্য আমরা ls
ব্যবহার করি। প্রজেক্ট ডিরেক্টরিতে, একটি Cargo.toml ফাইল রয়েছে, যা আমাদের একটি প্যাকেজ দেয়। এছাড়াও একটি src ডিরেক্টরি রয়েছে যার মধ্যে main.rs ফাইলটি আছে। আপনার টেক্সট এডিটরে Cargo.toml খুলুন, এবং লক্ষ্য করুন যে সেখানে src/main.rs সম্পর্কে কোনো উল্লেখ নেই। কার্গো এই কনভেনশন অনুসরণ করে যে, src/main.rs হলো প্যাকেজের নামের সাথে মিলিয়ে একটি বাইনারি ক্রেটের ক্রেট রুট। একইভাবে, কার্গো জানে যে যদি প্যাকেজ ডিরেক্টরিতে src/lib.rs থাকে, তাহলে প্যাকেজটিতে প্যাকেজের নামের সাথে মিলিয়ে একটি লাইব্রেরি ক্রেট রয়েছে, এবং src/lib.rs হলো তার ক্রেট রুট। কার্গো লাইব্রেরি বা বাইনারি বিল্ড করার জন্য ক্রেট রুট ফাইলগুলো rustc
-কে পাস করে।
এখানে, আমাদের একটি প্যাকেজ আছে যাতে শুধুমাত্র src/main.rs রয়েছে, যার অর্থ হলো এটিতে শুধুমাত্র my-project
নামের একটি বাইনারি ক্রেট আছে। যদি একটি প্যাকেজে src/main.rs এবং src/lib.rs উভয়ই থাকে, তবে এটির দুটি ক্রেট রয়েছে: একটি বাইনারি এবং একটি লাইব্রেরি, এবং উভয়ের নামই প্যাকেজের নামের সমান হয়। একটি প্যাকেজে একাধিক বাইনারি ক্রেট থাকতে পারে src/bin ডিরেক্টরিতে ফাইল রাখার মাধ্যমে: প্রতিটি ফাইল একটি পৃথক বাইনারি ক্রেট হবে।