سلام، کارگو!
کارگو سیستم بیلد و مدیر بستههای Rust است. بیشتر برنامهنویسان Rust از این ابزار برای مدیریت پروژههایشان استفاده میکنند، چون کارگو وظایف زیادی را بهصورت خودکار انجام میدهد، مثل بیلد کردن کد، دانلود کتابخانههای موردنیاز، و بیلد کردن آن کتابخانهها. (به این کتابخانههای موردنیاز وابستگی میگوییم.)
برنامههای سادهی Rust، مثل همانی که تا الآن نوشتیم، معمولاً هیچ وابستگیای ندارند. اگر پروژهی "Hello, world!" را با کارگو بیلد میکردیم، فقط از بخش بیلد آن استفاده میشد. اما هرچه برنامهات پیچیدهتر شود، احتمالاً به وابستگیهایی نیاز خواهی داشت، و اگر پروژهات را از اول با کارگو شروع کنی، اضافه کردن این وابستگیها خیلی راحتتر میشود.
چون بیشتر پروژههای Rust از کارگو استفاده میکنند، این کتاب هم فرض میکند که تو هم از آن استفاده میکنی. اگر Rust را با نصبکنندهی رسمی آن نصب کرده باشی، کارگو هم همراهش نصب شده است. اما اگر به روش دیگری نصب کردهای، میتوانی با این دستور بررسی کنی که کارگو نصب است یا نه:
$ cargo --version
اگر یک شماره نسخه دیدی، یعنی نصب شده! ولی اگر خطایی مثل command not found
دیدی، باید مستندات روش نصب را بررسی کنی تا ببینی چطور کارگو را جداگانه نصب کنی.
ساخت یک پروژه با کارگو
حالا بیایید یک پروژهی جدید با کارگو بسازیم و تفاوتهایش با پروژهی اولیهی "Hello, world!" را ببینیم. ابتدا به پوشهی پروژههایت برگرد (یا هر جایی که کدهایت را ذخیره میکنی) و این دستورات را اجرا کن:
$ cargo new hello_cargo
$ cd hello_cargo
دستور اول یک پوشهی جدید به نام hello_cargo میسازد و فایلهای پروژه را داخل آن قرار میدهد. بعد از ورود به این پوشه، اگر لیست فایلهای داخل آن را ببینی، کارگو دو فایل و یک پوشه برایت ساخته است:
- فایل Cargo.toml
- یک پوشه به نام src که فایل main.rs داخل آن قرار دارد.
همچنین کارگو یک ریپازیتوری Git و فایل .gitignore را هم ایجاد کرده است. البته اگر دستور cargo new
را داخل یک ریپازیتوری Git اجرا کنی، این فایلها ساخته نمیشوند. اگر بخواهی این رفتار را تغییر بدهی، میتوانی از cargo new --vcs=git
استفاده کنی.
نکته: Git یک سیستم کنترل نسخهی معروف است. میتوانی مشخص کنی که
cargo new
از چه سیستم کنترلی استفاده کند یا اینکه اصلاً از هیچ سیستمی استفاده نکند. برای دیدن گزینههای مختلف،cargo new --help
را اجرا کن.
حالا Cargo.toml را در ویرایشگر موردعلاقهات باز کن. محتوای آن باید شبیه این باشد:
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"
# برای اطلاعات بیشتر به این لینک مراجعه کن:
# https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
این فایل با فرمت [TOML] نوشته شده است که یک فرمت ساده و خوانا برای پیکربندی کارگو است.
بخش [package]
اطلاعاتی مثل نام پروژه، نسخه و ویرایش Rust را مشخص میکند. بخش [dependencies]
جایی است که میتوانی وابستگیهای پروژهات را تعریف کنی. در این پروژه به هیچ بستهی اضافی نیاز نداریم، اما در فصل دوم از آن استفاده خواهیم کرد.
حالا src/main.rs را باز کن:
fn main() { println!("Hello, world!"); }
همان برنامهی سادهی "Hello, world!" است که قبلاً نوشتیم! تنها تفاوت این است که کارگو فایل را داخل پوشهی src قرار داده و فایل Cargo.toml را در پوشهی اصلی پروژه ساخته است.
کارگو انتظار دارد که همهی کدهای پروژه داخل پوشهی src باشند، و پوشهی اصلی فقط شامل فایلهایی مثل README، مجوز، و تنظیمات باشد. این ساختار باعث نظم بیشتر پروژهها میشود.
اگر پروژهای را بدون کارگو شروع کردهای (مثل همین "Hello, world!")، میتوانی آن را به پروژهای که از کارگو استفاده میکند تبدیل کنی. فقط کافی است کدهای پروژه را داخل پوشهی src بگذاری و یک فایل Cargo.toml ایجاد کنی. یک راه آسان برای ساخت این فایل، اجرای دستور cargo init
است که بهصورت خودکار آن را برایت میسازد.
بیلد و اجرای پروژه با کارگو
حالا ببینیم اجرای برنامهی "Hello, world!" با کارگو چه تفاوتی دارد. داخل پوشهی hello_cargo، دستور زیر را اجرا کن:
$ cargo build
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
این دستور یک فایل اجرایی در مسیر target/debug/hello_cargo (یا در ویندوز target\debug\hello_cargo.exe) ایجاد میکند، نه در دایرکتوری فعلی شما. چون ساخت پیشفرض در حالت دیباگ (debug) است، Cargo فایل باینری را در یک دایرکتوری به نام debug قرار میدهد. برای اجرای این فایل اجرایی، میتوانید این دستور را بزنید:
$ ./target/debug/hello_cargo # در ویندوز: .\target\debug\hello_cargo.exe
اگر همه چیز درست باشد، Hello, world!
در ترمینال نمایش داده میشود. اجرای cargo build
برای اولین بار یک فایل جدید به نام Cargo.lock در سطح بالای پروژه ایجاد میکند. این فایل نسخهی دقیق وابستگیهای پروژه را ثبت میکند. این پروژه وابستگیای ندارد، پس فایل تقریباً خالی خواهد بود. نیازی به ویرایش دستی این فایل ندارید، چون Cargo خودش آن را مدیریت میکند.
ما پروژه را با cargo build
ساختیم و با ./target/debug/hello_cargo
اجرا کردیم، اما میتوانیم از cargo run
استفاده کنیم تا همزمان هم کد را کامپایل کند و هم آن را اجرا کند:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/hello_cargo`
Hello, world!
استفاده از cargo run
راحتتر از این است که هر بار cargo build
را اجرا کنیم و بعد مسیر کامل باینری را وارد کنیم، به همین دلیل بیشتر توسعهدهندگان از cargo run
استفاده میکنند.
اگر در کد تغییری نداده باشید، Cargo متوجه میشود و دوباره پروژه را نمیسازد، فقط باینری را اجرا میکند. اما اگر تغییری در کد داده باشید، Cargo قبل از اجرا پروژه را دوباره میسازد و چنین خروجیای خواهید دید:
$ cargo run
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs
Running `target/debug/hello_cargo`
Hello, world!
Cargo یک دستور دیگر هم دارد به نام cargo check
که به جای تولید فایل اجرایی، فقط بررسی میکند که آیا کد شما کامپایل میشود یا نه:
$ cargo check
Checking hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
چرا باید بخواهید که یک فایل اجرایی ساخته نشود؟ چون cargo check
معمولاً خیلی سریعتر از cargo build
اجرا میشود، چون مرحلهی تولید فایل اجرایی را رد میکند. اگر مدام در حال بررسی کد هنگام نوشتن هستید، استفاده از cargo check
سرعت کار را بالا میبرد. به همین دلیل، بیشتر برنامهنویسان Rust هنگام کدنویسی از cargo check
استفاده میکنند و وقتی آمادهی اجرای برنامه شدند، از cargo build
استفاده میکنند.
خلاصهی کارهایی که تا الآن یاد گرفتیم:
- با
cargo new
میتوانیم یک پروژه جدید بسازیم. - با
cargo build
میتوانیم پروژه را کامپایل کنیم. - با
cargo run
همزمان پروژه را کامپایل و اجرا کنیم. - با
cargo check
بدون ساختن باینری، بررسی کنیم که کد مشکلی ندارد. - Cargo خروجی بیلد را به جای قرار دادن در دایرکتوری پروژه، داخل target/debug ذخیره میکند.
یکی از مزیتهای Cargo این است که دستوراتش در همهی سیستمعاملها یکسان هستند، پس دیگر نیازی نیست برای لینوکس، مک و ویندوز دستور جداگانه بنویسیم.
بیلد نسخهی Release
وقتی پروژه آمادهی انتشار شد، میتوانید با cargo build --release
آن را با بهینهسازی کامپایل کنید. این دستور یک فایل اجرایی در مسیر target/release ایجاد میکند، نه target/debug. بهینهسازیها باعث میشوند که کد سریعتر اجرا شود، اما زمان کامپایل را افزایش میدهند. به همین دلیل، دو حالت مختلف برای بیلد وجود دارد: یکی برای توسعه که سریعتر ساخته شود، و یکی برای انتشار که سرعت اجرا بالاتر باشد.
اگر میخواهید عملکرد برنامه را تست کنید، حتماً با cargo build --release
کامپایل کنید و فایل اجرایی داخل target/release را اجرا کنید.
Cargo و استانداردهای آن
در پروژههای ساده، Cargo تفاوت زیادی با استفادهی مستقیم از rustc
ندارد، اما وقتی پروژهها پیچیدهتر میشوند یا وابستگیهای بیشتری دارند، مدیریت کارها با Cargo بسیار راحتتر خواهد شد.
حتی در همین پروژهی سادهی hello_cargo
، ما از ابزارهایی استفاده کردیم که در کل مسیر یادگیری Rust به کار خواهند آمد. اگر روی یک پروژهی موجود کار میکنید، کافی است کد را از گیت دریافت کنید، وارد دایرکتوری پروژه شوید و آن را بسازید (بیلد کنید):
$ git clone example.org/someproject
$ cd someproject
$ cargo build
برای اطلاعات بیشتر دربارهی Cargo، میتوانید مستندات آن را مطالعه کنید.
جمعبندی
شما شروع بسیار خوبی در یادگیری Rust داشتید! در این فصل یاد گرفتید که:
- نسخهی پایدار Rust را با
rustup
نصب کنید. - نسخهی Rust را بهروز کنید.
- مستندات محلی نصبشده را باز کنید.
- یک برنامهی سادهی
Hello, world!
را باrustc
بنویسید و اجرا کنید. - یک پروژهی جدید بسازید و اجرا کنید، مطابق استانداردهای Cargo.
حالا زمان مناسبی است که یک برنامهی کاربردیتر بنویسید تا بیشتر با Rust آشنا شوید. در فصل بعد، یک بازی حدس اعداد خواهیم ساخت. اما اگر ترجیح میدهید ابتدا با مفاهیم پایهی برنامهنویسی در Rust آشنا شوید، میتوانید فصل ۳ را مطالعه کنید و بعد به فصل ۲ برگردید.