2011-03-03 10 views
40

में ऑब्जेक्ट फ़ाइलों को कैसे स्थानांतरित करें मुझे ऑब्जेक्ट फ़ाइलों को एक अलग उपनिर्देशिका में रखने के लिए उपयोग करने का प्रयास करने में समस्या हो रही है, शायद एक बहुत ही बुनियादी तकनीक। मैं इस पृष्ठ में जानकारी का उपयोग करने की कोशिश की है: http://www.gnu.org/software/hello/manual/make/Prerequisite-Types.html#Prerequisite-Typesअलग-अलग उपनिर्देशिका

मैं मेकअप से निम्न आउटपुट प्राप्त: मेकअप: *** कोई नियम लक्ष्य ku.h', needed by obj/kumain.o बनाने के लिए '। रूक जा।

हालांकि ku.h एक निर्भरता लक्ष्य नहीं है (हालांकि यह स्पष्ट रूप से # स्रोत फ़ाइलों के भीतर शामिल है)। जब मैं ऑब्जेक्ट फ़ाइलों के लिए उपनिर्देशिका का उपयोग करने की कोशिश नहीं करता (यानी ओबीजेडीआईआर भागों को याद करता हूं) यह ठीक काम करता है। क्यों सोचते हैं ku.h एक लक्ष्य है?

मेरी makefile यह है: (शैली जानकारी के विभिन्न स्रोतों को पढ़ने के बाद है)

.SUFFIXES: 
.SUFFIXES: .c .o 

CC=gcc 
CPPFLAGS=-Wall 
LDLIBS=-lhpdf 
VPATH=%.c src 
VPATH=%.h src 
VPATH=%.o obj 
OBJDIR=obj 

objects= $(addprefix $(OBJDIR)/, kumain.o kudlx.o kusolvesk.o kugetpuz.o kuutils.o \ 
    kurand.o kuASCboard.o kuPDFs.o kupuzstrings.o kugensud.o \ 
    kushapes.o) 

ku : $(objects) 
    $(CC) $(CPPFLAGS) -o ku $(objects) $(LDLIBS) 

$(objects) : ku.h kudefines.h kuglobals.h kufns.h | $(OBJDIR) 

$(OBJDIR): 
    mkdir $(OBJDIR) 

.PHONY: clean 
clean : 
    rm $(objects) 

संपादित करें: मैं vpath निर्देश उपयोग करने के लिए परिवर्तन लागू कर दिया। मेरा संस्करण VPATH = xxx और vpath% .c xxx का खराब मिश्रण था। हालांकि अब मुझे एक और समस्या है (जो मैंने गलत vpath जोड़ने से पहले मूल समस्या थी)। यह अब उत्पादन होता है:

gcc -o ku -lhpdf obj/kumain.o obj/kudlx.o obj/kusolvesk.o ..etc 
    gcc: obj/kumain.o: No such file or directory 
    gcc: obj/kudlx.o: No such file or directory 
    gcc: obj/kusolvesk.o: No such file or directory 
    gcc: obj/kugetpuz.o: No such file or directory 
    gcc: obj/kuutils.o: No such file or directory 
    gcc: obj/kurand.o: No such file or directory 
    gcc: obj/kuASCboard.o: No such file or directory 
    gcc: obj/kuPDFs.o: No such file or directory 
    gcc: obj/kupuzstrings.o: No such file or directory 
    gcc: obj/kugensud.o: No such file or directory 
    gcc: obj/kushapes.o: No such file or directory 
    make: *** [ku] Error 1 

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

फिर से "उदाहरण के लिए, जब फ़ाइल foo.o के पास कोई स्पष्ट नियम नहीं है, तो अंतर्निहित नियमों को समझें, जैसे अंतर्निहित नियम foo.c को संकलित करने के लिए। अगर वह फ़ाइल मौजूद है। अगर ऐसी फ़ाइल में कमी है वर्तमान निर्देशिका, उचित निर्देशिकाओं के लिए खोज की जाती है। यदि किसी भी निर्देशिका में foo.c मौजूद है (या मेकफ़ाइल में उल्लिखित है), सी संकलन के लिए निहित नियम लागू किया गया है। "

मेरे मेकफ़ाइल के लिए काम करने के लिए निहित नियम प्राप्त करने में कोई सहायता की सराहना की जाएगी।

संपादित करें 2: जैक केली के लिए धन्यवाद मैंने .c फ़ाइलों को संकलित करने के लिए एक स्पष्ट नियम बना दिया है क्योंकि मैं कहीं भी निहित नियमों का उपयोग करने की कोशिश नहीं कर सका। Vpath जानकारी के लिए al_miro भी धन्यवाद।

.SUFFIXES: 
.SUFFIXES: .c .o 

CC=gcc 
CPPFLAGS=-Wall 
LDLIBS=-lhpdf 
OBJDIR=obj 
vpath %.c src 
vpath %.h src 

objects = $(addprefix $(OBJDIR)/, kumain.o kudlx.o kusolvesk.o kugetpuz.o kuutils.o \ 
    kurand.o kuASCboard.o kuPDFs.o kupuzstrings.o kugensud.o \ 
    kushapes.o) 

ku : $(objects) 
    $(CC) $(CPPFLAGS) -o ku $(objects) $(LDLIBS) 

$(OBJDIR) obj/%.o : %.c ku.h kudefines.h kuglobals.h kufns.h 
    $(CC) -c $(CPPFLAGS) $< -o [email protected] 

.PHONY : clean 
clean : 
    rm $(objects) 
+14

शैली ध्यान दें: '$ (CPPFLAGS)' परंपरागत रूप से, सी पूर्वप्रक्रमक झंडे के लिए इस्तेमाल किया जाता है, जबकि '$ (CFLAGS)' के लिए प्रयोग किया जाता है कंपाइलर के लिए झंडे। –

उत्तर

51

आप GNUmake उपयोग कर रहे हैं के बाद से, वस्तु फ़ाइलों के संकलन के लिए एक पैटर्न नियम का उपयोग:

$(OBJDIR)/%.o: %.c 
    $(CC) $(CFLAGS) $(CPPFLAGS) -c -o [email protected] $< 
+4

यह मेरे लिए काम नहीं करता है: यह $ (ओबीजेडीआईआर) /% सी और%% नहीं दिखता है। लक्ष्य के रूप में $ (OBJDIR) का उपयोग करते समय निर्भरता के रूप में वर्तमान निर्देशिका में सी फ़ाइलों का उपयोग करने के लिए मैं इसे कैसे प्राप्त कर सकता हूं? – Lelanthran

+0

@Lelanthran, सी फाइलें प्राप्त करने के समाधान के ऊपर वर्तमान निर्देशिका में है। यदि आप "% .c" के बजाय "$ (OBJDIR) /%। C" का उपयोग करते हैं, तो आपके सी कोड को इसे "$ (OBJDIR)" में रखना चाहिए। – Neal

22

VPATH लाइनों गलत हैं, वे

vpath %.c src 
vpath %.h src 

अर्थात नहीं राजधानी होना चाहिए और = बिना:

यहाँ काम कर makfile है। जैसा कि अब है, यह .h फ़ाइल नहीं ढूंढता है और सोचता है कि यह एक लक्ष्य है।

4

सामान्य तौर पर, आप या तो सभी नियमों की बाएं हाथ की ओर $(OBJDIR) निर्दिष्ट करने के लिए है कि $(OBJDIR) में जगह फ़ाइलें , या आप $(OBJDIR) से बना सकते हैं। VPATH स्रोतों के लिए है, वस्तुओं के लिए नहीं।

अधिक स्पष्टीकरण के लिए इन दो लिंक पर एक नज़र डालें, और एक "चालाक" कामकाज।

+1

दरअसल, यह सबसे अच्छा जवाब है। मजेदार कैसे यह शून्य अपवॉट (मेरे पहले) था, जबकि सभी हताश, अपूर्ण, टूटे आदि प्रयासों में यह सब है ...;) धन्यवाद, थियो बी, मेरे लिए कुछ घंटे बचाया! –

