2009-09-02 13 views
9

मेरे पास जीएनयू मेक का उपयोग कर सी ++ छोटी परियोजना है। मैं निम्नलिखित स्रोत फ़ाइलों चालू करने के लिए सक्षम होने के लिए करना चाहते हैं: निम्न उत्पादन संरचना मेंजीएनयू के साथ फ्लैट ऑब्जेक्ट फ़ाइल निर्देशिका संरचना आउटपुट

src/ 
    a.cpp 
    b/ 
    b.cpp 
    c/ 
    c.cpp 

(मैं इस बिंदु पर डुप्लिकेट के बारे में चिंतित नहीं हूँ): अब तक मेरे पास है

build/ 
    a.o 
    b.o 
    c.o 

निम्नलिखित, जो दुर्भाग्य से ओ डालता है और सही प्रत्येक सीपीपी के बगल में .d:

OBJS   :=  $(foreach file,$(SRCS),$(file).o) 
DEPS   :=  $(patsubst %.o,%.d,$(OBJS)) 
sinclude $(DEPS) 

$(OBJS) : %.o : %.cpp 
     @echo Compiling $< 
     $(CC) $(CC_FLAGS) $(INCS) -MMD -o [email protected] $< 

मैं $ (notdir ...) समारोह के बारे में पता है, लेकिन इस बिंदु पर मेरे प्रयासों इसका इस्तेमाल करने के वस्तुओं को फ़िल्टर करने में विफल रहा है। क्या कोई इस पर रोशनी डाल सकता है? ऐसा करने के लिए काफी उचित बात लगता है।

उत्तर

8

कम से कम दो तरीके आप कर सकते हैं। पहला (और मैं क्या अनुशंसा करता हूं) क्या आप लक्ष्य नामों में निर्माण निर्देशिका जोड़ सकते हैं (यहां तक ​​कि पैटर्न नियम का उपयोग करते समय भी)। उदाहरण के लिए:

$(OBJS) : build/%.o : %.cpp 

दूसरे, आप VPATH चर का उपयोग आवश्यक शर्तें के लिए एक अलग निर्देशिका खोज करने के लिए बनाने के बताने के लिए कर सकते हैं। यह शायद अधिक सामान्य (अधिक) उपयोग दृष्टिकोण है। इसमें कम से कम एक गंभीर कमी है, और यदि आप इसके साथ जाते हैं, और बाद में "डुप्लिकेट" के साथ समस्याओं में भाग लेते हैं, तो समस्या को हल करने का कोई तरीका नहीं है। पूर्व दृष्टिकोण के साथ, आप डुप्लिकेट टकराव से बचने के लिए बिल्ड निर्देशिका के नीचे स्रोत निर्देशिका संरचना को हमेशा दर्पण कर सकते हैं।

संपादित करें: मेरा पिछला उत्तर विस्तार से थोड़ा छोटा था, इसलिए मैं यह दिखाने के लिए विस्तार करूँगा कि यह वास्तव में विज्ञापन के रूप में काम करता है। यहां एक पूर्ण कार्य उदाहरण मेकफ़ाइल है जो समस्या को हल करने के लिए ऊपर वर्णित पहली तकनीक का उपयोग करता है। बस इसे मेकफ़ाइल में पेस्ट करें और रन करें - यह बाकी करेगा और दिखाएगा कि यह वास्तव में काम करता है।

संपादित करें: मैं यह नहीं समझ सकता कि मेरे उत्तर टेक्स्ट में टैब वर्णों को अनुमति देने के लिए एसओ कैसे प्राप्त करें (यह उन्हें रिक्त स्थान के साथ बदल दिया गया है)। इस उदाहरण की प्रतिलिपि बनाने और चिपकाने के बाद, आपको कमांड स्क्रिप्ट में टैब में प्रमुख रिक्त स्थान को कन्वर्ट करने की आवश्यकता होगी।

BUILD_DIR := build 

SRCS := \ 
    a.c \ 
    b.c \ 
    c.c \ 
    a/a.c \ 
    b/b.c \ 
    c/c.c 

OBJS := ${SRCS:%.c=${BUILD_DIR}/%.o} 

foo: ${OBJS} 
    @echo Linking [email protected] using $? 
    @touch [email protected] 

${BUILD_DIR}/%.o: %.c 
    @mkdir -p $(dir [email protected]) 
    @echo Compiling $< ... 
    @touch [email protected] 

${SRCS}: 
    @echo Creating [email protected] 
    @mkdir -p $(dir [email protected]) 
    @touch [email protected] 

