溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么進(jìn)行Makefile分析

發(fā)布時(shí)間:2021-12-23 17:17:00 來(lái)源:億速云 閱讀:113 作者:柒染 欄目:大數(shù)據(jù)

怎么進(jìn)行Makefile分析,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。

什么是Makefile

Makefile是一個(gè)名為GNU-Make軟件所需要的腳本文件,該腳本文件可以指導(dǎo)Make軟件控制arm-gcc等工具鏈去編譯工程文件最終得到可執(zhí)行文件,幾乎所有的Linux發(fā)行版都內(nèi)置了GNU-Make軟件,VScode等多種IED也內(nèi)置了Make程序。

你見到的xxx.mk文件或者M(jìn)akefile都統(tǒng)稱為Makefile腳本文件。

Makefile的規(guī)則

Makefile的規(guī)則如下,這里的[TAB]指鍵盤上的TAB按鍵,不是空格,如果在命令前輸入了空格則會(huì)造成錯(cuò)誤,并且在Makefile中TAB鍵不能隨意使用:

目標(biāo) : 依賴

[TAB]命令

例如:

Hello :

@echo “Hello”

這時(shí)執(zhí)行make命令就會(huì)輸出一條語(yǔ)句”Hello”,Hello是目標(biāo),依賴為空,為了生成目標(biāo),需要執(zhí)行echo “Hello”語(yǔ)句,從而導(dǎo)致輸出Hello。

例如:假設(shè)我們有一個(gè)Hello.c C語(yǔ)言源文件,需要將其編譯不鏈接為Hello.o文件,最后在進(jìn)行連接,Makefile內(nèi)容如下:

Hello.out : Hello.o

gcc -o Hello.out Hello.o

Hello.o : Hello.c

gcc -c -o Hello.o Hello.c

這時(shí)執(zhí)行make命令,make解釋器發(fā)現(xiàn)目標(biāo)為“Hello.out”,但是生成Hello.out需要Hello.o,發(fā)現(xiàn)目錄下找不到“Hello.o”,就向下查找是否有生成Hello.o的規(guī)則,找到了,發(fā)現(xiàn)”Hello.o”依賴于”Hello.c”,在目錄下也找到了Hello.c,就執(zhí)行語(yǔ)句“gcc -c -o Hello.o Hello.c”生成”Hello.o”,只要編譯過(guò)程不出錯(cuò),即可得到”Hello.o”,這時(shí)可以執(zhí)行“gcc -o Hello.out Hello.o“生成”Hello.out”

從哪里開始分析?

這里可以用分析一個(gè)C語(yǔ)言或Java語(yǔ)言程序來(lái)類比,一般都是根據(jù)程序是執(zhí)行流來(lái)進(jìn)行分析,也就是先找到main函數(shù),因?yàn)閙ain函數(shù)是程序的執(zhí)行入口,Makefile也有執(zhí)行入口,在執(zhí)行make命令時(shí),make解釋器默認(rèn)搜索當(dāng)前目錄下名為“Makefile”的文件,找到后,執(zhí)行生成第一個(gè)目標(biāo)的命令及生成其依賴所需的命令。

這里選擇在SDK/Targets目錄中STM32L431_BearPi工程中的GCC目錄下的Makefile開始分析。

第1行到第140行都是設(shè)置一些變量和導(dǎo)入一些makefile文件(其中也沒有任何規(guī)則,都是進(jìn)行一些變量的設(shè)置),第143行是第一條規(guī)則

怎么進(jìn)行Makefile分析

當(dāng)我們執(zhí)行make或make all時(shí),就開始生成all目標(biāo),其依賴于BUILD_DIR(GCC/build)目錄中的TARGET(Huawei_LiteOS).elf文件,BUILD_DIR和TARGET為兩個(gè)變量,一開始就被賦值,如下圖所示,實(shí)際使用時(shí)$(變量)會(huì)被替換為變量的值,例如$(TARGET).elf最終會(huì)被替換為Huawei_LiteOS.elf。

怎么進(jìn)行Makefile分析

怎么進(jìn)行Makefile分析

可是Huawei_LiteOS.elf還不存在,make只好繼續(xù)向下查找是否有生成Huawei_LiteOS.elf的規(guī)則,好在第147行的目標(biāo)為Huawei_LiteOS.elf,這就是生成Huawei_LiteOS.elf的規(guī)則,該規(guī)則依賴為$(OBJ_DIRS) $(C_OBJ) $(S_OBJ)分別對(duì)應(yīng)三個(gè)目錄,這三個(gè)目錄都不存在,所以make只好繼續(xù)向下查找,它發(fā)現(xiàn)第152行正好為目標(biāo)是該目錄的規(guī)則,就創(chuàng)建了該目錄,解決了$(OBJ_DIRS)這個(gè)依賴,接著該處理$(C_OBJ)這個(gè)依賴

