एक समाधान जो मैंने हाल ही में पाया है वह मेकफाइल आवरण के साथ आउट-ऑफ-सोर्स बिल्ड अवधारणा को संयोजित करना है।
मेरे शीर्ष-स्तरीय CMakeLists.txt फ़ाइल में, मैं इन-सोर्स बिल्ड्स को रोकने के लिए निम्नलिखित शामिल करता हूं:
if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} )
message( FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt." )
endif()
फिर, मैं एक शीर्ष-स्तरीय मेकफाइल बनाता हूं, और इसमें निम्नलिखित शामिल हैं:
# -----------------------------------------------------------------------------
# CMake project wrapper Makefile ----------------------------------------------
# -----------------------------------------------------------------------------
SHELL := /bin/bash
RM := rm -rf
MKDIR := mkdir -p
all: ./build/Makefile
@ $(MAKE) -C build
./build/Makefile:
@ ($(MKDIR) build > /dev/null)
@ (cd build > /dev/null 2>&1 && cmake ..)
distclean:
@ ($(MKDIR) build > /dev/null)
@ (cd build > /dev/null 2>&1 && cmake .. > /dev/null 2>&1)
@- $(MAKE) --silent -C build clean || true
@- $(RM) ./build/Makefile
@- $(RM) ./build/src
@- $(RM) ./build/test
@- $(RM) ./build/CMake*
@- $(RM) ./build/cmake.*
@- $(RM) ./build/*.cmake
@- $(RM) ./build/*.txt
ifeq ($(findstring distclean,$(MAKECMDGOALS)),)
$(MAKECMDGOALS): ./build/Makefile
@ $(MAKE) -C build $(MAKECMDGOALS)
endif
डिफ़ॉल्ट लक्ष्य allटाइप करके बुलाया जाता है make, और लक्ष्य को आमंत्रित करता है ./build/Makefile।
पहली चीज जो लक्ष्य का उपयोग ./build/Makefileकरती है वह है buildनिर्देशिका का उपयोग करना $(MKDIR), जो कि एक चर है mkdir -p। निर्देशिका buildवह जगह है जहां हम अपने आउट-ऑफ-सोर्स निर्माण का प्रदर्शन करेंगे। हम -pयह सुनिश्चित करने के लिए तर्क प्रदान करते हैं कि mkdirएक निर्देशिका बनाने की कोशिश करने के लिए हम पर चिल्लाएं नहीं जो पहले से मौजूद हो।
दूसरी बात ./build/Makefileयह है कि निर्देशिका को निर्देशिका में बदलना buildऔर आह्वान करना है cmake।
allलक्ष्य पर वापस , हम आह्वान करते हैं $(MAKE) -C build, जहां $(MAKE)एक मेकफाइल चर स्वचालित रूप से के लिए उत्पन्न होता है make। make -Cकुछ भी करने से पहले निर्देशिका को बदल देता है। इसलिए, का उपयोग करने $(MAKE) -C buildके बराबर है cd build; make।
संक्षेप में, इस मेकफाइल रैपर को कॉल करना make allया करने makeके बराबर है:
mkdir build
cd build
cmake ..
make
लक्ष्य distcleanका आह्वान cmake ..है, तो make -C build clean, और अंत में, से सभी सामग्री को हटा buildनिर्देशिका। मेरा मानना है कि यह वही है जो आपने अपने प्रश्न में अनुरोध किया था।
Makefile का अंतिम टुकड़ा मूल्यांकन करता है कि उपयोगकर्ता द्वारा प्रदान किया गया लक्ष्य है या नहीं distclean। यदि नहीं, तो यह buildलागू करने से पहले निर्देशिकाओं को बदल देगा । यह बहुत शक्तिशाली है क्योंकि उपयोगकर्ता टाइप कर सकता है, उदाहरण के लिए make clean, और मेकफाइल इसे एक समकक्ष में बदल देगा cd build; make clean।
अंत में, यह मेकफाइल रैपर एक अनिवार्य आउट-ऑफ-सोर्स बिल्ड सीएमके कॉन्फ़िगरेशन के साथ संयोजन में बनाता है, ताकि उपयोगकर्ता को कमांड के साथ कभी भी बातचीत न करनी पड़े cmake। यह समाधान buildनिर्देशिका से सभी CMake आउटपुट फ़ाइलों को हटाने के लिए एक सुरुचिपूर्ण विधि भी प्रदान करता है ।
PS मेकफाइल में, हम @शेल कमांड से आउटपुट को दबाने के लिए उपसर्ग का उपयोग करते हैं , और @-शेल कमांड से त्रुटियों को अनदेखा करने के लिए उपसर्ग । लक्ष्य के rmहिस्से के रूप में उपयोग करते समय distclean, कमांड एक त्रुटि लौटाएगा यदि फाइलें मौजूद नहीं हैं (वे कमांड लाइन का उपयोग करके पहले ही हटा दिया गया हो सकता है rm -rf build, या वे पहली बार में उत्पन्न नहीं हुए थे)। यह वापसी त्रुटि हमारे Makefile को बाहर निकलने के लिए मजबूर करेगी। @-इसे रोकने के लिए हम उपसर्ग का उपयोग करते हैं । यह स्वीकार्य है यदि एक फ़ाइल पहले ही हटा दी गई थी; हम चाहते हैं कि हमारा मेकफाइल चलता रहे और बाकी को हटाया जाए।
एक और बात ध्यान दें: यदि आप अपनी परियोजना का निर्माण करने के लिए सीएमके चर का एक चर संख्या का उपयोग करते हैं, तो यह मेकफाइल काम नहीं कर सकता है, उदाहरण के लिए cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar"। यह मेकफाइल आपको सीएमके को सुसंगत तरीके से, या तो टाइप करके cmake ..या cmakeलगातार तर्क प्रदान करके मानता है (जिसे आप अपने मेकफाइल में शामिल कर सकते हैं)।
अंत में, क्रेडिट जहां क्रेडिट देय है। यह Makefile आवरण C ++ अनुप्रयोग प्रोजेक्ट टेम्पलेट द्वारा प्रदान किए गए Makefile से अनुकूलित किया गया था ।