एक समाधान जो मैंने हाल ही में पाया है वह मेकफाइल आवरण के साथ आउट-ऑफ-सोर्स बिल्ड अवधारणा को संयोजित करना है।
मेरे शीर्ष-स्तरीय 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 से अनुकूलित किया गया था ।