2012-10-23 48 views
0

我對GNU makefile有一些有限的認識,目前我的失敗了。Makefile中的依賴關係沒有正確考慮

我有一個類聲明文件:mdfTree.h,類mdfTree.cpp的實現和一個mdfTree_x.cpp文件,其中主要是創建類mdfTree的對象並調用其公用函數,然後依次調用它的公共函數調用一些mdfTree的私有成員變量。

我用的Makefile編譯它:

CXX=g++ 
CXXFLAGS=-g -Wall -W -Wconversion -Wshadow -Wcast-qual -Wwrite-strings $(shell root-config --cflags --gl\ 
ibs) 
LDFLAGS=-g $(shell root-config --ldflags) 
LDLIBS=$(shell root-config --libs) 

mdfTree_x: mdfTree_x.o 
     g++ $(LDFLAGS) -o mdfTree_x mdfTree_x.o $(LDLIBS) 

mdfTree_x.o: mdfTree_x.cpp 
     g++ $(LDFLAGS) $(CXXFLAGS) -c mdfTree_x.cpp 

mdfTree.cpp和mdfTree_x.cpp中有一個#include mdfTree.h。 mdfTree_x.cpp是否也需要#include mdfTree.cpp

我想我的Makefile是錯誤的,因爲當我嘗試編譯時,類mdfTree的公共函數看不到相同類的私有變量。另外,當我在mdfTree.h中插入一個語法錯誤時,編譯器不會將其提取出來。我如何告訴Makefile mdfTree_x需要使用/編譯mdfTree.h/.cpp?

回答

1

你需要明確地添加所有的依賴關係,在這種情況下,你的可執行取決於有mdfTree.o已經建立並且mdfTree.o和mdfTree_x.o依賴於mdfTree.h。你的依賴關係應該像

mdfTree_x:mdfTree_x.o mdfTree.o 
mdfTree.o:mdfTree.cpp mdfTree.h 
mdfTree_x.o:mdfTree_x.cpp mdfTree.h 

一些編譯器(例如GNU &英特爾)能夠自動列出標題依賴關係在化妝格式。例如此生成的文件將重新生成可執行當任何mdfTree_x.cppmdfTree.cppmdfTree.h改變:

# Compiler flags... 
CPPFLAGS+=-MMD -MP 
mdfTree_x:mdfTree_x.o mdfTree.o 
-include mdfTree_x.d mdfTree.d 

的CPPFLAGS將創建報頭的依賴關係一個.D文件進行編譯時,該-include線將嘗試這些包括成如果存在makefile(如果它們不存在,源文件將被重新編譯,所以額外的依賴關係並不重要)。該.D文件的內容會像

mdfTree.o:mdfTree.h 

而且,你不必明確寫入訂立規則在大多數情況下 - 例如,如果你有列爲扶養GNU make的默認規則的文件foo.o要運行

$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o foo.o foo.cpp 

(和其他語言的類似)。類似地,如果可執行名稱與目標文件之一相匹配,鏈接是自動的,例如,

foo:foo.o 

將運行(注意CC不CXX)

$(CC) $(LDFLAGS) -o foo foo.o $(LDLIBS) 

使用默認的規則保持的makefile簡單,而且還可以讓你使用環境變量設置一個默認的編譯器。

+0

謝謝,解決了這個問題。 – mareks

2

不,你需要調整你的文件編譯和鏈接mdfTree.cpp以及。

像這樣的事情

mdfTree.o: mdfTree.cpp 
     g++ $(LDFLAGS) $(CXXFLAGS) -c mdfTree.cpp 

和更改鏈接步驟

mdfTree_x: mdfTree_x.o mdfTree.o 
     g++ $(LDFLAGS) -o mdfTree_x mdfTree_x.o mdfTree.o $(LDLIBS) 
1

我有一個類聲明文件:mdfTree.h,類mdfTree.cpp的實現,和mdfTree_x.cpp與主文件的形式創建類mdfTree的對象,並調用它的公共職能,其依次調用一些mdfTree的私有成員變量。

您的程序需要在mdfTree.cpp和mdfTree_x.cpp中定義的功能。所以你需要編譯這兩個文件,你的鏈接需要包含mdfTree.o和mdfTree_x.o。

您可以編寫兩條規則,一條用於編譯mdfTree.cpp,另一條用於編譯mdfTree_x.cpp。這將很快失去控制。是邪惡的。 建立它們的一條規則,找到它們的一條規則,將它們全部帶到黑暗中的一條規則將它們綁定起來。

objects = mdfTree_x.o mdfTree.o 
$(objects): %.o: %.cpp 
    g++ $(CXXFLAGS) -c $< 

注意,存在上述編譯規則沒有$(LDFLAGS)。編譯時不應指定鏈接選項。

您需要的對象聯繫起來,形成可執行文件:

mdfTree_x: $(objects) 
    g++ $(LDFLAGS) -o [email protected] $^ $(LDLIBS) 

注意,現在你需要指定鏈接選項;你在鏈接。

下一步之前的最後一點:您在makefile中指定規則的順序通常無關緊要。但是,有一個例外。第一條規則是默認規則,如果在make命令中根本沒有指定任何目標,將使用該規則。明確地將默認規則放置在makefile的最頂端是一個好主意。例如,把地方下面靠近你的Makefile頂部,前面的任何其他規則:

default: mdfTree_x 

mdfTree.cpp和mdfTree_x.cpp具有一個#include mdfTree.h在裏面。 mdfTree_x.cpp是否也需要#include mdfTree.cpp?

從不#include源文件。決不。讓鏈接器執行該操作。

然而,這裏還是有些遺漏。假設你改變了mdfTree.h。你需要重建。目前爲止的makefile不會那樣做。缺少的是對mdfTree.h的依賴。在這種情況下,這個依賴問題有一個簡單的解決方案:只需指定依賴關係。

$(objects): mdfTree.h 

一般來說,這個頭依賴問題是一個非常難的問題。最好不要將這些頭文件依賴項放在makefile中。讓一些自動化工具,如makedepend找出你的依賴關係。

+0

謝謝!非常有啓發性。 – mareks