2012-11-24 86 views
1

我想構建一些C++代碼。我已經有了一個可以自動計算依賴關係的魔法Makefile,但我想將目標文件保存在單獨的目錄中。因此,結構是這樣的:通過兩步依賴關係計算了解Makefile

  • 的Makefile
  • 源/一個/
  • 源/ B/
  • 源/ C/
  • OBJ/

我能跑使用obj /前綴將源代碼轉換爲對象的Makefile,但是當我想要反向依賴計算時,事情變得麻煩。

問題是,幾乎所有的Makefile示例都是在一步完成的,從.cpp(%.d: %.cpp)創建.d。我花了一些時間試圖理解Makefile並通過試驗和錯誤來修復它。最後,我已經有了一個工作腳本:

DIRS := a b c 
SOURCES := $(foreach dir,$(DIRS),$(wildcard source/$(dir)/*.cpp)) 
OBJECTS := $(patsubst %.cpp,obj/%.o,$(SOURCES)) 

obj/%.d: %.cpp 
    @mkdir -p $(@D) 
    @$(CXX) -E $(CXXFLAGS) -MM -MP -MF [email protected] -MQ $(@:.d=.o) -MQ [email protected] $< 

obj/%.o: %.cpp obj/%.d 
    @$(CXX) $(CXXFLAGS) -o [email protected] -c $< 

project: $(OBJECTS) 
    ... 

-include $(OBJECTS:.o=.d) 

但我仍然不知道爲什麼我需要有獨立的步驟爲CPP-> d和CPP & d - > O(或者也許我理解 - 但那麼我不知道爲什麼大多數例子不需要這個)。

+0

你不**需要單獨的步驟。你可以合併它們。這是否回答你的問題? – Beta

+0

@Beta:我不明白爲什麼所有的例子都顯示轉換'%.d:%.cpp'。目標二進制文件取決於目標文件(.o),而不是依賴文件,但在Makefile中,目標文件沒有規則,除非存在某些依賴文件。 – Marcin

回答

2

假設的源文件是foo.cppbar.cpp,和集管是foo.hbar.h,使得foo.cpp包括foo.hbar.h,和bar.cpp包括bar.h

你可以有一個簡單的makefile是完全不涉及相關文件:

project: $(OBJECTS) 
    ... 

%.o: %.cpp 
    ... 

現在,如果你修改foo.cpp,請將重建foo.o(和project)。如果修改bar.cpp,Make將重建bar.o(和project)。如果你修改了一個頭文件,Make將不會執行任何操作,因爲Make不知道這些對象以任何方式依賴頭文件。

你可以把一個規則的依賴文件:

project: $(OBJECTS) 
    ... 

%.o: %.cpp 
    ... 

%.d: 
    ... 

-include *.d 

現在做將建立和使用的依賴files--如果你記得告訴它。如果這樣做,Make會知道在修改foo.h時必須重建foo.o,並且在修改bar.h時必須重建foo.obar.o

記住重建依賴文件是一種痛苦。讓Make做它會更好。 foo.d何時必須重建?那麼,當foo.cpp被修改,肯定:

project: $(OBJECTS) 
    ... 

%.o: %.cpp 
    ... 

%.d: %.cpp 
    ... 

-include *.d 

但是foo.d當任何foo.o另一先決條件(即foo.hbar.h)的已被修改,也必須重新生成。我沒有在規則中闡明的命令(我不能讓你%.d規則確定命令的太大意義),但一個簡單的規則將建立一個foo.d,看起來像這樣:

foo.o: foo.cpp foo.h bar.h 

它可以編寫一個命令,將產生一個foo.d,看起來像這樣:

foo.o: foo.cpp foo.h bar.h 

foo.d: foo.cpp foo.h bar.h 

有更復雜的方法,但這是不夠的今天。

至於爲什麼許多示例makefile都共享某種次優功能,這是因爲人們在不嚴格檢查或理解每個功能的情況下複製彼此的生成文件。