C++ के साथ मोनोरेपोजिटरी: कोड संगठन और सर्वोत्तम अभ्यास
C++ में बड़े प्रोजेक्ट्स के विकास में अक्सर कोड विखंडन की समस्या का सामना करना पड़ता है: लाइब्रेरीज़ विभिन्न रिपॉजिटरी में बिखरी होती हैं, वर्ज़न सिंक नहीं होते, और इंटीग्रेशन सिरदर्द बन जाता है। समाधान है मोनोरेपोजिटरी (monorepo)। यह एक दृष्टिकोण है जिसमें लाइब्रेरीज़, यूटिलिटीज़ और टेस्ट सहित सारा कोड एक ही रिपॉजिटरी में संग्रहीत किया जाता है। इस लेख में, हम आधुनिक टूल्स (CMake, Conan, Git) का उपयोग करके और सामान्य गलतियों से बचते हुए, C++ प्रोजेक्ट्स के लिए मोनोरेपोजिटरी को सही ढंग से व्यवस्थित करने का तरीका समझेंगे।
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से बचें —PUBLICयाPRIVATEके साथtarget_include_directoriesका उपयोग करें।
3. मोनोरेपोजिटरी के अंदर निर्भरता प्रबंधन
मोनोरेपोजिटरी की मुख्य समस्याओं में से एक चक्रीय निर्भरताएँ हैं। समाधान: सख्त पदानुक्रम। उदाहरण के लिए:
- core (मानक लाइब्रेरी के अलावा किसी और चीज़ पर निर्भर नहीं करता)
- math (core पर निर्भर करता है)
- network (core और math पर निर्भर करता है)
- server (core, math, network पर निर्भर करता है)
math लाइब्रेरी के लिए CMakeLists.txt का उदाहरण:
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 # स्पष्ट रूप से निर्भरता इंगित करें
```