بسته‌ها و جعبه‌ها (crates)

اولین بخش‌هایی که در سیستم ماژول بررسی خواهیم کرد، بسته‌ها و جعبه‌ها (crates) هستند.

یک جعبه (crate) کوچک‌ترین واحد کدی است که کامپایلر Rust در یک زمان در نظر می‌گیرد. حتی اگر به جای cargo از rustc استفاده کنید و یک فایل کد منبع را ارسال کنید (همان‌طور که در بخش «نوشتن و اجرای یک برنامه Rust» در فصل ۱ انجام دادیم)، کامپایلر آن فایل را به عنوان یک جعبه (crate) در نظر می‌گیرد. جعبه‌ها (crates) می‌توانند شامل ماژول‌ها باشند، و این ماژول‌ها ممکن است در فایل‌های دیگری تعریف شوند که همراه با جعبه (crate) کامپایل می‌شوند، همان‌طور که در بخش‌های آینده خواهیم دید.

یک جعبه (crate) می‌تواند به یکی از دو شکل باشد: جعبه (crate) باینری یا جعبه (crate) کتابخانه‌ای. جعبه‌ها (crates)ی باینری برنامه‌هایی هستند که می‌توانید آن‌ها را به یک فایل اجرایی کامپایل کنید و اجرا کنید، مانند یک برنامه خط فرمان یا یک سرور. هر جعبه (crate) باینری باید یک تابع به نام main داشته باشد که مشخص کند وقتی فایل اجرایی اجرا می‌شود چه اتفاقی می‌افتد. تمامی جعبه‌ها (crates)یی که تاکنون ایجاد کرده‌ایم، جعبه‌ها (crates)ی باینری بوده‌اند.

جعبه‌ها (crates)ی کتابخانه‌ای تابع main ندارند و به یک فایل اجرایی کامپایل نمی‌شوند. بلکه، آن‌ها عملکردهایی را تعریف می‌کنند که برای اشتراک‌گذاری میان چندین پروژه طراحی شده‌اند. به عنوان مثال، جعبه (crate) rand که در فصل ۲ از آن استفاده کردیم، قابلیت تولید اعداد تصادفی را فراهم می‌کند. اغلب اوقات وقتی Rustaceanها می‌گویند “جعبه (crate)”، منظورشان جعبه (crate) کتابخانه‌ای است، و آن را به صورت متناوب با مفهوم عمومی برنامه‌نویسی “کتابخانه” استفاده می‌کنند.

ریشه جعبه (crate) یک فایل منبع است که کامپایلر Rust از آن شروع می‌کند و ریشه ماژول جعبه (crate) را تشکیل می‌دهد (ماژول‌ها را در بخش «تعریف ماژول‌ها برای کنترل محدوده و حریم خصوصی» به طور کامل بررسی خواهیم کرد).

یک بسته مجموعه‌ای از یک یا چند جعبه (crate) است که مجموعه‌ای از عملکردها را فراهم می‌کند. یک بسته شامل یک فایل Cargo.toml است که توضیح می‌دهد چگونه باید این جعبه‌ها (crates) ساخته شوند. Cargo خود یک بسته است که شامل جعبه (crate) باینری ابزار خط فرمانی که از آن برای ساخت کدتان استفاده کرده‌اید می‌شود. بسته Cargo همچنین شامل یک جعبه (crate) کتابخانه‌ای است که جعبه (crate) باینری به آن وابسته است. پروژه‌های دیگر می‌توانند به جعبه (crate) کتابخانه‌ای Cargo وابسته شوند تا از همان منطقی که ابزار خط فرمان Cargo استفاده می‌کند بهره‌مند شوند. یک بسته می‌تواند شامل هر تعداد جعبه (crate) باینری باشد که می‌خواهید، اما در بیشترین حالت تنها یک جعبه (crate) کتابخانه‌ای می‌تواند داشته باشد. یک بسته باید حداقل یک جعبه (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) باینری جداگانه خواهد بود.