بستهها و جعبهها (crates)
اولین بخشهایی که در سیستم ماژول بررسی خواهیم کرد، بستهها و جعبهها (crates) هستند.
یک crate کوچکترین واحدی از کد است که کامپایلر Rust در هر لحظه به آن توجه میکند.
حتی اگر به جای استفاده از cargo
، مستقیماً rustc
را اجرا کنید و تنها یک فایل کد منبع را (همانطور که در فصل اول در بخش «نوشتن و اجرای یک برنامه Rust» انجام دادیم) به آن بدهید،
کامپایلر آن فایل را به عنوان یک crate در نظر میگیرد.
crateها میتوانند شامل ماژولهایی باشند، و این ماژولها ممکن است در فایلهای دیگری تعریف شده باشند
که هنگام کامپایل، همراه با crate پردازش میشوند، همانطور که در بخشهای بعدی خواهیم دید.
یک crate میتواند یکی از دو نوع زیر باشد: crate دودویی (binary) یا crate کتابخانهای (library).
crateهای دودویی برنامههایی هستند که میتوانید آنها را به فایل اجرایی کامپایل کرده و اجرا کنید،
مانند یک برنامهی خط فرمان یا یک سرور. هر crate دودویی باید تابعی به نام main
داشته باشد
که مشخص میکند هنگام اجرای فایل اجرایی، چه اتفاقی میافتد.
تمام crateهایی که تا اینجا ایجاد کردهایم، crateهای دودویی بودهاند.
crateهای کتابخانهای تابع main
ندارند و به فایل اجرایی کامپایل نمیشوند.
در عوض، آنها قابلیتهایی را تعریف میکنند که برای اشتراکگذاری میان پروژههای مختلف در نظر گرفته شدهاند.
برای مثال، crate rand
که در فصل ۲ از آن استفاده کردیم، قابلیتهایی برای تولید اعداد تصادفی فراهم میکند.
در اغلب موارد، زمانی که Rustaceanها از واژهی “crate” استفاده میکنند، منظورشان crate کتابخانهای است
و این واژه را بهطور معادل با مفهوم عمومی «کتابخانه» در برنامهنویسی به کار میبرند.
ریشهی crate (crate root) فایلی از کد منبع است که کامپایلر Rust از آن شروع میکند و ماژول ریشهی crate را تشکیل میدهد (ماژولها را در بخش “تعریف ماژولها برای کنترل حوزه و سطح دسترسی” با جزئیات توضیح خواهیم داد).
یک package مجموعهای از یک یا چند crate است که مجموعهای از قابلیتها را ارائه میدهد. یک package شامل یک فایل Cargo.toml است که مشخص میکند چگونه crateها باید ساخته شوند. خود Cargo در واقع یک package است که شامل یک crate دودویی برای ابزار خط فرمانی است که تاکنون از آن برای ساخت کد خود استفاده کردهاید. پکیج Cargo همچنین شامل یک crate کتابخانهای است که crate دودویی به آن وابسته است. سایر پروژهها میتوانند به crate کتابخانهای Cargo وابسته شوند تا از همان منطق استفاده کنند که ابزار خط فرمان Cargo از آن بهره میبرد.
یک package میتواند هر تعداد crate دودویی داشته باشد، اما در بیشترین حالت، تنها یک crate کتابخانهای میتواند داشته باشد. هر package باید دستکم شامل یک crate باشد، چه crate کتابخانهای و چه crate دودویی.
بیایید ببینیم وقتی یک بسته ایجاد میکنیم چه اتفاقی میافتد. ابتدا دستور 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 چه چیزی ایجاد کرده است. در دایرکتوری پروژه، یک فایل Cargo.toml وجود دارد که به ما یک بسته میدهد. همچنین یک دایرکتوری src وجود دارد که شامل فایل main.rs است. فایل Cargo.toml را در ویرایشگر متن خود باز کنید و توجه کنید که هیچ اشارهای به src/main.rs نشده است. Cargo از یک قرارداد پیروی میکند که src/main.rs ریشه جعبه (crate) یک جعبه (crate) باینری با همان نام بسته است. به همین ترتیب، Cargo میداند که اگر دایرکتوری بسته شامل src/lib.rs باشد، بسته شامل یک جعبه (crate) کتابخانهای با همان نام بسته است و src/lib.rs ریشه جعبه (crate) آن است. Cargo فایلهای ریشه جعبه (crate) را به rustc
ارسال میکند تا کتابخانه یا فایل اجرایی ساخته شود.
در اینجا، ما یک بسته داریم که تنها شامل src/main.rs است، به این معنی که تنها یک جعبه (crate) باینری به نام my-project
دارد. اگر یک بسته شامل src/main.rs و src/lib.rs باشد، آن بسته دو جعبه (crate) خواهد داشت: یک جعبه (crate) باینری و یک کتابخانه، هر دو با همان نام بسته. یک بسته میتواند چندین جعبه (crate) باینری داشته باشد با قرار دادن فایلها در دایرکتوری src/bin: هر فایل یک جعبه (crate) باینری جداگانه خواهد بود.