Make向下查找依賴發(fā)現(xiàn)位于第156行出現(xiàn)生成這個(gè)以來(lái)的規(guī)則,這里的$(C_OBJ):$(BUILD_DIR)/%.o:%.c對(duì)應(yīng)makefile中的靜態(tài)模式,我這里簡(jiǎn)單的說(shuō)一下,大家如果想深入了解可以自行百度。

靜態(tài)模型的格式如下:

目標(biāo)列表: 與目標(biāo)列表相匹配的模型: 與依賴相匹配的模型

[TAB]命令

來(lái)看一個(gè)例子,

怎么進(jìn)行Makefile分析

目標(biāo)列表中有foo.o、bar.o和test.s三個(gè)值,首先將匹配%.o的模型找出來(lái),test.s不匹配就被遺棄了,將匹配的foo.o和bar.o替換為foo.c和bar.c,最終這一條規(guī)則等于執(zhí)行了下列這兩條規(guī)則,為什么要這樣做呢?你可以試想以下,假設(shè)目標(biāo)列表中有幾千個(gè)文件,這樣做的話是不是就可以少寫很多規(guī)則:

怎么進(jìn)行Makefile分析

回到LiteOS_Lab的Makefile上來(lái),156行將C_OBJ變量中的符合build/xxx.o格式的文件作為xxx.c格式的依賴,C_OBJ變量的賦值如下圖所示:

怎么進(jìn)行Makefile分析

$(patsubst PATTERN, REPLACEMENT, TEXT)函數(shù)的作用是模式替換,將TEXT中以空格隔開的每個(gè)單詞(文件名),符合PATTERN格式的替換為REPLACEMENT格式,例如第124行,將所有的C_SOURCE變量中的文件名,凡是只要在SDK/ iot_link目錄下的都替換為.o后綴,SDK/ iotlink目錄中有一個(gè)符合該模型的文件,link_main.c,在執(zhí)行該規(guī)則對(duì)應(yīng)的命令時(shí),目標(biāo)文件為link_main.o,第125和126行同上。

怎么進(jìn)行Makefile分析

這里以link_main.c為例向大家講解指令,經(jīng)過(guò)模式替換后規(guī)則如下:

link_main.o: link_main.c

$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(@:%.o=%.lst) $< -o $@

這里的CC是指arm-none-eabi-gcc,CFLAGS是指各類編譯參數(shù),例如-MMD -MP -Wno-missing-braces,$(@:%.o=%.lst)函數(shù)的作用是將$@目標(biāo)符合%.o模型的值替換為%. lst,這里就將link_main.o替換link_main. lst,$<是指第一個(gè)依賴,$@是指目標(biāo),組合的命令后如下:

arm-none-eabi-gcc -c -MMD -MP -Wno-missing-braces -Wa,-a,-ad,-alms=link_main. lst link_main.c -o link_main.o。一句話來(lái)說(shuō)就是將所有的.c源文件編譯不鏈接生成.o文件和.lst文件,等待后續(xù)進(jìn)一步操作。

第160和161行的操作類似于上面的操作,將所有的匯編文件都編譯不鏈接生成.o文件等待后續(xù)進(jìn)一步操作。

第147到149行規(guī)則所需的依賴全部都生成好了,可以開始執(zhí)行該規(guī)則的命令,將所有依賴通過(guò)LDFLAGS變量中的值鏈接生成Huawei_LiteOS.elf文件并列出程序文件中各段的大小。

LDFLAGS變量中通過(guò)MCU變量定義了內(nèi)核相關(guān)參數(shù),例如ARM架構(gòu)的版本以及是否支持硬件浮點(diǎn)數(shù)運(yùn)算等參數(shù),如下圖所示,如果你需要將工程移植到不是STM32L431系類的MCU上,就需要修改MCU變量的值。

怎么進(jìn)行Makefile分析

怎么進(jìn)行Makefile分析

LDFLAGS變量中通過(guò)LDSCRIPT變量讀取os.ld鏈接腳本來(lái)控制程序該如何鏈接,每個(gè)段應(yīng)該存放在程序中的何處,在os.ld鏈接腳本中還指明了MCU的RAM和FLASH大小及起始位置,我們?cè)谶M(jìn)行移植時(shí)也需要修改。

Huawei_LiteOS.elf文件是第143至145行規(guī)則的依賴,將該elf文件轉(zhuǎn)換為Huawei_LiteOS.hex和Huawei_LiteOS.bin文件,即可燒錄。

現(xiàn)在大家應(yīng)該明白make控制下的整個(gè)程序編譯過(guò)程了吧,以及Makefile文件起到的作用,我們?cè)賮?lái)看看前面的include導(dǎo)入的文件,如下圖所示:

