??在之前的博文 Linux 之八 完整嵌入式 Linux 環(huán)境介紹及搭建過程詳解 中我們說了要一步步搭建整個嵌入式 Linux 運行環(huán)境,今天繼續(xù)介紹 U-Boot 相關(guān)的內(nèi)容。我所使用的硬件平臺及整個要搭建的嵌入式 Linux 環(huán)境見博文 Linux 之八 完整嵌入式 Linux 環(huán)境介紹及搭建過程詳解,沒有特殊說明都是在以上環(huán)境中進行驗證的,就不過多說明了。
??這篇博文我們僅僅關(guān)注 U-Boot 構(gòu)建過程本身,想要吃透 U-Boot,有太多東西需要學(xué)習(xí)!最開始我想放到一篇文章中,寫著寫著內(nèi)容越來越多,最終超過了 CSDN 編輯器的限制。。。最終決定把內(nèi)容拆分成多篇文章。你可能需要:
- U-Boot 之一 零基礎(chǔ)編譯 U-Boot 過程詳解 及 編譯后的使用說明
- U-Boot 之二 詳解使用 eclipse + J-Link 進行編譯及在線調(diào)試
- U-Boot 之三 U-Boot 源碼文件解析及移植過程詳解
- U-Boot 之五 詳解 U-Boot 及 SPL 的啟動流程
Kbuild && Kconfig
??Kbuild && Kconfig 隸屬于 Linux Kernel Build System。在宏觀上,Kbuild && Kconfig 可以統(tǒng)稱為 Kbuild,從微觀上來說,Kbuild 指的是編譯的過程,而 Kconfig 指的在編譯之前對內(nèi)核進行配置的過程(該過程中會編譯一些工具來實現(xiàn)配置過程)。關(guān)于詳細的可以查看 Linux Kernel 的官方文檔 The Linux Kernel Documentation 中的 Kernel Build System 章節(jié)的介紹。
- 本文約定俗成的稱呼:構(gòu)建 指的 Kbuild + Kconfig;配置 指的 Kconfig;編譯 指的 Kbuild。
- https://www./doc/
??Kbuild && Kconfig 這套構(gòu)建系統(tǒng)一個顯著的特點就是每一級目錄都會有單獨的相關(guān)文件,然后會被上一級相同的文件引用。這樣就保證了每一級目錄都是相互獨立的。尤其是對于源碼的維護者來說,這個是至關(guān)重要。每個維護者可以只關(guān)心他所負責(zé)的代碼部分,任何更改只需要變更它自己的 Kbuild && Kconfig 相關(guān)文件即可。它本身主要包含以下幾類文件:
-
Makefile: Kbuild && Kconfig 這套構(gòu)建系統(tǒng)本身屬于 make 功能的擴展,因此,整個工作過程就是一些列 Makefile 文件的調(diào)用。其中入口就是根目錄下的 Makefile 文件,Makefile 中會調(diào)用各種工具以實現(xiàn)不同的功能。
??注意,為了區(qū)分不同的功能,在源碼中對于 Makefile 的命名有時候會加一個后綴。例如,config.mk、Makefile.build、Makefile.clean等這些都屬于 Makefile 文件。
??Makefile 文件無法在線調(diào)試,對于理解一個復(fù)雜的 Makefile 很不友好。一般我們可以使用--debug參數(shù)讓 make 打印詳細的信息來協(xié)助理解。或者是在 Makefile 中添加一些打印信息,常用打印方式有兩種:- 使用
$(info, xxxx$(xxx))、$(warning, xxxx$(xxx))、$(error, xxxx$(xxx)),其中,$(xxx)表示某個變量。這三個命令可以加到 Makefile 的任意地方,注意$(error, xxxx$(xxx))會終止 Make 過程。 - 使用
@echo "xxxx $xx xxxx",其中,$(xxx)表示某個變量。這個命令只能用在目標后邊,且前面是個TAB。這個就是標準 Makefile 語法中的一個命令。
再順帶說一句
make的工作的一些機制:- 如果給出了參數(shù),則
make優(yōu)先去找匹配的規(guī)則(匹配規(guī)則:完整匹配 > 通配符半匹配 > 完全通配符匹配)去執(zhí)行;如果沒有給出參數(shù),make會自動找到 Makefile 中第一個目標中沒有通配符的規(guī)則執(zhí)行。 - 如果中間遇到 include 其他文件,就會緊接著執(zhí)行 include 的文件,完成后再繼續(xù)執(zhí)行本文件。
make總是從 Makefile 的開頭開始解析,并不是找到匹配目標之后僅執(zhí)行匹配目標的命令。也就是說,在匹配之前,Make 可能已經(jīng)解析了很多判斷條件。- 對于匹配的規(guī)則如果有依賴,優(yōu)先解析依賴。注意,依賴的匹配也符合 1 中所說的規(guī)則。
- 命令前面加了
@字符,則不顯示命令本身而只顯示它的結(jié)果。命令前面加了-號,即使這條命令出錯,make也會繼續(xù)執(zhí)行后續(xù)命令。 - 如果 Makefile 中存在多條同名規(guī)則,則
make程序會嘗試將他們合并。但是如果這些同名規(guī)則都有命令的話,make會給出警告,并用后面的命令代替前面的命令。