2

निम्नलिखित समाधान के रूप में मैं वास्तव में बिल्ट-इन नियमों से प्यार है, मेरी राय में अच्छा नहीं है। हालांकि, जीएनयू आउटपुट निर्देशिकाओं के लिए vpath जैसे कुछ का समर्थन नहीं करता है। और बिल्ट-इन नियमों से मेल नहीं कर सकते हैं के रूप में %.o में %obj/foo.o की obj/foo से मेल खाएंगे, src/obj/foo.c की तरह सामान के लिए vpath %.c src/ में एक खोज के साथ make छोड़ रहा है, लेकिन नहीं src/foo.c

लेकिन यह आपके द्वारा प्राप्त किए जा सकने वाले अंतर्निहित नियमों के करीब है, और इसलिए मेरे सर्वोत्तम ज्ञान के लिए उपलब्ध सबसे अच्छा समाधान है।

$(OBJDIR)/%.o: %.c 
     $(COMPILE.c) $(OUTPUT_OPTION) $< 

स्पष्टीकरण: $(COMPILE.c) $(OUTPUT_OPTION) $< वास्तव में, कैसे .c.o कार्यान्वित किया जाता है, http://git.savannah.gnu.org/cgit/make.git/tree/default.c देखते हैं (और यह और भी मैनुअल में उल्लेख किया गया है)