.PHONY: clean 
clean: 
    rm -f foo 
    rm -f ${OBJS} 

विशेष रूप से, ध्यान दें नकली नाम (a.c और एक/a.c, ई.पू. और बी/ई.पू., आदि) के साथ स्रोत फ़ाइलें देखते हैं कि और यह किसी भी समस्याओं का कारण नहीं है कि। यह भी ध्यान दें कि वीपीएटीएच का कोई उपयोग नहीं है, जिसे मैं अपनी अंतर्निहित सीमाओं के कारण उपयोग करने से बचने की सलाह देता हूं।

+0

ठीक है, इस दृष्टिकोण का उपयोग करके मुझे आउटपुट फ़ोल्डर में उप-फ़ोल्डर बनाने के लिए शायद एक अतिरिक्त नियम की आवश्यकता होगी? – Justicle

+0

मैं इस मार्ग पर जा रहा हूं - क्योंकि मुझे लक्ष्य और कॉन्फ़िगरेशन विशिष्ट बिल्ड फ़ोल्डरों को वैसे भी बनाना है, फिर भी "बिल्डफोल्डर" चरण में कुछ और फ़ोल्डरों को जोड़ना आसान था। धन्यवाद! – Justicle

+0

बिल्ड फ़ोल्डर्स के लिए एक अलग नियम ठीक काम करना चाहिए। मैं आमतौर पर जो करता हूं, ऑब्जेक्ट फ़ाइल बनाने के हिस्से के रूप में आउटपुट निर्देशिका (यदि यह पहले से मौजूद नहीं है) बनाने के लिए कमांड स्क्रिप्ट को "@mkdir -p $ (dir $ @)" पंक्ति जोड़ता है (रों)। –

2
vpath %.cpp src src/b src/c 

फिर स्रोत निर्देशिका को उनके निर्देशिका नाम के बिना देखें; vpath खोज लेंगे।

1

आरंभ में अनुरोध के रूप में फ्लैट निर्देशिका संरचना बनाना।

स्रोत फ़ाइलों को ट्रैक करने के लिए vpath का उपयोग करता है, लेकिन सभी बुकिपींग SRC सूची से स्वचालित रूप से किया जाता है।

SRC = a/a.c a/aa.c b/b.c 
TARGET = done 

FILES = $(notdir $(SRC)) 
#make list of source paths, sort also removes duplicates 
PATHS = $(sort $(dir $(SRC))) 

BUILD_DIR = build 
OBJ = $(addprefix $(BUILD_DIR)/, $(FILES:.c=.o)) 
DEP = $(OBJ:.o=.d) 

# default target before includes 
all: $(TARGET) 

include $(DEP) 

vpath %.c $(PATHS) 

# create dummy dependency files to bootstrap the process 
%.d: 
    echo a=1 >[email protected] 

$(BUILD_DIR)/%.o:%.c 
    echo [email protected]: $< > $(patsubst %.o,%.d,[email protected]) 
    echo $< >[email protected] 

$(TARGET): $(OBJ) 
    echo $^ > [email protected] 

.PHONY: clean 
clean: 
    del $(BUILD_DIR)/*.o 
    del $(BUILD_DIR)/*.d 

बदसूरत echo के बारे में क्षमा करें, लेकिन मैं केवल उस पर परीक्षण करने के लिए मेरी जीत बॉक्स था।

0

आप इस दृष्टिकोण की तरह खासकर न हों, लेकिन:

AUTOMAKE_OPTIONS = 

एक Makefile.am में काफी अच्छी तरह से काम कर देता है। बस कहना है कि आपको हाथ से सब कुछ लिखने की जरूरत नहीं है।

1

यह Win32 mingw32-make के लिए है। यह कार्य करता है। सबसे महत्वपूर्ण हिस्सा

-mkdir $(patsubst %/,%,$(dir [email protected]))

Win32 के लिए

है। हमें ट्रेलिंग/Win32 के लिए स्ट्रिप करने की आवश्यकता है।

GENERATED_DIRS = a b 

# Dependency generator function 
mkdir_deps =$(foreach dir,$(GENERATED_DIRS),$(dir)/.mkdir.done) 

# Target rule to create the generated dependency. 
# And create the .mkdir.done file for stop continuous recreate the dir 
%/.mkdir.done: # target rule 
    -mkdir $(patsubst %/,%,$(dir [email protected])) 
    echo $(patsubst %/,%,$(dir [email protected])) >[email protected] 

all: $(mkdir_deps) 
    @echo Begin 

clean: 
    @echo Cleaning