目錄搜索
在一個大工程中,通常會將源文件和中間生成文件放在不一樣的目錄,並且不會污染源碼所在的目錄。當須要編譯不一樣目錄下的源文件時,就須要指定路徑,那麼怎樣讓路徑的表示以及源文件的引用更加靈活。就要用到目錄搜索功能。git
VPATH
VPATH:指定依賴文件的搜索目錄,當規則的依賴文件在當前目錄不存在時,make會在此變量所指定目錄下去尋找這些依賴文件。github
#VPATH = src all: VPATH.o @echo compile done %.o: %.c gcc -c $< -o $@
源碼路徑url
依賴文件一般你能夠指定全路徑,那麼執行make時能找到依賴文件,就會編譯出對應的目標文件。可是在一個大工程中,源碼的目錄結構複雜,每一個依賴文件都帶上絕對路徑,makefile看起來會很是繁瑣。上面給出的例子中,只有一個依賴文件,或許你能夠這樣寫all: src/VPATH.o, 可是當依賴文件變多,目錄結構變複雜,或者須要更改目錄結構時,makefile文件的改動很大。可是若是使用VPATH指定搜索目錄,那麼只須要關注依賴文件的文件名,而後在VPATH中指定搜索路徑便可。spa
vpath
vpath: make的一個關鍵字,和VPATH的功能相似,都是指定依賴文件的搜索目錄。.net
使用的三種方法:3d
vpath PATTERN DIRECTORIEScode
爲全部符合PATTERN的文件指定搜索目錄DIRECTORIES.多個目錄使用空格或冒號(:)分開blog
vpath PATTERNget
清除以前 符合 PATTERN 的文件設置路徑 源碼
vpath
清除全部的已被設置的文件搜索路徑
#爲.c文件指定搜索目錄 vpath %.c src all: vpath.o @echo compile done %.o: %.c gcc -c $< -o $@
#爲.c文件指定搜索目錄 vpath %.c src #爲.h文件指定搜索目錄 vpath %.h include all: vpath.o @echo compile done %.o: %.c gcc -MD -I include -c $< -o $@ clean: rm *.o *.d
源碼路徑:https://github.com/suonikeyinsuxiao/trunk/tree/master/makefile_project/vpath/vpath/vp2 makefile vpath 中出現的.h文件,僅限於在makefile中有效。對於源文件#include的頭文件仍須要使用-I + directory 指定搜索目錄。
若是上例子中,將 -I include 去掉,那麼make會報「src/vpath.c:2:19: fatal error: vpath.h: No such file or directory」的錯誤。
自動生成依賴關係
-MD 自動生成目標文件的依賴關係,並保存在*.d文件中。
#爲.c文件指定搜索目錄 vpath %.c src #爲.h文件指定搜索目錄 vpath %.h include all: vpath.o @echo compile done %.o: %.c #gcc -MD -c $< -o $@ gcc -MD -I include -c $< -o $@ clean: rm *.o *.d
修改src/vpath.c前,該源文件是#include "vpath.h"的。生成的vpath.d的內容是:vpath.o: src/vpath.c /usr/include/stdc-predef.h include/vpath.h
修改src/vpath.c後,即將源文件中的#include "vpath.h"註釋掉。生成的vpath.d的內容是:vpath.o: src/vpath.c /usr/include/stdc-predef.h
顯然少了 include/vpath.h.那使用-MD有什麼做用呢。
試想,當在源文件中加入或者刪除頭文件時,若是不使用MD自動生成依賴關係,就須要手動的修改makefile中顯示的依賴關係,顯然這是一種低效的方式且容易出錯。
gcc 的 "-MD"選項將自動尋找源文件中include的頭文件,並生成文件的依賴關係,保存在*.d文件中。
incdirs := include include/src2 srcdirs := src src2 #指定源文件列表(由vpath處理路徑問題) srcs := vpath.c src2.c #指定中間文件目錄 objdir := obj #指定目標文件列表 objlist := $(patsubst %.c, $(objdir)/%.o, $(srcs)) #指定gcc頭文件路徑 INCDIR := $(patsubst %, -I%, $(incdirs)) #爲.c文件指定搜索目錄 vpath %.c $(srcdirs) #爲.h文件指定搜索目錄 vpath %.h $(incdirs) .PHONY: all clean objdir: @echo "create obj directory" -mkdir $(objdir) $(objdir)/%.o: %.c gcc -MD $(INCDIR) -c $< -o $@ all: $(objdir) $(objlist) @echo compile done clean: rm $(objdir)/*.o $(objdir)/*.d $(objdir) -rf