كيف تقرأ برنامج Rust بياناته الوصفية من Cargo.toml

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

كيف تقرأ برنامج Rust بياناته الوصفية من Cargo.toml

\n\n

هل سبق لك أن كتبت أداة CLI بلغة Rust وأردت أن تعرض عند تشغيلها مع العلم --version الإصدار الحقيقي الموجود في Cargo.toml بدلاً من "0.1.0"؟ أو ربما احتجت إلى تسجيل اسم الكريت ووصفه في السجلات — ولكن كان سحب هذه النصوص من الكود غير مريح وعرضة للأخطاء؟

\n\n

هذا السؤال من أكثر الأسئلة شيوعاً على Stack Overflow (آلاف المشاهدات!). وليس من دون سبب: قد يبدو قراءة ملف الإعدادات الخاص بك أمراً بسيطاً، لكن في Rust هناك بعض التحديات، والأهم من ذلك، عدة طرق أنيقة للحل.

\n\n

في هذا المقال، سنستعرض ثلاث طرق رئيسية للحصول على البيانات الوصفية لحزمة Cargo مباشرة من الكود: من الماكرو البسيط env!() إلى الطريقة المرنة build.rs. ستتعلم كيفية قراءة الإصدار واسم الكريت والوصف بشكل صحيح، وكيفية تجنب الأخطاء الشائعة.

\n\n

لماذا تحتاج هذا؟ ثلاثة سيناريوهات نموذجية

\n\n

قبل الغوص في الكود، دعنا نفهم لماذا نريد الوصول إلى البيانات الوصفية للحزمة. إليك ثلاث حالات واقعية:

\n\n
    \n
  • أدوات CLI: الأمر myapp --version يجب أن يعرض الإصدار من Cargo.toml، وليس قيمة ثابتة.
  • \n
  • السجلات والقياس عن بعد: عند بدء التطبيق، من المفيد تسجيل اسم الكريت وإصداره في السجل — مما يسهل عملية التصحيح.
  • \n
  • التوليد التلقائي للتوثيق: يمكنك إدراج وصف الكريت في رسالة المساعدة أو ملف README الذي يتم إنشاؤه ديناميكياً.
  • \n
\n\n

الآن بعد أن فهمنا "لماذا"، ننتقل إلى "كيف".

\n\n

الطريقة الأولى: ماكرو env!() — الأبسط والأكثر شيوعاً

\n\n

الطريقة الأكثر مباشرة هي استخدام الماكرو المدمج env!(). يتيح لك قراءة متغيرات البيئة التي يضبطها Cargo تلقائياً أثناء التجميع. إليك قائمة بأكثرها فائدة:

\n\n
    \n
  • CARGO_PKG_NAME — اسم الحزمة (مثال: "my_cool_app")
  • \n
  • CARGO_PKG_VERSION — الإصدار (مثال: "0.2.1")
  • \n
  • CARGO_PKG_DESCRIPTION — الوصف من حقل description في Cargo.toml
  • \n
  • CARGO_PKG_AUTHORS — قائمة المؤلفين مفصولة بنقطتين
  • \n
  • CARGO_PKG_LICENSE — الترخيص
  • \n
  • CARGO_PKG_REPOSITORY — رابط المستودع
  • \n
\n\n

مثال على الاستخدام:

\n\n
fn main() {\n    let name = env!("CARGO_PKG_NAME");\n    let version = env!("CARGO_PKG_VERSION");\n\n    println!("{} v{}", name, version);\n    // المخرجات: my_cool_app v0.2.1\n}\n
\n\n

مهم: env!() هو ماكرو وقت التجميع. إذا لم يتم تعيين متغير البيئة، فلن يتم تجميع البرنامج! هذه ميزة (أمان الأنواع) وعيب (لا يمكنك عمل fallback إلى قيمة ثابتة بدون حيل إضافية).

\n\n

إذا كنت بحاجة إلى الإصدار فقط لأغراض التصحيح، يمكنك استخدام option_env!() الذي يُرجع Option<&str>:

\n\n
let version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown");\nprintln!("Version: {}", version);\n
\n\n

هذه الطريقة مثالية لـ 90% من الحالات. لا تتطلب تبعيات إضافية وتعمل "مباشرة من الصندوق".

\n\n

الطريقة الثانية: include_str!() + التحليل اليدوي — للتحكم الكامل

\n\n

أحياناً لا تحتاج فقط إلى قراءة حقل واحد، بل إلى الحصول على بيانات منظمة من Cargo.toml. مثلاً، جميع التبعيات أو الكلمات المفتاحية. في هذه الحالة، يمكنك قراءة الملف نفسه كنص وتحليله.

\n\n
fn main() {\n    let cargo_toml = include_str!("../Cargo.toml");\n    // هنا يمكنك استخدام محلل toml، لكن للمثال — بحث بسيط\n    if let Some(line) = cargo_toml.lines().find(|l| l.starts_with("version =")) {\n        let version = line.trim_start_matches("version = \\"").trim_end_matches('"');\n        println!("Version from file: {}", version);\n    }\n}\n
\n\n

هذه الطريقة تعطيك مرونة كاملة، لكنها تتطلب منك التعامل مع تحليل النص بنفسك. يمكنك استخدام مكتبة مثل toml لتحليل أكثر احترافية.

المدونات

توصيات الكتب