2013-07-27 88 views
0

我有一個目前效果很好的Makefile。雖然隨着它開始增長,每次重新編譯所有來源開始花費太長時間。下面是從工作版本的代碼段:Makefile - 文件夾中的依賴文件「沒有這樣的文件或目錄」

CC=$(CROSS_COMPILE)g++ 
CFLAGS=-Wall -I./include -pg -O2 
VPATH=./src:./include 

all: dotgazer.cpp dotgazer/Dot.cpp 
    $(CC) $(CFLAGS) $^ -o dotgazer.out `pkg-config --libs opencv` 

有很多更依賴,但是這兩個都足以說明是什麼問題。我正試圖將每個cpp文件的編譯階段移至單獨的目標。當涉及到頂級文件(dotgazer.cpp)這不是一個問題,一般規則%.o: %.cpp工作正常。但是我無法獲得第二個依賴。下面是它現在的樣子:

CC=$(CROSS_COMPILE)g++ 
CFLAGS=-Wall -I./include -pg -O2 
VPATH=./src:./include 

all: dotgazer.o dotgazer/Dot.o 
    $(CC) $(CFLAGS) $^ -o dotgazer.out `pkg-config --libs opencv` 

%.o: %.cpp 
    $(CC) -c $(CFLAGS) $^ -o [email protected] 

dotgazer/Dot.o: dotgazer/Dot.cpp 
    $(CC) -c $(CFLAGS) $^ -o [email protected] 

我已經試過Dot.o規則的不同變化,但他們都不似乎工作。我得到的錯誤是:

Fatal error: can't create dotgazer/Dot.o: No such file or directory 

我應該怎麼做?我最希望將.o文件放在與其來源相同的文件夾中。此外,我會感謝一般規則(如%.o: %.cpp),因爲有很多源文件,我不希望Makefile過於臃腫。謝謝!

+0

我可能是啞巴,但不是'%的.o:%.cpp'和'dotgazer/Dot.o:dotgazer/Dot.cpp'規則增加了一倍?比如,是不是前者已經處理了後者的目標? –

+0

@AdamGoodwin我認爲它會以這種方式工作(只需要'%.o:%.cpp'規則)。但事實證明 - 不。所以我特別爲第二個依賴添加了第二條規則,但它仍然無效。只用'%.o:%.cpp'規則的消息是一樣的:'不能創建dotgazer/Dot.o:沒有這樣的文件或目錄' – Wojtek

+0

嗯,我只是試過你的makefile,它對我來說工作得很好。它甚至可以只用'%.o'目標,也不需要'dotgazer/Dot.o'目標。你有沒有犯過錯誤的文件名或目錄有嗎?或者你是否在做一些像從自己的目錄以外的地方運行makefile? –

回答

1

我認爲你的Makefile是有點特定,因此容易出錯。我建議看看我的下面的例子,它比你的更通用。

我的例子利用了make對隱式規則的嘲弄。對於cpp-文件已經存在通用隱式規則。那麼爲什麼要不要使用它!?

參考手冊描述爲如下:

編譯的C++程序

n.o從n.cc,n.cpp,或N.C自動進行與表單$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c的配方。

所以,如果你有%.o文件作爲先決條件像在規則dotgazer.out: $(OBJS)make適用隱含規則對所有這些自動文件上面。假定您已爲CXX,CPPFLAGS和/或CXXFLAGS設置了有效值。

此外,您通常不需要手動添加源到變量。大多數情況下,項目目錄樹中的所有源都需要構建可執行文件。如果不是這種情況,你應該考慮建立一個反映這種情況的適當的樹。

由於find負責將來源指定給CPPFILES,所以我們不需要設置VPATH。由於我們使用了findpatsubst,我們在我們的Makefile中只有一個明確的文件名。這使得有大量不同來源的實際項目更加流暢。

當然,您不需要allclean規則。我只是爲了方便而添加了這些。

CXX=$(CROSS_COMPILE)g++ 
CPPFLAGS=-I./include 
CXXFLAGS=-Wall -pg -O2 
LDLIBS=`pkg-config --libs opencv` 

CPPFILES=$(shell find . -name "*.cpp") 
OBJS=$(patsubst %.cpp, %.o, $(CPPFILES)) 

all: dotgazer.out 
    @echo $(CPPFILES) 
    @echo $(OBJS) 

dotgazer.out: $(OBJS) 
    $(CXX) $(CXXFLAGS) -o [email protected] $^ $(LDLIBS) 

clean: 
    rm -f $(OBJS) 
+0

真棒回答,謝謝!它具有我需要的所有內容,所有文件都是單獨編譯的,'.o'文件位於各自的文件夾中。雖然有一個問題,儘管有'LDLIBS'設置,OpenCV函數仍然無法識別。以下是輸出:http://pastebin.com/zV9btgqN'dotgazer.out'規則應該如下所示:'$(CXX)$^-o $ @ $(LDLIBS)'。但是,這仍然是一個很好的答案! – Wojtek

+0

你說得對,我應該把'$(CXX)$(LDLIBS)$^-o $ @'改成'$(CXX)$(LDLIBS)-o $ @ $ ^'。 'g ++ --help' sais輸入文件應該在選項之後。此致敬意 – user1146332

+0

這不是問題所在。 '-o'可以隨時來。問題是圖書館_必須最後(和圖書館列出的順序也很重要)。另外'CPPFLAGS'用於C預處理器標誌('-I' /'-D');像'-Wall -pg -O2'這樣的編譯器標誌屬於'CXXFLAGS'(用於C++)。要鏈接,請使用'$(CXX)$(CXXFLAGS)$(LDFLAGS)-o $ @ $^$(LDLIBS)' – MadScientist

相關問題