- 使用
-
Kconfig 文件: 這個文件就是 Kconfig 系統(tǒng)的菜單項,當我們使用命令:
make menuconfig時,Kconfig 系統(tǒng)讀取該文件,根據(jù)該文件的內(nèi)容生成各級菜單。U-Boot 源碼根目錄下的 Kconfig 就是頂級的配置菜單,其中會在引入其他目錄下的 Kconfig 作為二級菜單,依次類推。 -
.config 文件: 這個文件記錄了我們菜單項中的配置的具體值,我們所有對于構(gòu)建的配置的存放在這個文件中,我們在,Kconfig 系統(tǒng)菜單中的更改,最終都會改寫該文件。注意:該文件默認是個隱藏文件,可以使用
ls -al查看。 -
xxxx_defconfig 文件: xxxx_defconfig 文件就為 Kconfig 系統(tǒng)的菜單項提供一個默認值。不過,Kconfig 系統(tǒng)不會直接讀取 xxxx_defconfig 文件,而是需要使用方式是通過
make xxx_deconfig生成帶默認值的.config。這樣,在加載 Kconfig 時,就可以同時加載.config以提供默認值。
??簡單來說,xxxx_defconfig 就是為了方便支持更多個性化配置,從而可以盡可能少的改動源代碼。 -
Kbuild 文件: 這個是 Kbuild 系統(tǒng)使用的文件,該文件用于定義一些源碼使用的需要根據(jù)編譯環(huán)境產(chǎn)生的中間文件。
-
config.mk 文件: 用來處理一些編譯過程中的環(huán)境變量。Linux Kernel 沒有這個文件,U-Boot 需要使用它。
??U-Boot 從 v2014.10 版本開始也引入 Kbuild && Kconfig 這套構(gòu)建系統(tǒng),相比于原來應(yīng)該是復(fù)雜了不少。但是對于屬性 Linux Kernel 的人來說確實是一個好消息!今天我們就來學(xué)習(xí)一下 U-Boot 中這套系統(tǒng)的具體工作流程。
??Kbuild && Kconfig 這套構(gòu)建系統(tǒng)中定義了很多命令,我們可以使用 make help 來進行查看(就在根目錄的 Makefile 文件中),其中經(jīng)常用到命令如下圖所示:

構(gòu)建過程
??在 Kbuild && Kconfig 這套構(gòu)建系統(tǒng)中,源碼中使用的有些文件是要靠 Kbuild && Kconfig 這套系統(tǒng)來生成的,直接在源碼中是找不到。這就要求我們必須要了解 Kbuild && Kconfig 是如何工作的,更重要的是要知道 Kbuild && Kconfig 會產(chǎn)生哪些源碼使用的文件。
??整個構(gòu)建過程的這個入口就是源碼根目錄下的 Makefile 文件。下面我們先來整體看一下這個文件的總體結(jié)構(gòu),并且對其中的規(guī)則進行一下說明。其大體可以分為三部分:

