示例的要求
1.自動生成target文件夾存放可執(zhí)行文件
2.自動生成objs文件夾存放編譯生成的目標(biāo)文件
3.支持調(diào)試版本的編譯選項
4.考慮代碼的擴展性
完成該示例所需的
1.$(wildcardpattern)獲取當(dāng)前工作目錄中滿足pattern的文件或目錄列表
2.$(addprefix,_name)給名字列表name的每一個名字增加前綴_prefix
關(guān)鍵技巧
1.自動獲取當(dāng)前目錄下的源文件列表(函數(shù)調(diào)用)
SRC : = $(wildcard *.c)
2.根據(jù)源文件列表生成目標(biāo)目標(biāo)文件列表(變量的值替換)
OBJS := $(SRCS:.c=.o)
3.對每一個目標(biāo)文件列表加上路徑前綴(函數(shù)調(diào)用)
OBJS := $(addprefix path/,$(OBJS))
規(guī)則中的模式替換(目錄結(jié)構(gòu))
編譯規(guī)則的依賴
編譯的示例代碼及運行結(jié)果
CC := gcc
MKDIR := mkdir
RM := rm -fr
DIR_OBJS := objs
DIR_TARGET := target
DIRS := $(DIR_OBJS) $(DIR_TARGET)
TARGET := $(DIR_TARGET)/hello-makefile.out
# main.c const.c func.c
SRCS := $(wildcard *.c)
# main.o const.o func.o
OBJS := $(SRCS:.c=.o)
# objs/main.o objs/const.o objs/func.o
OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
.PHONY : rebuild clean all
$(TARGET) : $(DIRS) $(OBJS)
$(CC) -o $@ $(OBJS)
@echo "Target File ==> $@"
$(DIRS) :
$(MKDIR) $@
$(DIR_OBJS)/%.o : %.c
ifeq ($(DEBUG),true)
$(CC) -o $@ -g -c $^
else
$(CC) -o $@ -c $^
endif
rebuild : clean all
all : $(TARGET)
clean :
$(RM) $(DIRS)
運行結(jié)果
小結(jié):
1.目錄可以成為目標(biāo)的依賴,在規(guī)則中創(chuàng)建目錄
2.預(yù)定義函數(shù)是makefile不可或缺的部分
3.規(guī)則這的模式匹配可以直接針對目錄中的文件
4.可以使用命令行變量編譯特殊的目標(biāo)版本
一.編譯行為帶來的缺陷
1.預(yù)處理器將頭文件中的代碼直接插入源文件
2.編譯器只能通過預(yù)處理后的源文件產(chǎn)生目標(biāo)文件‘
所以,規(guī)則中以源文件為依賴,命令可能無法執(zhí)行
示例
在第一張圖可以看出main.c與func.c是依賴于func.h的,此時將func.h中的打印信息改了之后運行的結(jié)果如下圖所示
由運行的結(jié)果可以看到把打印的信息改變了,但是make之后的結(jié)果并沒有改變,這是因為并沒有把func.h算子啊依賴上去,所以在它的打印信息改變之后,結(jié)果還是一樣的 ,需要進(jìn)行以下修改才能實現(xiàn)修改打印信息,運行結(jié)果也改變(如圖所示)
由上面的解決方法可以得出
1.頭文件作為依賴條出現(xiàn)于每個目標(biāo)對應(yīng)的規(guī)則中
2.當(dāng)頭文件改動,任何源文件都將被重新編譯
3.當(dāng)項目中頭文件數(shù)量巨大時,makefile將很難維護
二.改進(jìn)的方法
1.通過命令自動生成對頭文件的依賴
2.將生成的依賴自動包含進(jìn)makefile中
3.當(dāng)頭文件改動后,自動確認(rèn)需要重新編譯的文件
所需條件
1.Linux命令sed
2.編譯器依賴生成選項gcc -MM(gcc -M)
A.Linux中的sed命令
1.sed是一個流編輯器,用于流文本的修改(增/刪/查/改)
2.sed可用于流文本的中的字符串替換
3.sed的字符串替換方式為 :sed 's:src:des:g'
B.sed的正則表達(dá)式支持
1.在sed中可以用正在表達(dá)式匹配替換目標(biāo)
2.并且可以使用匹配的目標(biāo)生成替換結(jié)果
C.gcc關(guān)鍵編譯選項(生成依賴關(guān)系)
1.獲取目標(biāo)的完整依賴關(guān)系(gcc -M test.c)
2.獲取目標(biāo)的部分依賴關(guān)系(gcc -MM test.c)
D.makefile中的include關(guān)鍵字
1.類似C語言中的include
2.將其它文件的內(nèi)容原封不動的搬入當(dāng)前文件
make對include關(guān)鍵字的處理方式
a.在當(dāng)前目錄搜索或指定目錄搜索目標(biāo)文件
1.搜索成功:將文件搬入當(dāng)前makefile中
2.搜索失敗:產(chǎn)生警告
a.以文件名作為目標(biāo)查找并執(zhí)行對應(yīng)規(guī)則
b.當(dāng)前文件名對應(yīng)的規(guī)則不存在時,最終產(chǎn)生錯誤
代碼示例及運行結(jié)果
makefile中命令的執(zhí)行機制
1.規(guī)則中的每個命令默認(rèn)是在一個新的進(jìn)程中執(zhí)行
2.可以通過連續(xù)符(;)將多個命令組成一個命令
3.組合的命令依次在同一個進(jìn)程中被執(zhí)行
4.set -e指定發(fā)生錯誤后立即退出執(zhí)行
示例:
該代碼主要的目的是想在當(dāng)前文件夾下新建test文件夾,然后進(jìn)入test文件夾,創(chuàng)建subtest文件夾,但是make之后的結(jié)果如圖所示,可以看到subtest與test文件夾在同一級目錄,不是我們要的結(jié)果
經(jīng)過修改之后的代碼及運行結(jié)果
思路:通過gcc -MM 和sed得到.dep依賴文件,通過inclue指令包含所有的.dep依賴文件
運行的結(jié)果:
該示例可能會出現(xiàn)的問題是如何在makefile在組織.dep文件到指定目錄
解決的思路:
當(dāng)include發(fā)現(xiàn).dep文件不存在:
1.通過規(guī)則和命令創(chuàng)建deps文件
2.將所有.dep文件創(chuàng)建到deps文件夾
3..dep文件記錄目標(biāo)文件的依賴關(guān)系
代碼實現(xiàn)
總結(jié):
a.使用減號(-)不但關(guān)閉了include發(fā)出的警告,同時關(guān)閉了錯誤,當(dāng)錯誤發(fā)生時make將忽略這些錯誤
b.當(dāng)目標(biāo)文件不存在(以文件名查找規(guī)則,并執(zhí)行)
c.當(dāng)目標(biāo)文件不存在,且查找到的規(guī)則在創(chuàng)建了目標(biāo)文件(將創(chuàng)建成功的目標(biāo)文件包含進(jìn)當(dāng)前makefile)
d.當(dāng)目標(biāo)文件存在(將目標(biāo)文件包含進(jìn)當(dāng)前makefile,以目標(biāo)文件名查找是否有相應(yīng)的規(guī)則)
e.當(dāng)目標(biāo)文件存在,且目標(biāo)名對應(yīng)的規(guī)則被執(zhí)行(規(guī)則中的命令更新了目標(biāo)文件,make重新包含目標(biāo)文件,替換之前包含的內(nèi)容),目標(biāo)文件未被更新(無操作)
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。