2011-05-18 35 views
8

我知道已經有類似的標題,但沒有幾個問題似乎提供了一個答案,我需要什麼(糾正我,如果我錯了)。編譯多個**在GNU改變**源文件一次讓

考慮這個Makefile:

SOURCES=file1.cpp file2.cpp file3.cpp 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=myprog 

all: $(SOURCES) $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS) 
    $(CXX) -o [email protected] $(OBJECTS) 

file1.o: file1.cpp file1.h 
file2.o: file2.cpp file2.h file1.h 
file3.o: file3.cpp 

.cpp.o: 
    $(CXX) $(CXXFLAGS) -c -o [email protected] $< 

如果我改變file1.h,以下運行:

g++ -c -o file1.o file1.cpp 
g++ -c -o file2.o file2.cpp 
g++ -o myprog file1.o file2.o file3.o 

我想擁有的是:

g++ -c file1.cpp file2.cpp 
g++ -o myprog file1.o file2.o file3.o 

(我知道我不能用GCC指定對象輸出目錄,但是我可以忍受;應該可以解決一些問題cd命令。)

在nmake中,這是通過雙冒號推理規則(所謂的「batch-mode rule"」)完成的。基本上,它爲多個目標分組推理規則(例如「.obj.cpp:」),併爲所有依賴項調用編譯器,而不是每個文件一次。 $<變量獲取依賴關係列表,而不是第一個。

現在我們正在使用並行建設(使-j),但它有自己的問題,和VC++編譯器工作在一個調用模式更好,所以我寧願使用。

+2

爲什麼你的'all'目標取決於你的'$(SOURCES)'?這是不需要的,因爲你的'$(OBJECTS)'已經依賴於它們了。 – 2011-05-18 15:50:59

+1

這只是我找到的一個例子。在我們的makefile中(它們非常複雜),我們只依賴最終的可執行文件。無論如何,這不是問題所在。 – 2011-05-18 15:53:45

+2

gcc包裝只是多次調用cc1,gas等。您將保存的唯一程序調用是gcc包裝器本身。 – 2011-05-18 18:42:03

回答

1

我不明白你爲什麼要這樣的效果,但在這裏是如何得到它(在gnumake的):

SOURCES=file1.cpp file2.cpp file3.cpp 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=myprog 

all: $(EXECUTABLE) 

$(EXECUTABLE): $(SOURCES) 
    $(CXX) $(CXXFLAGS) -c $? 
    $(CXX) -o [email protected] $(OBJECTS) 

編輯:
我很驚訝的是解決方案的工作 - 有我對Make的做法有什麼不妥 - 但我不認爲它適用於你的情況,有頭文件依賴性,沒有下面的kludge。 (有一個或兩個其他可能的工作方法,如果不挑鍋。)

SOURCES=file1.cpp file2.cpp file3.cpp 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=myprog 

all: $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS) 
    $(CXX) -o [email protected] $(OBJECTS) 

file1.cpp: file1.h 
file2.cpp: file2.h file1.h 

$(SOURCES): 
    @touch [email protected] 

$(OBJECTS): $(SOURCES) 
    $(CXX) $(CXXFLAGS) -c $? 
    @touch $(OBJECTS) 
+0

謝謝,這是一種可能性。然而,有了這個,我不得不按照相同的規則進行編譯和鏈接。我能以某種方式保持鏈接和編譯分離嗎? – 2011-05-18 17:10:53

+0

這個解決方案的一個問題是它不跟蹤個別文件(我們已經聲明)的依賴關係。所以例如更改標題不會觸發重新編譯。我發現了一個幾乎可以在[這裏]工作的解決方案(http://lists.gnu.org/archive/html/help-make/2001-03/msg00064.html),但它需要將所有依賴關係從.obj更改爲。 CPP。嗯... – 2011-05-18 18:17:48

1

您可以gnumake的做你想做的通過收集這些文件是在生成規則實際上是重建,然後當你連接時建立它們:

SOURCES=file1.cpp file2.cpp file3.cpp 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=myprog 

all: $(EXECUTABLE) 

.PHONY: build_list 

build_list: 
     -rm -f build_list 

$(OBJECTS): %.o: %.cpp | build_list 
     echo $< >> build_list 

$(EXECUTABLE): build_list $(OBJECTS) 
     if [ -r build_list ]; then $(CXX) $(CXXFLAGS) -c `cat build_list`; fi 
     $(CXX) -o [email protected] $(OBJECTS) 

file1.o: file1.h 
file2.o: file2.h file1.h 
+0

這看起來很有趣,我們會看看是否有效。雖然我不知道你是否可以使用make變量而不是列表文件。 – 2011-05-19 00:01:00