الدرس4 / 4

أول برنامج

قراءة

اللي هتفهمه

  • إزاي تعمل مشروع بـ cargo، وإيه كل ملف بيتعمل بيعمل إيه.
  • الفرق العملي بين cargo build و cargo run و cargo check، وإمتى تستخدم كل واحد.
  • فين الملف التنفيذي بيقع، وليه مالوش امتداد على لينكس وماك.

الشرح

تقدر تترجم ملف Rust واحد بـ rustc مباشرة، بس محدش بيعمل كده في مشروع حقيقي. الأداة اللي هتستخدمها كل يوم هي cargo، وهي مدير مشاريع كامل: بتعمل هيكل المشروع، بتنزّل التبعيات، بتبني، وبتشغّل الاختبارات.

ابدأ من مجلد مشاريعك واعمل مشروع جديد:

cargo new hello

الرد:

    Creating binary (application) `hello` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

cargo 1.97.1 (c980f4866 2026-06-30)

كلمة binary هنا معناها إن ده برنامج بيشتغل، مش مكتبة. لو كنت عايز مكتبة كنت كتبت cargo new --lib.

خد بالك إن cargo new بيعمل مستودع git جوه المشروع كمان — عشان كده فيه .gitignore من غير ما تطلبه.

المرئي

hello/مجلد المشروع├──Cargo.tomlاسم المشروع وإصداره وتبعياته├──.gitignoreسطر واحد جواه: ‎/target└──src/كل الكود بيقعد هنا└──main.rsنقطة البداية — دالة main
اللي بيتعمل بالظبط لما تكتب cargo new hello

الكود

src/main.rs اتعمل جاهز وفيه ده:

fn main() {
    println!("Hello, world!");
}
افتح في Playground

أربع حاجات في تلات سطور:

  • fn بتعرّف دالة.
  • main اسم خاص: دي نقطة بداية كل برنامج تنفيذي في Rust. لو مش موجودة، الترجمة بتفشل.
  • println! — علامة التعجب دي مش زينة. هي بتقول إن ده ماكرو مش دالة، والفرق مهم: الماكرو بيتوسّع لكود تاني وقت الترجمة، وعشان كده بيقدر ياخد عدد متغير من الوسائط ويتحقق من صيغة النص وقت الترجمة.
  • الفاصلة المنقوطة في آخر السطر بتخلّيه جملة. الفرق بين الجملة والتعبير حاجة أساسية في Rust، وليها درس كامل بعد كده.

Cargo.toml

[package]
name = "hello"
version = "0.1.0"
edition = "2024"

[dependencies]
  • name اسم الحزمة، وهو كمان اسم الملف التنفيذي اللي هيطلع.
  • edition إصدار اللغة. Rust بتطلّع إصدار كل تلات سنين، والإصدارات القديمة بتفضل مدعومة للأبد — يعني كودك القديم مش هيقع أبداً. الرقم عندك ممكن يكون مختلف حسب نسخة cargo.
  • [dependencies] فاضي دلوقتي. لما تضيف مكتبة، بتتكتب هنا سطر واحد وcargo بيتولى الباقي.

ليه بيشتغل كده

فيه تلات أوامر هتستخدمهم، وكل واحد ليه سبب وجود مختلف.

cargo run — ابنِ وشغّل

   Compiling hello v0.1.0 (/home/user/hello)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.09s
     Running `target/debug/hello`
Hello, world!

cargo 1.97.1 (c980f4866 2026-06-30)

ده اللي هتستخدمه 90% من الوقت. لاحظ السطر Running — هو بيقولك بالظبط أنهي ملف شغّله.

cargo build — ابنِ بس

   Compiling hello v0.1.0 (/home/user/hello)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.09s

بيطلّع الملف ومش بيشغّله.

cargo check — اتأكد إنه بيترجم، من غير ما تبني

    Checking hello v0.1.0 (/home/user/hello)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s

خد بالك من كلمة Checking بدل Compiling، ومن الوقت. cargo check بيعمل كل التحليل — الأنواع، الملكية، الاستعارة — وبيوقف قبل الخطوة الأغلى، وهي توليد الكود الفعلي.

في مشروع صغير الفرق مش باين. في مشروع حقيقي، check بيبقى أسرع بمرات كتير، وده اللي بيخلّيه الأمر اللي بتشغّله وإنت بتكتب. rust-analyzer بيشغّله لوحده وراك في المحرر — عشان كده بتشوف الأخطاء قبل ما تحفظ.

فين الملف بقى

cargo بيحط كل ناتج البناء في target/، مش جنب src/:

$ ls -F target/debug
build/  deps/  examples/  hello*  hello.d  incremental/

الملف اسمه hello من غير أي امتداد. على لينكس وماك، اللي بيحدد إن الملف تنفيذي هو بِت الصلاحية x، مش اسمه — علامة * اللي ls -F بيحطها معناها إن البِت ده مفعّل. على ويندوز بس هتلاقي hello.exe.

وتقدر تشغّله بنفسك:

./target/debug/hello

الـ ./ مش زيادة — من غيرها الـ shell بيدوّر في مسارات النظام بس ومش بيبص في المجلد اللي إنت واقف فيه.

لو دوّرت على الملف وملقتوش، الشرح الكامل في فين الملف التنفيذي بعد cargo build؟.

تمرين

غيّر src/main.rs عشان يطبع اسمك، وبعدين جاوب:

  1. شغّل cargo build مرتين ورا بعض. إيه الفرق في المخرجات بين المرة الأولى والتانية، وليه؟
  2. شغّل cargo check بعد ما تضيف سطر فيه غلط إملائي (مثلاً printn!). إيه الرسالة؟
  3. جرّب cargo build --release. الملف بيقع فين المرة دي؟
الحل

1. المرة الأولى بتشوف Compiling وبعدها Finished. المرة التانية بتشوف Finished لوحدها، والوقت قريب من الصفر. cargo بيقارن تواريخ تعديل الملفات وبيعرف إن مفيش حاجة اتغيرت، فمش بيعيد الترجمة. المجلد target/incremental/ موجود عشان الحكاية دي بالظبط.

2. cargo check بيوقف على الغلط ومش بيبني حاجة، فالرد بيبقى أسرع بكتير من build. جرّب الاتنين وقارن الوقت المكتوب في سطر النهاية.

3. في target/release/hello، مش target/debug/. بناء الـ release بيشغّل المُحسِّن — أبطأ في الترجمة، أسرع بكتير في التشغيل، وبيشيل معلومات التصحيح.

وفيه فرق تالت أهم من الاتنين دول، هتقابله في درس أنواع البيانات: الفيضان الحسابي بيتصرّف بشكل مختلف في الاتنين. في debug البرنامج بيقف بخطأ واضح، وفي release الرقم بيلف. ده مقصود، والدرس اللي جاي بيشرح ليه.

مشاكل شائعة

النقاش

لو عندك سؤال أو لقيت غلطة في الصفحة دي، اكتبها فيالنقاشات على GitHub. كل صفحة ليها موضوعها الخاص.