इसके अलावा अगर $(OBJDIR) ही कभी ऑटो gererated फ़ाइलें हो जाएगा है आप उस पर बना सकते हैं एक आदेश-केवल शर्त के साथ -इस मक्खी, स्वच्छ शासन कर रही है थोड़ा सरल:

$(OBJDIR): 
     mkdir -p $(OBJDIR) 

$(OBJDIR)/%.o: %.c | $(OBJDIR) 
     $(COMPILE.c) $(OUTPUT_OPTION) $< 

.PHONY: clean 
clean: 
     $(RM) -r $(OBJDIR) 

यह जरूरी है कि सुविधा आदेश केवल उपलब्ध है, जिसे आप $(filter order-only, $(.FETAURES)) का उपयोग करके जांच सकते हैं। मैंने कुबंटू 14.04 जीएनयू पर 3.81 और ओपनएसयूएसई 13.1 जीएनयू को 3.82 बना दिया है। दोनों को ऑर्डर-केवल सक्षम बनाया गया था, और अब यह पता चला है कि क्यों Kubuntu 14.04 OpenSUSE 13.1 की तुलना में जीएनयू बनाने के पुराने संस्करण के साथ आता है। वैसे भी, वाला डाउनलोड अब 4.1 बनाने :)

32

यह makefile कि मैं अपनी परियोजनाओं के अधिकांश के लिए उपयोग करते हैं,

यह स्रोत फ़ाइलें, हेडर और सबफ़ोल्डर में इनलाइन फ़ाइलें, और सबफ़ोल्डर और तथाकथित के सबफ़ोल्डर डाल परमिट है आगे, और स्वचालित रूप से प्रत्येक ऑब्जेक्ट के लिए एक निर्भरता फ़ाइल उत्पन्न करेगा इसका मतलब है कि हेडर और इनलाइन फ़ाइलों का संशोधन उन फ़ाइलों के पुनर्मूल्यांकन को ट्रिगर करेगा जो निर्भर हैं।

स्रोत फ़ाइलों को शेल खोज कमांड के माध्यम से पता चला है, इसलिए स्पष्ट रूप से निर्दिष्ट करने की कोई आवश्यकता नहीं है, बस अपने दिल की सामग्री पर कोडिंग रखें।

यह प्रोजेक्ट संकलित होने पर बिन फ़ोल्डर में सभी फ़ाइलों को 'संसाधन' फ़ोल्डर से कॉपी करेगा, जो मुझे अधिकतर समय में आसान लगता है।

क्रेडिट प्रदान करने के लिए जहां यह देय है, ऑटो-निर्भरता सुविधा काफी हद तक स्कॉट मैकपीक के पृष्ठ पर आधारित थी जो HERE पाया जा सकता है, मेरी आवश्यकताओं के लिए कुछ अतिरिक्त संशोधन/tweaks के साथ।

उदाहरण Makefile

#Compiler and Linker 
CC   := g++-mp-4.7 

#The Target Binary Program 
TARGET  := program 

#The Directories, Source, Includes, Objects, Binary and Resources 
SRCDIR  := src 
INCDIR  := inc 
BUILDDIR := obj 
TARGETDIR := bin 
RESDIR  := res 
SRCEXT  := cpp 
DEPEXT  := d 
OBJEXT  := o 

