2013-05-24 3 views
9

recompiling मैं मेकफ़ाइल सेट अप करने के तरीके सीख रहा हूँ, और एक समस्या में भाग गया है। इसे प्रदर्शित करने के लिए मैंने एक सरल "प्रोजेक्ट" बनाया है जिसमें स्रोत फ़ाइलों main.m और test.m शामिल हैं।मेकफ़ाइल हमेशा एक फ़ाइल

मैं इन फ़ाइलों (केवल यदि somethings परिवर्तित) संकलन, और वस्तु फ़ाइलों कहीं और में (यहाँ build/) स्टोर करने के लिए बनाने के सेटअप करने के लिए कोशिश कर रहा हूँ

मेरे Makefile:

OBJ = ./build 

SOURCES=main.m test.m 
OBJECTS=$(addprefix $(OBJ)/,$(SOURCES:.m=.o)) 
EXECUTABLE=test 

all: $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS) 
     gcc $(OBJECTS) -o $(EXECUTABLE) 

$(OBJECTS): $(OBJ)/%.o: %.m build/ 
     gcc -c $< -o [email protected] 

build/: 
     mkdir build 

जब मैं चलाने

gcc -c main.m -o build/main.o 
gcc -c test.m -o build/test.o 
gcc ./build/main.o ./build/test.o -o test 

लेकिन अगर मैंचलाएँ: यह (केवल Makefile के साथ और मौजूदा निर्देशिका में सूत्रों का कहना है) पहली बार के लिए यह मैं इसे करने की उम्मीद क्या करता हैदोबारा:

gcc -c main.m -o build/main.o 
gcc ./build/main.o ./build/test.o -o test 

मैंने क्या गलत किया है? मेकफ़ाइल में किसी भी अन्य त्रुटियों को ध्यान में रखते हुए भी सराहना की जाती है, क्योंकि मैं "अच्छा" मेकफ़ाइल बनाने के लिए सीखने की कोशिश कर रहा हूं।

संपादित करें:

मैं make -d से क्या देखा:

Finished prerequisites of target file `build/main.o'. 
Prerequisite `main.m' is older than target `build/main.o'. 
Prerequisite `build/' is older than target `build/main.o'. 
No need to remake target `build/main.o'. 

और

Finished prerequisites of target file `build/test.o'. 
Prerequisite `test.m' is older than target `build/test.o'. 
Prerequisite `build/' is newer than target `build/test.o'. 
Must remake target `build/test.o'. 
+0

मुझे लगता है कि तुम सिर्फ '/' एक में 'build' से जुड़ी नहीं करना चाहते कुछ स्थानों पर। मैं इसे यहाँ आज़माएं। आप 'मेक-डी' का उपयोग यह देखने के लिए कर सकते हैं कि 'मेक' किस प्रकार निर्माण करने के बारे में अपने निर्णय ले रहा है, अगर इससे मदद मिलती है। –

+0

धन्यवाद। हालांकि 'मेक-डी' मार्ग में थोड़ी देर लगने जा रही है क्योंकि यह जानकारी के 927 लाइनों को आउटपुट करता है :) – varesa

+0

आप जितना निर्दोष नियमों को छिपाने के लिए इसे शांत कर सकते हैं। मैंने बस एक सरल परीक्षण परियोजना के साथ अपने मेकफ़ाइल की कोशिश की, और ऐसा लगता है कि यह अपेक्षित काम करता है। दूसरी तरफ, मैं बस 'मेक' प्राप्त करता हूं: 'सब' के लिए कुछ नहीं किया जाना चाहिए। –

उत्तर

9

आपका make -d उत्पादन से पता चलता make सोचता है कि अपने निर्माण निर्देशिका अद्यतन किया गया है, और इसलिए है कि फाइल की जरूरत पुनर्निर्मित करने के लिए।

मुझे लगता है कि ऐसा होता है क्योंकि कुछ या तो आपके निर्माण सिस्टम के हिस्से पर या आपके फाइल सिस्टम में कुछ और द्वारा इस ऑपरेशन को अद्यतन करने के लिए कुछ टाइमस्टैम्प का कारण बनता है। के बाद से यह कुछ भी नहीं कर रहा था

$(OBJECTS): $(OBJ)/%.o: %.m | build 

मैं / भी नष्ट कर दिया,:

आपको लगता है कि शासन के लिए एक | जोड़कर build एक आदेश केवल-शर्त बनाकर इस समस्या को ठीक कर सकते हैं।

जब से तुम से पूछा, कुछ अन्य संपादकीय नोट:

  1. एक clean लक्ष्य जोड़ें। कुछ की तरह: जब आप OBJ सेट

    clean: 
        rm -rf $(EXECUTABLE) $(OBJ) 
    
  2. आप ./ जरूरत नहीं है। बस OBJ = build पर्याप्त है।

  3. आपको ऊपर उल्लिखित build पर / की आवश्यकता नहीं है। लेकिन इससे कोई फर्क नहीं पड़ता है, क्योंकि आपको इसे किसी भी तरह से संदर्भित नहीं करना चाहिए। $(OBJ) जहां भी आप इसे देखते हैं, को दोबारा दोहराएं।

  4. mkdir निर्देशिका विफल होने पर विफल हो जाएगी।आप शायद एक - साथ कि आदेश उपसर्ग चाहिए:

    $(OBJ): 
        -mkdir $(OBJ) 
    

    ध्यान दें कि मैं $(OBJ) कि मैं ऊपर में वर्णित # 3 के साथ प्रतिस्थापन किया है।

  5. निर्भरता की स्वत: पीढ़ी बहुत उपयोगी है। दिखाए गए अनुसार आपकी परियोजना वास्तव में इसकी आवश्यकता के लिए पर्याप्त नहीं है, लेकिन इसे जोड़ने में काफी आसान है, तो क्यों नहीं। आपको कुछ चीजें करने की आवश्यकता होगी। सबसे पहले, उचित निर्भरता फ़ाइल नाम मिलता है:

    DEPFILES = $(addprefix $(OBJ)/,$(SOURCES:.m=.d)) 
    

    फिर उन्हें -MMD झंडा जोड़कर उत्पन्न करने के लिए संकलक मिलती है:

    gcc -MMD -c $< -o [email protected] 
    

    अन्त में, अपने makefile में उन्हें शामिल करता है, तो वे उपलब्ध हैं द्वारा अपने makefile के अंत में एक पंक्ति जोड़कर:

    -include $(DEPFILES) 
    
+0

तो मूल रूप से 'बिल्ड' को 'बिल्ड /' में ऑब्जेक्ट फ़ाइलों को बनाने के कारण बनाया गया था जिससे इसे पुन: संकलित करने और मजबूर करने के लिए मजबूर किया गया था? – varesa

+0

उस तरह से लगता है। यह मेरी मशीन पर नहीं होता है, लेकिन मुझे लगता है कि व्यवहार फाइल सिस्टम-निर्भर हो सकता है। –

+0

या यह माउंट पैरामीटर के साथ कुछ भी करने के लिए हो सकता है, मुख्य रूप से इसे बताते समय इसे टाइमस्टैम्प अपडेट करना चाहिए। – varesa