整個文件的前半部分就是定義一堆符號,檢測工作環(huán)境、處理各種參數(shù),基本沒有實際與編譯源碼相關(guān)的命令。下面重點介紹一些(注意,由于我在其中添加了一些打印信息,導(dǎo)致行號與原文件有區(qū)別):
- 給
HOST_ARCH賦值。HOST_ARCH代表我們當前指定的 主機 的類型。當我們沒有指定的時候,它就是我們的 PC 架構(gòu)(例如我的 HOST_ARCH_X86_64),指定 交叉編譯器 后(例如,我們編譯時CROSS_COMPILE=arm-none-eabi- ARCH=arm make -j4),他就是我們指定的架構(gòu)(HOST_ARCH_ARM)。

- 處理 make 參數(shù):
make V=1、make -s等。這里導(dǎo)出了quiet、Q、KBUILD_VERBOSE,用以指示編譯過程的顯示方式。

- 處理編譯的當前目錄以及編譯輸出目錄。其中,我們可以使用環(huán)境變量
KBUILD_OUTPUT或者 指定make O=xxx的方式指定輸出目錄。而編譯的源目錄KBUILD_SRC根據(jù)注釋僅用于在 OBJ 目錄時,而且一般不給使用者使用。代碼可以簡化為以下邏輯:
??這里需要注意的就是,如果指定了輸出目錄,將轉(zhuǎn)到 輸出目錄中去執(zhí)行 Makefile,本 Makefile 的執(zhí)行就結(jié)束了。if `KBUILD_SRC` 為空 檢查 O=xxx 參數(shù),如果有指定,則賦值給 `KBUILD_OUTPUT` 定義偽目標_all ,且 _all 為空目標,避免后面include其余文件的時候?qū)ふ译[含的第一個目標。后面肯定還會定義 _all, 而且肯定不為空 if `KBUILD_OUTPUT` 不為空 `KBUILD_OUTPUT` = 創(chuàng)建并指定的目錄 到 `KBUILD_OUTPUT` 繼續(xù)執(zhí)行 make (其中需要過濾掉一些內(nèi)容,防止無限嵌套)。因為 在 `KBUILD_OUTPUT` 中執(zhí)行的 Makefile 就是當前這個 Makefile skip-makefile 賦值為 1 endif endif if skip-makefile 為空。不空表示上面已經(jīng)在 `KBUILD_OUTPUT` 中執(zhí)行過了 執(zhí)行其他各種操作 endif 整個makefie 結(jié)束skip-makefile被賦值為 1,此后只有在skip-makefile不為 1 時才會繼續(xù)執(zhí)行。 - 再接下來就是判斷
make C=x參數(shù)以及處理是編譯整個 U-Boot 還是編譯的模塊(由環(huán)境變量SUBDIRS或make M=xxx執(zhí)行),如果是模塊,賦值給KBUILD_EXTMOD(賦值厚就不空)。

??前面有說過,開始定義了一個空的目標 _all,這里再次定義目標 _all。這里的_all根據(jù)KBUILD_EXTMOD的值依賴于all或者是modules,但是命令還是為空。這里我們不關(guān)心模塊,重點關(guān)注all。all又依賴.binman_stmp和inputs,如下圖所示:

關(guān)于all后文會有詳細的介紹。 - 繼續(xù)下來就是檢查編譯工具鏈。并做了一些重命名以統(tǒng)一編譯時的顯示。

- 再繼續(xù)就是 kconfig 和 kbuild 共用的一些規(guī)則
scripts_basic、outputmakefile的定義。然后檢查要執(zhí)行的操作是否需要.config文件,最終出現(xiàn)以下邏輯:
也就是在此之前的內(nèi)容,無論給出啥命令,都會被 make 解析,然后從這里開始分道揚鑣!if 是多個目標(mixed-targets=1) 一個一個處理 else if 配置(config-targets=1),即我們執(zhí)行的 make xxxconfig 時的處理 config: scripts_basic outputmakefile FORCE $(Q)$(MAKE) $(build)=scripts/kconfig $@ %config: scripts_basic outputmakefile FORCE $(Q)$(MAKE) $(build)=scripts/kconfig $@ else 這里就是 編譯過程以及 非 config(例如 clean) 的處理了 scripts: scripts_basic scripts_dtc include/config/auto.conf $(Q)$(MAKE) $(build)=$(@) if 需要 .confg 檢查 .confg 文件 else include/config/auto.conf: ; endif all 的定義(實際編譯文件等等) 非 config(例如 clean、check)等的定義 endif Makefile 結(jié)束
??至此,就開始根據(jù)給出的目標的不同開始區(qū)分具體操作類型了,后續(xù)我們單獨章節(jié)來介紹!***注意,由于我在 Makefile 中添加了一些打印信息,導(dǎo)致行號與原文件有區(qū)別!***下面是我大體整理的一個流程圖:

Kconfig
??在 Kbuild && Kconfig 這套構(gòu)建系統(tǒng)中,當我們使用 make xxxconfg 類似的命令時,就會執(zhí)行 Kconfig 流程。例如,當執(zhí)行 make menuconfig 時會出現(xiàn)一個配置界面,允許開發(fā)者通過類似于 UI 的方式來對內(nèi)核進行配置,之所為我們可以看到這個類似于 UI 的界面,就是因為 Kconfig 從中產(chǎn)生了多個文件和工具來實現(xiàn)的。
Kconfig 語法可以從 https://www./doc/html/latest/kbuild/kconfig-language.html 里來學(xué)習(xí)。
??當我們在 U-Boot 根目錄執(zhí)行 make menuconfig 或者 make xxx_deconfig 時,make 命令便會讀取 U-Boot 根目錄下的 Makefile 文件,然后解析并匹配 Makefile 文件中的規(guī)則 。而 xxxconfig 就會匹配根目錄下 Makefile 文件中的如下圖示的規(guī)則(% 可以匹配任意非空字符串,所以 menuconfig、xxx_deconfig 都匹配):

- Q 是否顯示信息信息,在 Makefile 前面有賦值為
@或空

- MAKE: 就是指的可執(zhí)行程序 make
- $(build): 定義在
./scripts/Kbuild.include中:181行

那么將以上命令展開之后就是:make -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig menuconfig或者$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig xxx_defconfig - $(srctree): 在 Makefile 前面有賦值為
.或$(KBUILD_SRC) - scripts_basic: 就定義在 U-Boot 根目錄的 Makefile 中

那么將以上命令第一句規(guī)則展開之后就是:make -f $(srctree)/scripts/Makefile.build obj=scripts/basic,第二句規(guī)則沒啥可說的,就是移除個文件。 - outputmakefile: 就定義在 U-Boot 根目錄的 Makefile 中,如下所示:

從規(guī)則代碼可以看出只有當 KBUILD_SRC 不為空時才有效,而對于 KBUILD_SRC 一般都是空,非空的情況下一般也不使用。因此,這里的依賴 outputmakefile 這里就是空。對于具體見如下說明:

- FORCE 是沒有規(guī)則和依賴的,所以每次都會重新生成 FORCE。當 FORCE 作為其他目標的依賴時,由于 FORCE 總是被更新過的,因此依賴所在的規(guī)則總是會執(zhí)行的。

??經(jīng)過上面的分析,最終由兩條語句 make -f $(srctree)/scripts/Makefile.build obj=scripts/basic 和 make -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig menuconfig 或者 make -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig xxx_defconfig 是我們需要進一步來解析的。接下來就要進入 /scripts/Makefile.build 這個文件了。
Makefile.build
??對于 Makefile.build 文件,目前我們只需要關(guān)注下圖所示的兩部分(說明見注釋):

接下就是進一步處理 scripts/basic/Makefile 或者 scripts/kconfig/Makefile 了。
make xxx_deconfig
??經(jīng)過上面的分析,當我執(zhí)行 make xxx_defconfig 時(例如,我這里的 make stm32f769-disco_defconfig),最終會執(zhí)行以下兩句:make -f $(srctree)/scripts/Makefile.build obj=scripts/basic 和 make -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig xxx_defconfig 。

make -f $(srctree)/scripts/Makefile.build obj=scripts/basic展開后是cc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 -o scripts/basic/fixdep scripts/basic/fixdep.c最終在scripts/basic/目錄下生成了可執(zhí)行工具fixdep。make -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig xxx_defconfig展開后是:
最終在cc -Wp,-MD,scripts/kconfig/.conf.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 -c -o scripts/kconfig/conf.o scripts/kconfig/conf.c bison -oscripts/kconfig/zconf.tab.c -t -l scripts/kconfig/zconf.y flex -oscripts/kconfig/zconf.lex.c -L scripts/kconfig/zconf.l cc -Wp,-MD,scripts/kconfig/.zconf.tab.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 -Iscripts/kconfig -c -o scripts/kconfig/zconf.tab.o scripts/kconfig/zconf.tab.c cc -o scripts/kconfig/conf scripts/kconfig/conf.o scripts/kconfig/zconf.tab.o scripts/kconfig/conf --defconfig=arch/../configs/stm32f769-eval_defconfig Kconfigscripts/kconfig/目錄下生成了可執(zhí)行工具conf,緊接著使用剛生成的scripts/kconfig/conf工具根據(jù)我們指定的stm32f769-eval_defconfig生成.config文件。
make menuconfig
??經(jīng)過上面的分析,當我執(zhí)行 make menuconfig 時,最終會執(zhí)行以下兩句:make -f $(srctree)/scripts/Makefile.build obj=scripts/basic 和 make -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig menuconfig 。

make -f $(srctree)/scripts/Makefile.build obj=scripts/basic與make xxx_deconfig時的語句是一樣的。如果在執(zhí)行make menuconfig之前沒有使用make xxx_deconfig,那么這句就會和make xxx_deconfig時一樣去執(zhí)行來生成scripts/basic/fixdep。make -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig menuconfig展開后是:
最終生成make -f ./scripts/Makefile.build obj=scripts/basic rm -f .tmp_quiet_recordmcount make -f ./scripts/Makefile.build obj=scripts/kconfig menuconfig set -e; mkdir -p scripts/kconfig/; /bin/bash scripts/kconfig/mconf-cfg.sh < scripts/kconfig/mconf-cfg.sh > scripts/kconfig/.mconf-cfg.tmp; if [ -r scripts/kconfig/.mconf-cfg ] && cmp -s scripts/kconfig/.mconf-cfg scripts/kconfig/.mconf-cfg.tmp; then rm -f scripts/kconfig/.mconf-cfg.tmp; else : ' UPD scripts/kconfig/.mconf-cfg'; mv -f scripts/kconfig/.mconf-cfg.tmp scripts/kconfig/.mconf-cfg; fi cc -Wp,-MD,scripts/kconfig/.mconf.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -c -o scripts/kconfig/mconf.o scripts/kconfig/mconf.c cc -Wp,-MD,scripts/kconfig/lxdialog/.checklist.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -c -o scripts/kconfig/lxdialog/checklist.o scripts/kconfig/lxdialog/checklist.c cc -Wp,-MD,scripts/kconfig/lxdialog/.inputbox.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -c -o scripts/kconfig/lxdialog/inputbox.o scripts/kconfig/lxdialog/inputbox.c cc -Wp,-MD,scripts/kconfig/lxdialog/.menubox.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -c -o scripts/kconfig/lxdialog/menubox.o scripts/kconfig/lxdialog/menubox.c cc -Wp,-MD,scripts/kconfig/lxdialog/.textbox.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -c -o scripts/kconfig/lxdialog/textbox.o scripts/kconfig/lxdialog/textbox.c cc -Wp,-MD,scripts/kconfig/lxdialog/.util.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -c -o scripts/kconfig/lxdialog/util.o scripts/kconfig/lxdialog/util.c cc -Wp,-MD,scripts/kconfig/lxdialog/.yesno.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -c -o scripts/kconfig/lxdialog/yesno.o scripts/kconfig/lxdialog/yesno.c cc -o scripts/kconfig/mconf scripts/kconfig/mconf.o scripts/kconfig/zconf.tab.o scripts/kconfig/lxdialog/checklist.o scripts/kconfig/lxdialog/inputbox.o scripts/kconfig/lxdialog/menubox.o scripts/kconfig/lxdialog/textbox.o scripts/kconfig/lxdialog/util.o scripts/kconfig/lxdialog/yesno.o -Wl,-Bsymbolic-functions -lncursesw -ltinfo scripts/kconfig/mconf Kconfigscripts/kconfig/mconf,緊接著使用剛生成的scripts/kconfig/mconf工具讀取根目錄的 Kconfig 文件,隨之出現(xiàn)配置界面。
??make xxx_deconfig之后,Kconfig 系統(tǒng)會在 U-Boot 源碼根目錄下生成 .config 文件,當我們使用 make menuconfig 修改了相關(guān)配置之后,Kconfig 系統(tǒng)最終也是修改根目錄下的 .config 文件(注意,該文件默認是個隱藏文件,可使用 ls -al 查看),而 .config 文件就記錄了我們當前對于 U-Boot 的配置,后續(xù)構(gòu)建時便會讀取該文件。
Kbuild
??這里說的 Kbuild 是微觀上的 Kbuild,指的是編譯的過程。在經(jīng)過上面 Kconfig 之后,接下來就是真正的編譯過程,這個過程采用的就是 Kbuild 系統(tǒng)。Linux 官方文檔地址:https://www./doc/html/latest/kbuild/index.html。
??編譯使用的命令是 CROSS_COMPILE=arm-none-eabi- ARCH=arm make -j8,當我們使用該命令之后,make 程序就會讀取 U-Boot 根目錄的 Makefile 文件,然后解析并匹配 Makefile 文件中的規(guī)則。由于這里沒有指明目標,Make 會自動找到 makefile 中第一個目標中沒有通配符的規(guī)則執(zhí)行,這里就是 _all。

??注意,這里的 _all 并不是第一個定義的 _all。第一個定義的 _all 是個空命令目標,空命令行可以防止 make 在執(zhí)行時試圖為重建這個目標去查找隱含命令(包括了使用隱含規(guī)則中的命令和“ .DEFAULT”指定的命令)。后面重新定義的 _all 才是最終生效的 _all
??如果 KBUILD_EXTMOD 為空的話 _all 依賴于 all。我們不編譯模塊(沒有指定 KBUILD_EXTMOD),所以 KBUILD_EXTMOD 就是空 ,_all 依賴于 all 的。 all 又依賴 .binman_stmp 和 inputs,如下圖所示:

注意,如果使用的命令是 CROSS_COMPILE=arm-none-eabi- ARCH=arm make all -j8,則直接就會匹配到 all 這條規(guī)則,就不會有 _all 啥事了!
??.binman_stamp這個比較簡單,就是通過使用 touch 命令更新 .binman_stamp 文件(不存在時會新建)的時間戳保證 binman 總是會被執(zhí)行。然后檢查一些定義,給出提示。

??重點就在 inputs,而 inputs 又是依賴于 $(INPUTS-y)。通過將 $(INPUTS-y) 展開后就是 checkarmreloc u-boot.srec u-boot.bin u-boot.sym System.map binary_size_check spl/u-boot-spl.bin u-boot.img u-boot.dtb u-boot-dtb.img 再進一步就是展開及處理各個依賴項了,下面我們重點來介紹一下 checkarmreloc 和 u-boot.srec,其他的大家自行解析。
-
checkarmreloc

將 u-boot 的各項依賴展開就是:u-boot: arch/arm/cpu/armv7m/start.o arch/arm/cpu/built-in.o arch/arm/cpu/armv7m/built-in.o arch/arm/lib/built-in.o arch/arm/mach-stm32/built-in.o board/st/common/built-in.o board/st/stm32f769-eval/built-in.o cmd/built-in.o common/built-in.o disk/built-in.o drivers/built-in.o drivers/dma/built-in.o drivers/gpio/built-in.o drivers/net/built-in.o drivers/net/phy/built-in.o drivers/power/built-in.o drivers/power/battery/built-in.o drivers/power/domain/built-in.o drivers/power/fuel_gauge/built-in.o drivers/power/mfd/built-in.o drivers/power/pmic/built-in.o drivers/power/regulator/built-in.o drivers/serial/built-in.o drivers/spi/built-in.o drivers/usb/cdns3/built-in.o drivers/usb/common/built-in.o drivers/usb/dwc3/built-in.o drivers/usb/emul/built-in.o drivers/usb/eth/built-in.o drivers/usb/host/built-in.o drivers/usb/mtu3/built-in.o drivers/usb/musb-new/built-in.o drivers/usb/musb/built-in.o drivers/usb/phy/built-in.o drivers/usb/ulpi/built-in.o env/built-in.o fs/built-in.o lib/built-in.o net/built-in.o u-boot.lds FORCE,其中:$(u-boot-init):arch/arm/cpu/armv7m/start.o$(u-boot-main):后面一大串 built-in.o$(u-boot-keep-syms-lto):空,不包含任何內(nèi)容
因此,我們需要重點來關(guān)注 u-boot.lds 這個依賴:

其中,$(LDSCRIPT)就是我們使用的鏈接腳本文件,這里就是./arch/arm/cpu/u-boot.lds。而 prepare 的內(nèi)容就比價多了,如下圖所示:

中間各種依賴,最終會到include/config/%.conf:這條規(guī)則。 -
u-boot.srec這個比較簡單,至于它依賴的 u-boot 在上面已經(jīng)說了。

其實到這里基本就可以了,解析來就不繼續(xù)深入了!下面來一張圖:

clean、mrproper、distclean
??介紹了以上的工作過程之后,我們再介紹一下三個與清理相關(guān)的命令:clean、mrproper、distclean。至于支持的其他命令基本都差不多,大家感興趣可以自己分析即可。這三個命令的清理程度是逐漸增加,后者包含前者,如下圖所示:

我們就以 distclean 為例來說明。當我們執(zhí)行 make distclean 這條命令時,make 讀取根目錄的 Makefile,然后開始解析,最終匹配到規(guī)則 distclean: mrproper,如下所示:

-
命令部分:第一個 find 命令查找上面指定的文件并刪除。其中的 “|” 表示管道,即左邊的輸出作為右邊的輸入。rm 命令刪除 boards.cfg 和 CHANGELOG。
關(guān)于 find 命令:https://www.cnblogs.com/shenqidu/p/10615593.html
關(guān)于 xargs 命令:https://www.runoob.com/linux/linux-comm-xargs.html -
依賴
mrproper:接下來重點看他的依賴mrproper,由于mrproper也有依賴,我把它們整理到一個圖中,如下所示:

從中可以看出,mrproper先執(zhí)行了clean,然后執(zhí)行$(mrproper-dirs)。綜合來看,clean和mrproper結(jié)構(gòu)基本一致,我們將里面各變量展開,其中: -
先看
clean:- 依賴
rm-dirs:展開后就是.tmp_versions、spl/* - 依賴
rm-files:展開后就是include/bmp_logo.h include/bmp_logo_data.h tools/version.h boot* u-boot* MLO* SPL System.map fit-dtb.blob* u-boot-ivt.img.log u-boot-dtb.imx.log SPL.log u-boot.imx.log lpc32xx-* bl31.c bl31.elf bl31_*.bin image.map tispl.bin* idbloader.img flash.bin flash.log defconfig keep-syms-lto.c - 依賴
$(clean-dirs):$(clean):定義在Kbuild.include文件中:clean := -f $(srctree)/scripts/Makefile.clean objcmd:定義在Kbuild.include文件中:cmd = @$(echo-cmd) $(cmd_$(1)),進一步$(echo-cmd)就在之上:echo-cmd = $(if $($(quiet)cmd_$(1)),echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
- 命令部分:
$(call cmd,rmdirs):$(call cmd,rmfiles):find xxx | xargs rm -f:在以上清理的基礎(chǔ)上再清理一些符號文件,臨時文件、腳本文件等
- 依賴
-
mrproper:- 依賴
rm-dirs:include/config、include/generated spl - 依賴
rm-files:.config、.config.old、include/autoconf.mk、include/autoconf.mk.dep、include/config.h - 依賴
clean:就是上面的clean - 依賴
$(mrproper-dirs): - 命令部分:
$(clean):同上cmd:同上
- 依賴
參考
- https:///2021/04/27/uboot-%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90/
- https://www.cnblogs.com/humaoxiao/p/4189411.html
- https://github.com/zhaojh329/U-boot-1/blob/master/%E7%AC%AC9%E7%AB%A0-U-boot%E7%BC%96%E8%AF%91%E4%B9%8B%E4%B8%80%E9%85%8D%E7%BD%AE%E8%BF%87%E7%A8%8B.md
- https://blog.csdn.net/guyongqiangx/article/details/52558087
- https://yunyanan./exploring_kbuild/
- https:///article/18/10/kbuild-and-kconfig
- https://www.cnblogs.com/syyxy/p/9350999.html
- https://blog.csdn.net/q_z_r_s/article/details/80783631
- https://blog.csdn.net/linuxweiyh/article/details/100528718




