makefile之目錄搜索&自動依賴

目錄搜索

在一個大工程中,通常會將源文件和中間生成文件放在不一樣的目錄,並且不會污染源碼所在的目錄。當須要編譯不一樣目錄下的源文件時,就須要指定路徑,那麼怎樣讓路徑的表示以及源文件的引用更加靈活。就要用到目錄搜索功能。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

源碼路徑

相關文章
相關標籤/搜索