怎么進(jìn)行Makefile分析

首先導(dǎo)入了.config文件,這由Kconfig軟件讀取用戶通過(guò)圖形化配置的各項(xiàng)參數(shù)信息生成的,其中包含了對(duì)SDK中各組件參數(shù)的配置信息,如下圖所示:

怎么進(jìn)行Makefile分析

怎么進(jìn)行Makefile分析

以AT組件為例,CONFIG_AT_ENABLE=y代表使能AT組件;CONFIG_AT_DEVNAME="atdev"將AT組件用到的串口以"atdev"注冊(cè)到driver層中;CONFIG_AT_OOBTABLEN=6 OOB表的長(zhǎng)度配置為6個(gè),這時(shí)用于接收異步數(shù)據(jù)的結(jié)構(gòu)體,意味著我們最多能配置6個(gè)特定字符串,當(dāng)這時(shí)字符串出現(xiàn)時(shí)調(diào)用相應(yīng)處理函數(shù)進(jìn)行處理;CONFIG_AT_RECVMAXLEN=1024將AT框架中的接收緩存區(qū)大小配置為1024字節(jié),如果你的MCU資源受限可以減少這里的大小;CONFIG_AT_TASKPRIOR=10將AT任務(wù)的優(yōu)先級(jí)配置為10,注意:這里只有第35行這條語(yǔ)句會(huì)影響Make的編譯,其余語(yǔ)句是為了記錄用戶做了哪些配置和生成iot_config.h所用。

.config文件中所有的組件配置都和上面分析的一致,如果組件沒有被使能如下圖所示:

怎么進(jìn)行Makefile分析

相信大家看到這里又有新的疑問(wèn)了,這些配置是如何影響到程序的編譯呢?回到前面的第70行include $(SDK_DIR)/iot_link/iot.mk,來(lái)看看這個(gè)SDK/iot_link目錄下的iot.mk文件中有什么你就有答案了,如下圖所示:

?怎么進(jìn)行Makefile分析

該Makefile將每個(gè)組件所屬文件夾下的Makefile也導(dǎo)入進(jìn)來(lái)了,我們還是以AT框架為例,第31行,導(dǎo)入at目錄下的at.mk文件,該Makefile內(nèi)容如下圖所示:

怎么進(jìn)行Makefile分析

看到了吧,第7行與前面的CONFIG_AT_ENABLE=y變量相對(duì)應(yīng),ifeq ($(CONFIG_AT_ENABLE),y)語(yǔ)句的意思是如果CONFIG_AT_ENABLE變量的值為y,則將ifeq到endif之間的語(yǔ)句全部執(zhí)行。

第8至9行將at目錄下所有.c文件添加到C_SOURCES變量中,注意這里用的是+=是追加上去。

第11至12行將at目錄下所有.h文件所在路徑(注意是路徑,通過(guò)-I參數(shù)指定頭文件所在的路徑,這樣編譯器才能找到頭文件,否則會(huì)因?yàn)檎也坏筋^文件導(dǎo)致編譯失?。┨砑拥紺_INCLUDES變量中,注意這里用的是+=是追加上去。

第14至14行將-D CONFIG_AT_ENABLE=1文本追加到C_DEFS變量中。

這三個(gè)變量大家都很眼熟吧,這就是工程目錄/GCC目錄中Makefile中的那三個(gè)變量,如下圖所示:

怎么進(jìn)行Makefile分析

怎么進(jìn)行Makefile分析

這樣AT組件中的所有源文件和頭文件就參與了編譯。

回到第三個(gè)include,include $(MAKEFILE_DIR)/project.mk,這是用于包含(引入)工程目錄/GCC目錄下的project.mk,該Makefile部分內(nèi)容如下圖所示:

怎么進(jìn)行Makefile分析

主要用于包含Hal庫(kù)中的文件以及用戶自己添加進(jìn)去的文件,這也是移植時(shí)需要進(jìn)行修改的文件之一,大家可以仿照我前面分析的方法自己分析一下。最終所有被添加進(jìn)入的.c源文件會(huì)被追加到C_SOURCES變量中,所有.h頭文件所在的路徑會(huì)被追加到C_INCLUDES變量中。

SDK中所有的Makefile文件都不需要也不能進(jìn)行修改,只需要修改工程中的三個(gè)Makefile,.config(這個(gè)不用手動(dòng)修改,可以通過(guò)圖形化配置進(jìn)行修改),Makefile(根據(jù)目標(biāo)MCU修改MCU相關(guān)的參數(shù)即可,也就是MCU這個(gè)變量的值),project.mk(根據(jù)目標(biāo)MCU修改、添加或刪除庫(kù)文件以及用戶文件以及最后的C_DEFS變量即可)。

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI