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

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

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

ابدأ الدورة

مقدمة: لماذا المستودع الأحادي (monorepo) للغة C++؟



في تطوير C++ الحديث، خاصة في المشاريع المتوسطة والكبيرة الحجم، يصبح تنظيم الكود مهمة بالغة الأهمية. المستودع الأحادي (monorepo) هو نهج يتم فيه تخزين كود جميع المكونات والمكتبات والخدمات في مستودع واحد. على عكس المستودعات المتعددة، يقدم المستودع الأحادي نقطة دخول واحدة، ويبسط عملية إعادة الهيكلة وإدارة التبعيات. عمليًا، هذا يعني أنه يمكنك تغيير واجهة برمجة التطبيقات (API) لمكتبة ما ورؤية تأثير ذلك فورًا على جميع الوحدات المعتمدة عليها.



في هذه المقالة، سنقوم بتحليل الجوانب العملية لتنظيم كود C++ في مستودع أحادي: من هيكل المجلدات إلى إعداد CI/CD. ستتعلم كيفية تجنب الأخطاء الشائعة وجعل عملية البناء سريعة ويمكن التنبؤ بها.



1. هيكل المستودع الأحادي للغة C++



هيكل المجلدات الصحيح هو أساس نجاح المستودع الأحادي. دعنا نستعرض التسلسل الهرمي الموصى به لمشاريع C++.



التسلسل الهرمي الأساسي للدلائل



my_project/├── CMakeLists.txt          # ملف البناء الجذري├── cmake/                  # وحدات CMake المخصصة│   └── FindMyLib.cmake├── libs/                   # المكتبات الداخلية│   ├── core/│   │   ├── CMakeLists.txt│   │   ├── include/│   │   │   └── core/│   │   │       ├── utils.h│   │   │       └── types.h│   │   └── src/│   │       ├── utils.cpp│   │       └── types.cpp│   └── network/│       ├── CMakeLists.txt│       ├── include/│       │   └── network/│       │       └── http_client.h│       └── src/│           └── http_client.cpp├── apps/                   # التطبيقات القابلة للتنفيذ│   ├── server/│   │   ├── CMakeLists.txt│   │   └── src/│   │       └── main.cpp│   └── cli/│       ├── CMakeLists.txt│       └── src/│           └── main.cpp├── tests/                  # اختبارات التكامل│   ├── CMakeLists.txt│   └── test_integration.cpp├── third_party/            # التبعيات الخارجية (vendoring)│   ├── fmt/│   └── spdlog/├── .github/                # إعدادات CI/CD│   └── workflows/│       └── build.yml└── README.md


المبادئ الأساسية:

  • libs/ — جميع المكتبات الداخلية. كل مكتبة لها مجلدها الخاص مع CMakeLists.txt.
  • apps/ — الملفات القابلة للتنفيذ. تعتمد على المكتبات الموجودة في libs/.
  • third_party/ — التبعيات المورّدة (git submodules أو المصادر المنسوخة).
  • tests/ — اختبارات التكامل التي تتحقق من تفاعل عدة مكتبات.


مثال على CMakeLists.txt لمكتبة



# libs/core/CMakeLists.txtadd_library(core    src/utils.cpp    src/types.cpp)

target_include_directories(core PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)

target_link_libraries(core PUBLIC fmt::fmt spdlog::spdlog)


هام: استخدم PUBLIC و PRIVATE لتمرير التبعيات بشكل صحيح. هذه نقطة أساسية — إذا كانت المكتبة A تستخدم المكتبة B فقط في ملفاتها المصدرية، اجعل B PRIVATE.



2. إدارة التبعيات في المستودع الأحادي



واحدة من المشاكل الرئيسية للمستودعات الأحادية هي "جحيم التبعيات". في C++، يتم حلها من خلال التصميم الموجه نحو الأهداف في CMake (CMake target-oriented design).



القاعدة: هدف واحد — مكتبة واحدة



يجب على كل مكتبة تصدير هدف CMake واحد بالضبط. هذا يبسط عملية الربط ويمنع التبعيات الدائرية.



# ملف CMakeLists.txt الجذريcmake_minimum_required(VERSION 3.20)project(MyProject VERSION 1.0.0 LANGUAGES CXX)

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

المدونات

توصيات الكتب