2010-09-15 9 views
12

यह मेरा वर्तमान मेकफ़ाइल है।यह मेकफ़ाइल 'साफ करें' पर एक लक्ष्य निष्पादित क्यों करता है

CXX  = g++ 
CXXFLAGS = -Wall -O3 
LDFLAGS = 

TARGET = testcpp 
SRCS = main.cpp object.cpp foo.cpp 
OBJS = $(SRCS:.cpp=.o) 
DEPS = $(SRCS:.cpp=.d) 


.PHONY: clean all 

all: $(TARGET) 

$(TARGET): $(OBJS) 
    $(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $(TARGET) 

.cpp.o: 
    $(CXX) $(CXXFLAGS) -c $< -o [email protected] 

%.d: %.cpp 
    $(CXX) -M $(CXXFLAGS) $< > [email protected] 

clean: 
    rm -f $(OBJS) $(DEPS) $(TARGET) 

-include $(DEPS) 

यह एक अपवाद के साथ पूरी तरह से काम करता है। यदि निर्देशिका (कोई * .D, * ओ) पहले से ही साफ है और मैं चलाने के 'स्वच्छ बनाने', इसे फिर से पैदा करता है निर्भरता, तो तुरंत उन्हें हटाता है:

[[email protected] proj]$ make 
g++ -M -Wall -O3 foo.cpp > foo.d 
g++ -M -Wall -O3 object.cpp > object.d 
g++ -M -Wall -O3 main.cpp > main.d 
g++ -Wall -O3 -c main.cpp -o main.o 
g++ -Wall -O3 -c object.cpp -o object.o 
g++ -Wall -O3 -c foo.cpp -o foo.o 
g++ -Wall -O3 main.o object.o foo.o -o testcpp 
[[email protected] proj]$ make clean 
rm -f main.o object.o foo.o main.d object.d foo.d testcpp 
[[email protected] proj]$ make clean 
g++ -M -Wall -O3 foo.cpp > foo.d 
g++ -M -Wall -O3 object.cpp > object.d 
g++ -M -Wall -O3 main.cpp > main.d 
rm -f main.o object.o foo.o main.d object.d foo.d testcpp 
[[email protected] proj]$ 

मुझे समझ नहीं आता क्यों दूसरा 'साफ करें' निर्भरता फ़ाइलों को फिर से उत्पन्न करेगा। इससे कैसे बचा जा सकता है? यह इस प्रदूषित उदाहरण के लिए एक बड़ा सौदा नहीं है, लेकिन एक बड़ी परियोजना के लिए, यह काफी समय लेने वाला हो सकता है।

धन्यवाद।

+4

आप किस ट्रैकिंग के लिए एक समाधान का वर्णन करता है http://mad-scientist.net/make/autodep.html को पढ़ने के लिए, चाहते हो सकता है निर्भरता कि इस समस्या से बचा जाता है, साथ ही आश्चर्यजनक रूप से कई अन्य जटिलताओं में शामिल हैं। – slowdog

उत्तर

21

ऐसा इसलिए है क्योंकि .d फ़ाइलें -include डी बिना शर्त हैं। जहां तक ​​make जानता है, वे clean लक्ष्य पर निर्भरता या आदेश जोड़ सकते हैं। इस कारण से सभी include डी फ़ाइलें पहले बनाई गई हैं, अन्यथा आपको गलत या असफल बिल्ड मिल सकता है। इसे निष्क्रिय करने के लिए, आप सशर्त निर्भरता फ़ाइलें शामिल करना चाहते हैं:

ifneq ($(MAKECMDGOALS),clean) 
-include $(DEPS) 
endif 

एक वैकल्पिक समाधान touch का उपयोग कर निर्भरता फ़ाइलें पैदा करते हैं और उन्हें संकलन का एक पक्ष प्रभाव के रूप में वास्तविक डेटा के द्वारा बदल दिया है। इस प्रकार ऑटोमैट अपनी निर्भरता ट्रैकिंग करता है, क्योंकि यह एक बार तेजी से बनाता है। यदि आप इस मार्ग पर जाना चाहते हैं तो -MD और -MMD विकल्पों को gcc पर देखें। पैटर्न पैटर्न का प्रयोग करें जैसे:

%.d: 
    @touch [email protected] 

प्रारंभ में निर्भरता फ़ाइलों को बनाने के लिए।

+0

ओह, अच्छी चाल। मुझे '$ (MAKECMDGOALS)' के बारे में पता नहीं था। – zwol

+0

बस एक नोट: एक बार में कई लक्ष्यों का निर्माण करना संभव है - उदाहरण के लिए: 'सभी साफ करें' '$ (MAKECMDGOALS) 'को' सभी स्वच्छ 'पर सेट करेगा, जो अभी भी उल्लिखित बयान के शरीर का आह्वान करेगा। यह इतना बुरा नहीं होगा, हालांकि 'सभी' लक्ष्य के लिए '$ (DEPS)' को शामिल करने की आवश्यकता होती है। यदि आपके पास एक और लक्ष्य था जिसे संभवतः साफ से बुलाया जा सकता है, तो आपको अपने 'ifneq' कथन में अधिक चालाक होना होगा – John

4

यह निर्भरता फ़ाइलों को पुन: उत्पन्न करना चाहता है क्योंकि यह हमेशा कुछ भी करने से पहले, सभी अंतर्निहित मेकफ़ाइल सहित पुनर्नवीनीकरण करने का प्रयास करता है। (खैर, असल में, मेरे लिए यह ऐसा नहीं करता है - मेरे पास जीएनयू 3.81 है - तो हो सकता है कि यह आपके संस्करण में एक बग है जो तय किया गया था, या मेरे पास ऑप्टिमाइज़ेशन है और आपका नहीं है। लेकिन वैसे भी।)

इसके आस-पास का सबसे आसान तरीका अपने नियमों को लिखना है ताकि वे उत्पन्न करने के लिए स्पष्ट नियम देने के बजाय नियमित संकलन के दुष्प्रभाव के रूप में .d फ़ाइलों को उत्पन्न कर सकें। इस तरह, जब वे वहां नहीं होते हैं, तो उन्हें नहीं पता कि उन्हें कैसे उत्पन्न किया जाए, इसलिए यह कोशिश नहीं करता है (एक स्वच्छ पेड़ में, .cpp.o नियम पर्याप्त हैं, आप को हेडर फ़ाइल की आवश्यकता नहीं है निर्भरता)। ऑटोमैक-जेनरेटेड मेकफ़ाइल को देखें - एक साधारण - यह देखने के लिए कि यह कैसे किया जाता है।

2

प्रमुख -include में - मतलब यह है कि make शिकायत नहीं होगा अगर निर्भरता याद कर रहे हैं और पुनर्निर्माण नहीं किया जा सकता है, लेकिन इसका मतलब यह नहीं यह उनके बनाने की कोशिश नहीं जाएगा पहली (और, इस मामले में, सफल) - आखिरकार, कुछ भी रोचक या महत्वपूर्ण शामिल फ़ाइलों में हो सकता है, जहां से उन्हें प्रयास करने की कोशिश की जाती है। मुझे नहीं लगता कि इसे रोकने का एक तरीका है।

include और -include पर दस्तावेज़ों के लिए, here देखें।

4

यदि आप एकाधिक लक्ष्यों के लिए शामिल करना चाहते हैं, तो आप filter फ़ंक्शन का उपयोग कर सकते हैं।

MAKEFILE_TARGETS_WITHOUT_INCLUDE := clean distclean doc 

# Include only if the goal needs it 
ifeq ($(filter $(MAKECMDGOALS),$(MAKEFILE_TARGETS_WITHOUT_INCLUDE)),) 
    -include $(DEPS) 
endif 
संबंधित मुद्दे