مستودع واحد مع C++: تنظيم الكود وأفضل الممارسات

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

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

ابدأ الدورة

مستودع واحد (مونوريبو) مع C++: تنظيم الكود وأفضل الممارسات



غالبًا ما يواجه تطوير المشاريع الكبيرة بلغة C++ مشكلة تجزئة الكود: حيث تكون المكتبات موزعة عبر مستودعات مختلفة، والإصدارات غير متزامنة، ويصبح التكامل بمثابة صداع. الحل هو المستودع الواحد (monorepo). هذا نهج يتم فيه تخزين جميع الكود، بما في ذلك المكتبات والأدوات المساعدة والاختبارات، في مستودع واحد. في هذه المقالة، سنشرح كيفية تنظيم مستودع واحد لمشاريع C++ بشكل صحيح، باستخدام أدوات حديثة (CMake, Conan, Git) وتجنب الأخطاء النموذجية.



1. هيكل الدلائل: أساس النظام



الخطوة الأولى هي إنشاء هيكل مجلدات موحد وواضح. إليك المخطط الموصى به لمستودع واحد بلغة C++:



my-monorepo/├── cmake/                  # وحدات CMake المشتركة├── libs/                   # المكتبات│   ├── core/               # النواة (تسجيل، مخصصات)│   ├── math/               # مكتبة رياضيات│   └── network/            # مكتبة شبكات├── apps/                   # التطبيقات القابلة للتنفيذ│   ├── server/             # تطبيق الخادم│   └── client/             # تطبيق العميل├── tests/                  # اختبارات التكامل├── scripts/                # نصوص البناء والنشر├── third_party/            # التبعيات الخارجية (submodules)├── CMakeLists.txt          # ملف CMake الجذري├── conanfile.txt           # مدير التبعيات (اختياري)└── .github/                # CI/CD (GitHub Actions)


لماذا يعمل هذا؟

  • libs/ — جميع المكتبات في مكان واحد، سهلة إعادة الاستخدام.
  • apps/ — التطبيقات التي تعتمد على libs.
  • third_party/ — التبعيات الخارجية (عبر git submodules أو CMake FetchContent).
  • cmake/ — دوال مخصصة (مثل add_library_with_tests).


2. CMake: إعداد المشروع الجذري



CMake هو المعيار لبناء C++ في المستودعات الواحدة. قم بإعداد ملف CMakeLists.txt الجذري بحيث يضم جميع المشاريع الفرعية:



cmake_minimum_required(VERSION 3.20)project(MyMonorepo LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)set(CMAKE_CXX_STANDARD_REQUIRED ON)

# خيارات عامةoption(BUILD_TESTS "Build tests" ON)

# تضمين المكتباتadd_subdirectory(libs/core)add_subdirectory(libs/math)add_subdirectory(libs/network)

# تضمين التطبيقاتadd_subdirectory(apps/server)add_subdirectory(apps/client)

# تضمين الاختباراتif(BUILD_TESTS) enable_testing() add_subdirectory(tests)endif()


نقاط مهمة:

  • استخدم target_link_libraries لتحديد التبعيات بين المكتبات بشكل صريح.
  • بالنسبة للتبعيات الخارجية (مثل Boost, fmt) استخدم FetchContent أو Conan.
  • تجنب استخدام include_directories العامة — استخدم target_include_directories مع PUBLIC أو PRIVATE.


3. إدارة التبعيات داخل المستودع الواحد



إحدى المشكلات الرئيسية للمستودع الواحد هي التبعيات الدائرية. الحل: تسلسل هرمي صارم. على سبيل المثال:



  • core (لا يعتمد على أي شيء باستثناء المكتبة القياسية)
  • math (يعتمد على core)
  • network (يعتمد على core و math)
  • server (يعتمد على core, math, network)


مثال لملف CMakeLists.txt للمكتبة math:



add_library(math    src/vector.cpp    src/matrix.cpp    include/math/vector.h    include/math/matrix.h)

target_include_directories(math PUBLIC include PRIVATE src)

target_link_libraries(math PUBLIC core # نحدد صراحة اعتماد

المدونات

توصيات الكتب