從開始學習到瞭解到makefile自動依賴到目前爲止總算是掌握了makefile的自動依賴寫法
因爲接觸的項目代碼分佈的問題源文件和頭文件不在同一個目錄下,,網上很多makefile自動依賴的方案不能直接拿來用.所以是在其基礎上進行的改編
總體來說 是這麼個過程
先決條件 工程目錄結構爲 頂層中放置
1 Makefile
2 src目錄放置源文件
3 inc目錄
4 可能有lib目錄
生成的程序在頂層目錄中
第一步 寫好你的環境變量 一般設置如下參數即可
CC=gcc
CFLAGS=-g -rdynamic -W -Wall
SRC=src
INC=-I. -I./inc
LIB=lib/xxxx.a #如果有
TARGET=demo
第二步 獲取所有參與編譯的源文件
在這步中我所使用的是makefile提供的函數
SOURCES = $(wildcard src/*.cpp)
OBJ=$(patsubst %.cpp, %.o,$(SOURCES))
這樣在SOURCES中獲取到的是所有參加編譯的cpp文件 但是如果有多個目錄放置的話 可以使用追加方式添加其他的目錄下的源文件,最好在做完這一步之後進行驗證
兩個函數的用途分別是 獲取匹配的文件列表 和對匹配的字符串進行替換 將.cpp替換成.o,具體的詳細內容可以百度,不贅述
第三步 寫下如下語句
ALL: $(TARGET)
$(TARGET):$(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJ) $(LIB)
很明顯是申明要生成的文件 爲TARGET也就是demo
第四步 設置自動依賴關係
%d:%cpp
@$(CC) -MM $(CFLAGS) $< $(INC) > [email protected];
@sed -i 's,\($(*F)\)o[ :]*,$(*D)/\1o: ,g' [email protected] ;
@sed 's,\($*\)o[ :]*,\1o $@ : ,g' < [email protected] > $@;
@echo "\t$(CC) -c -o $*o $< $(INC)" >>$@;
@$(RM) [email protected]
-include $(patsubst %.cpp, %.d,$(SOURCES))
這個地方有幾個位置需要注意 第一點也就是最重要的一點
就是%d:%cpp 是沒有.
%d:%cpp 是沒有.
%d:%cpp 是沒有.
重要的事情說三遍
當然如果要加點的話可是可行的,但是需要對整個結構進行一些變形,在這裏就不展開了
解釋一下上面語句發生的事情
@$(CC) -MM $(CFLAGS) $< $(INC) > [email protected];
這句是非常通用的獲取依賴頭文件的方法,不過在最後的寫入文件裏面我沒有用$$$$作爲進程號設置文件名,我覺得這樣比較麻煩還需要\來支持寫在一行,直接指定一個不會重複的就可以了
@sed -i 's,\($(*F)\)o[ :]*,$(*D)/\1o: ,g' [email protected] ;
這一句也是十分常見 第一句的結果爲 a.o: src/a.cpp inc/a.h 這句話的意思爲將其替換成 src/a.o: src/a.cpp inc/a.h
這個替換對下面的有關鍵性幫助 ,因爲OBJ裏面存的變量都是形如src/a.o的 與這個相對應起來
@sed 's,\($*\)o[ :]*,\1o $@ : ,g' < [email protected] > $@;
這一句不展開講,也很通用 將 src/a.o: src/a.cpp inc/a.h 替換爲 src/a.o src/a.d: src/a.cpp inc/a.h
@echo "\t$(CC) -c -o $*o $< $(INC)" >>$@;
這一句是分目錄src和inc編譯的關鍵,沒有這一句編譯將不能正常進行.這是在src/a.d中手動添加inc目錄進編譯選項中,沒有這個 將在編譯的時候報找不到頭文件
@$(RM) [email protected]
-include $(patsubst %.cpp, %.d,$(SOURCES))
這兩句都不說了 一個是刪除,另外一個是包含src/a.d的makefile規則的文件
到這裏我們的makefile自動依賴就完成了,可以作用於多個目錄,有着比較良好的通用性,可以試試
當然少不了clean 這個就自己寫吧