स्टार्टर के रूप में, निर्देशिका के कुछ पारंपरिक नाम हैं जिन्हें आप अनदेखा नहीं कर सकते हैं, ये यूनिक्स फाइल सिस्टम के साथ लंबी परंपरा पर आधारित हैं। य़े हैं:
trunk
├── bin : for all executables (applications)
├── lib : for all other binaries (static and shared libraries (.so or .dll))
├── include : for all header files
├── src : for source files
└── doc : for documentation
कम से कम शीर्ष स्तर पर, इस मूल लेआउट से चिपके रहना शायद एक अच्छा विचार है।
शीर्ष लेख फ़ाइलों और स्रोत फ़ाइलों (cpp) को विभाजित करने के बारे में, दोनों योजनाएँ काफी सामान्य हैं। हालांकि, मैं उन्हें एक साथ रखना पसंद करता हूं, यह फाइलों को एक साथ रखने के लिए दिन-प्रतिदिन के कार्यों पर अधिक व्यावहारिक है। इसके अलावा, जब सभी कोड एक शीर्ष-स्तरीय फ़ोल्डर के अंतर्गत होते हैं, अर्थात, trunk/src/
आप देख सकते हैं कि शीर्ष स्तर पर, अन्य सभी फ़ोल्डर (बिन, lib, शामिल, डॉक्टर, और शायद कुछ परीक्षण फ़ोल्डर), इसके अलावा आउट-ऑफ-सोर्स बिल्ड के लिए "बिल्ड" डायरेक्टरी, सभी फ़ोल्डर हैं जिनमें बिल्ड प्रक्रिया में उत्पन्न फ़ाइलों से अधिक कुछ नहीं है। और इस प्रकार, केवल src फ़ोल्डर को बैकअप नियंत्रण प्रणाली / सर्वर (जैसे Git या SVN) के तहत रखने की आवश्यकता होती है, या बहुत बेहतर।
और जब यह आपके हेडर फाइल को गंतव्य प्रणाली पर स्थापित करने की बात आती है (यदि आप अंततः अपनी लाइब्रेरी को वितरित करना चाहते हैं), तो, सीएमके में फाइलें स्थापित करने के लिए एक कमांड है ("स्थापित करें" करने के लिए, "स्थापित करें" लक्ष्य बनाएं) आप /usr/include/
निर्देशिका में सभी हेडर डालने के लिए उपयोग कर सकते हैं । मैं सिर्फ इस उद्देश्य के लिए निम्नलिखित cmake मैक्रो का उपयोग करता हूं:
# custom macro to register some headers as target for installation:
# setup_headers("/path/to/header/something.h" "/relative/install/path")
macro(setup_headers HEADER_FILES HEADER_PATH)
foreach(CURRENT_HEADER_FILE ${HEADER_FILES})
install(FILES "${SRCROOT}${CURRENT_HEADER_FILE}" DESTINATION "${INCLUDEROOT}${HEADER_PATH}")
endforeach(CURRENT_HEADER_FILE)
endmacro(setup_headers)
जहाँ SRCROOT
एक cmake वैरिएबल है जिसे मैंने src फ़ोल्डर में सेट किया है, और INCLUDEROOT
cmake वैरिएबल है जिसे मैं हेडर में जाने के लिए जहाँ भी कॉन्फ़िगर करता हूँ। बेशक, ऐसा करने के कई अन्य तरीके हैं, और मुझे यकीन है कि मेरा तरीका सबसे अच्छा नहीं है। मुद्दा यह है कि हेडर और स्रोतों को विभाजित करने का कोई कारण नहीं है, क्योंकि केवल हेडर को लक्ष्य प्रणाली पर स्थापित करने की आवश्यकता है, क्योंकि यह बहुत आसान है, विशेष रूप से सीएमके (या सीपीैक) के साथ, हेडर को बाहर निकालने और कॉन्फ़िगर करने के लिए। उन्हें एक अलग निर्देशिका में स्थापित किए बिना स्थापित किया जाए। और यही मैंने ज्यादातर पुस्तकालयों में देखा है।
उद्धरण: दूसरे मैं अपने कोड के परीक्षण के लिए Google C ++ टेस्टिंग फ्रेमवर्क का उपयोग करना चाहूंगा क्योंकि यह उपयोग करने में काफी आसान लगता है। क्या आप इसे मेरे कोड से जोड़ने का सुझाव देते हैं, उदाहरण के लिए "inc / gtest" या "contrib / gtest" फ़ोल्डर में? यदि बंडल किया गया है, तो क्या आप संख्या या फ़ाइलों को कम करने के लिए fuse_gtest_files.py स्क्रिप्ट का उपयोग करने का सुझाव देते हैं, या जैसा है वैसा ही छोड़ देते हैं? यदि बंडल नहीं है तो यह निर्भरता कैसे नियंत्रित की जाती है?
अपने पुस्तकालय के साथ निर्भरता को बंडल न करें। यह आम तौर पर एक बहुत ही भयानक विचार है, और मैं हमेशा इसे नफरत करता हूं जब मैं एक पुस्तकालय बनाने की कोशिश कर रहा हूं जो ऐसा किया था। यह आपका अंतिम उपाय होना चाहिए, और नुकसान से सावधान रहना चाहिए। अक्सर, लोग अपनी लाइब्रेरी के साथ निर्भरता को या तो बंडल करते हैं, क्योंकि वे एक भयानक विकास के वातावरण (जैसे, विंडोज) को लक्षित करते हैं, या क्योंकि वे केवल पुस्तकालय (निर्भरता) के एक पुराने (अस्वीकृत) संस्करण का समर्थन करते हैं। मुख्य नुकसान यह है कि आपकी बंडल की गई निर्भरता उसी लाइब्रेरी / एप्लिकेशन के पहले से इंस्टॉल किए गए संस्करणों के साथ टकरा सकती है (उदाहरण के लिए, आपने gtest को बंडल किया है, लेकिन आपके लाइब्रेरी का निर्माण करने की कोशिश करने वाले व्यक्ति के पास पहले से ही स्थापित gtest का नया (या पुराना) संस्करण है, फिर दोनों टकरा सकते हैं और उस व्यक्ति को बहुत बुरा सिरदर्द दे सकते हैं)। इसलिए, जैसा कि मैंने कहा, इसे अपने जोखिम पर करें, और मैं केवल अंतिम उपाय के रूप में कहूंगा। अपनी लाइब्रेरी को संकलित करने में सक्षम होने से पहले कुछ निर्भरताएं स्थापित करने के लिए लोगों से पूछना आपके बंडल पर निर्भरता और मौजूदा प्रतिष्ठानों के बीच संघर्ष को सुलझाने की कोशिश करने की तुलना में बहुत कम बुराई है।
उद्धरण: जब लेखन परीक्षण की बात आती है, तो ये आम तौर पर कैसे व्यवस्थित होते हैं? मैं प्रत्येक वर्ग (उदाहरण के लिए test_vector3.cpp) के लिए एक cpp फ़ाइल रखने की सोच रहा था, लेकिन सभी एक बाइनरी में संकलित हैं ताकि वे सभी आसानी से एक साथ चल सकें?
प्रति वर्ग (या कक्षाओं और कार्यों के छोटे सामंजस्यपूर्ण समूह) प्रति एक सीपीपी फ़ाइल मेरी राय में अधिक सामान्य और व्यावहारिक है। हालाँकि, निश्चित रूप से, उन सभी को केवल एक बाइनरी में संकलित न करें ताकि "वे सभी एक साथ चल सकें"। यह एक बहुत बुरा विचार है। आमतौर पर, जब कोडिंग की बात आती है, तो आप चीजों को उतना ही विभाजित करना चाहते हैं जितना कि ऐसा करना वाजिब है। यूनिट-परीक्षणों के मामले में, आप सभी परीक्षणों को चलाने के लिए एक बाइनरी नहीं चाहते हैं, क्योंकि इसका मतलब है कि आपके पुस्तकालय में किसी भी चीज़ में थोड़ा सा भी बदलाव होने पर उस इकाई-परीक्षण कार्यक्रम के निकट पुनर्मिलन होने की संभावना है , और वह बस कुछ ही मिनटों / घंटों के लिए इंतजार कर रहे थे। बस एक साधारण योजना से चिपके रहें: 1 इकाई = 1 इकाई-परीक्षण कार्यक्रम। फिर,
उद्धरण: चूँकि gtest लाइब्रेरी आमतौर पर cmake और मेक का उपयोग करके निर्मित होती है, मैं सोच रहा था कि यह मेरी परियोजना के लिए भी समझ में आएगा? यदि मैंने निम्नलिखित प्रोजेक्ट लेआउट का उपयोग करने का निर्णय लिया है:
मैं इस लेआउट का सुझाव दूंगा:
trunk
├── bin
├── lib
│ └── project
│ └── libvector3.so
│ └── libvector3.a products of installation / building
├── docs
│ └── Doxyfile
├── include
│ └── project
│ └── vector3.hpp
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
│
├── src
│ └── CMakeLists.txt
│ └── Doxyfile.in
│ └── project part of version-control / source-distribution
│ └── CMakeLists.txt
│ └── vector3.hpp
│ └── vector3.cpp
│ └── test
│ └── test_vector3.cpp
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
│
├── build
└── test working directories for building / testing
└── test_vector3
यहाँ ध्यान देने योग्य कुछ बातें। सबसे पहले, आपकी src निर्देशिका की उप-निर्देशिकाओं में आपकी शामिल निर्देशिका की उप-निर्देशिकाओं को प्रतिबिंबित करना चाहिए, यह सिर्फ चीजों को सहज रखने के लिए है (साथ ही, अपने उप-निर्देशिका संरचना को यथोचित रूप से सपाट (उथले) रखने की कोशिश करें, क्योंकि फ़ोल्डरों के गहरे घोंसले के शिकार) अक्सर किसी अन्य चीज की तुलना में अधिक परेशानी होती है)। दूसरा, "शामिल" निर्देशिका सिर्फ एक अधिष्ठापन निर्देशिका है, इसकी सामग्री बस वही है जो हेडर src निर्देशिका से बाहर निकाले जाते हैं।
तीसरा, CMake सिस्टम को स्रोत उप-निर्देशिकाओं में वितरित करने का इरादा है, न कि शीर्ष स्तर पर एक CMakeLists.txt फ़ाइल के रूप में। यह चीजों को स्थानीय रखता है, और यह अच्छा है (चीजों को स्वतंत्र टुकड़ों में विभाजित करने की भावना में)। यदि आप एक नया स्रोत, एक नया हेडर, या एक नया परीक्षण कार्यक्रम जोड़ते हैं, तो आपको केवल एक और छोटे और सरल CMakeLists.txt फ़ाइल को किसी अन्य चीज को प्रभावित किए बिना, उप-निर्देशिका में संपादित करना है। यह आपको आसानी से निर्देशिकाओं का पुनर्गठन करने की भी अनुमति देता है (CMakeLists स्थानीय हैं और उप-निर्देशिकाओं में निहित हैं)। शीर्ष स्तर के CMakeLists में अधिकांश शीर्ष-स्तरीय कॉन्फ़िगरेशन होते हैं, जैसे कि गंतव्य निर्देशिकाओं को सेट करना, कस्टम कमांड (या मैक्रोज़), और सिस्टम पर स्थापित पैकेज खोजना। निचले स्तर के CMakeLists में हेडर, स्रोतों की केवल सरल सूची होनी चाहिए,
उद्धरण: CMakeLists.txt को कैसे देखना होगा ताकि यह या तो सिर्फ पुस्तकालय या पुस्तकालय और परीक्षणों का निर्माण कर सके?
मूल उत्तर यह है कि सीएमके आपको विशेष रूप से "सभी" (जो कि "मेक" टाइप करने पर बनाया गया है) से कुछ लक्ष्यों को बाहर करने की अनुमति देता है, और आप लक्ष्यों के विशिष्ट बंडल भी बना सकते हैं। मैं यहां सीएमके ट्यूटोरियल नहीं कर सकता, लेकिन यह स्वयं के द्वारा पता लगाने के लिए काफी सीधा है। इस विशिष्ट मामले में, हालांकि, अनुशंसित समाधान, निश्चित रूप से, सीरेस्ट का उपयोग करने के लिए है, जो कि कमांड का एक अतिरिक्त सेट है जिसका उपयोग आप कई लक्ष्यों (कार्यक्रमों) को पंजीकृत करने के लिए CMakeLists फाइलों में कर सकते हैं जिन्हें इकाई के रूप में चिह्नित किया गया है- परीक्षण। तो, सीएमके सभी परीक्षणों को एक विशेष श्रेणी के बिल्ड की श्रेणी में रखेगा, और ठीक वही है जो आपने पूछा था, इसलिए, समस्या हल हो गई।
Quote: इसके अलावा, मैंने काफी कुछ प्रोजेक्ट देखे हैं जिनमें एक बिल्ड विज्ञापन एक बिन निर्देशिका है। क्या बिल्ड बिल्ड निर्देशिका में होता है और फिर बायनेरिज़ बिन निर्देशिका में चले गए? क्या परीक्षण और पुस्तकालय के लिए बायनेरिज़ एक ही जगह पर रहेंगे? या इसे इस तरह से संरचना करने के लिए अधिक समझ में आता है:
स्रोत ("आउट-ऑफ-सोर्स" बिल्ड) के बाहर एक बिल्ड डायरेक्टरी होना वास्तव में एकमात्र समझदारी की बात है, यह इन दिनों वास्तविक मानक है। तो, निश्चित रूप से, स्रोत निर्देशिका के बाहर एक अलग "बिल्ड" डायरेक्टरी है, जैसा कि सीएमके लोग सलाह देते हैं, और जैसा कि मैंने कभी भी किया है, हर प्रोग्रामर करता है। बिन निर्देशिका के लिए, ठीक है, यह एक सम्मेलन है, और शायद यह एक अच्छा विचार है कि मैं उससे चिपके रहूं, जैसा कि मैंने इस पोस्ट की शुरुआत में कहा था।
Quote: मैं अपने कोड को डॉक्यूमेंट करने के लिए doxygen का इस्तेमाल करना चाहूंगा। क्या यह संभव है कि यह स्वचालित रूप से सेमीक के साथ चले और बनाये?
हाँ। यह संभव से अधिक है, यह भयानक है। इस बात पर निर्भर करता है कि आप कैसा फैंस हासिल करना चाहते हैं, इसकी कई संभावनाएं हैं। CMake के पास Doxygen (यानी find_package(Doxygen)
) के लिए एक मॉड्यूल है, जो आपको कुछ फ़ाइलों पर Doxygen चलाए जाने वाले लक्ष्यों को पंजीकृत करने की अनुमति देता है। यदि आप अधिक फैंसी चीजें करना चाहते हैं, जैसे कि Doxyfile में संस्करण संख्या को अपडेट करना, या स्रोत फ़ाइलों के लिए दिनांक / लेखक टिकटों को स्वचालित रूप से दर्ज करना और इसी तरह, यह सभी CMake कुंग-फू के साथ संभव है। आम तौर पर, ऐसा करने में शामिल होगा कि आप एक स्रोत Doxyfile (उदाहरण के लिए, "Doxyfile.in" जो कि मैं ऊपर फ़ोल्डर लेआउट में रखता हूं) को रखा जाना है, जिसमें सीएमके के पार्सिंग कमांड को ढूंढना और प्रतिस्थापित करना है। में अपने शीर्ष स्तर CMakeLists फ़ाइल , आप CMake कुंग फू कि cmake-Doxygen एक साथ के साथ कुछ फैंसी काम करता है में से एक इस तरह के टुकड़े मिल जाएगा।