#Flags, Libraries and Includes 
CFLAGS  := -fopenmp -Wall -O3 -g 
LIB   := -fopenmp -lm -larmadillo 
INC   := -I$(INCDIR) -I/usr/local/include 
INCDEP  := -I$(INCDIR) 

#--------------------------------------------------------------------------------- 
#DO NOT EDIT BELOW THIS LINE 
#--------------------------------------------------------------------------------- 
SOURCES  := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) 
OBJECTS  := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT))) 

#Defauilt Make 
all: resources $(TARGET) 

#Remake 
remake: cleaner all 

#Copy Resources from Resources Directory to Target Directory 
resources: directories 
    @cp $(RESDIR)/* $(TARGETDIR)/ 

#Make the Directories 
directories: 
    @mkdir -p $(TARGETDIR) 
    @mkdir -p $(BUILDDIR) 

#Clean only Objecst 
clean: 
    @$(RM) -rf $(BUILDDIR) 

#Full Clean, Objects and Binaries 
cleaner: clean 
    @$(RM) -rf $(TARGETDIR) 

#Pull in dependency info for *existing* .o files 
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) 

#Link 
$(TARGET): $(OBJECTS) 
    $(CC) -o $(TARGETDIR)/$(TARGET) $^ $(LIB) 

#Compile 
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) 
    @mkdir -p $(dir [email protected]) 
    $(CC) $(CFLAGS) $(INC) -c -o [email protected] $< 
    @$(CC) $(CFLAGS) $(INCDEP) -MM $(SRCDIR)/$*.$(SRCEXT) > $(BUILDDIR)/$*.$(DEPEXT) 
    @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp 
    @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) 
    @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) 
    @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp 

#Non-File Targets 
.PHONY: all remake clean cleaner resources 
+0

'एमपी' का मतलब मैकपॉर्ट्स है। जी ++ - एमपी -4.7 मैकपॉर्ट्स के लिए जीसीसी से सी ++ कंपाइलर है –

1

सभी निहित नियम (और GNU बनाने) के साथ काम कर रहे लोगों के लिए। यहाँ एक सरल makefile जो अलग निर्देशिका का समर्थन करता है:

#Start of the makefile 

VPATH = ./src:./header:./objects 

OUTPUT_OPTION = -o objects/[email protected] 

CXXFLAGS += -Wall -g -I./header 

Target = $(notdir $(CURDIR)).exe 

Objects := $(notdir $(patsubst %.cpp,%.o,$(wildcard src/*.cpp))) 



all: $(Target) 

$(Target): $(Objects) 
    $(CXX) $(CXXFLAGS) -o $(Target) $(addprefix objects/,$(Objects)) 


#Beware of -f. It skips any confirmation/errors (e.g. file does not exist) 

.PHONY: clean 
clean: 
    rm -f $(addprefix objects/,$(Objects)) $(Target) 

चलें करीब से देख (मैं curdir के साथ वर्तमान निर्देशिका का उल्लेख होगा) है:

इस लाइन का इस्तेमाल किया की एक सूची प्राप्त करने के लिए प्रयोग किया जाता है। ओ फाइलें जो curdir/src में हैं।

Objects := $(notdir $(patsubst %.cpp,%.o,$(wildcard src/*.cpp))) 
#expands to "foo.o myfoo.o otherfoo.o" 

आउटपुट के माध्यम से आउटपुट एक अलग निर्देशिका (curdir/ऑब्जेक्ट्स) पर सेट है।

OUTPUT_OPTION = -o objects/[email protected] 
#OUTPUT_OPTION will insert the -o flag into the implicit rules 

संकलक पाता नई वस्तुओं फ़ोल्डर में वस्तुओं, पथ फ़ाइल नाम में जोड़ा जाता है सुनिश्चित करने के लिए।

$(Target): $(Objects) 
    $(CXX) $(CXXFLAGS) -o $(Target) $(addprefix objects/,$(Objects)) 
#         ^^^^^^^^^^^^^^^^^^^^  

यह एक उदाहरण के रूप में है और वहाँ निश्चित रूप से सुधार की गुंजाइश है।

अतिरिक्त जानकारी के लिए देखें: Make documetation. See chapter 10.2

या: Oracle: Programming Utilities Guide

संबंधित मुद्दे