1. 工作目錄
如上圖代碼,編譯之後将解壓包放到windows解壓觀看。
目錄如下:
檔案夾:
檔案:
1.1 arch
這裡面存放着和架構有關的檔案
我們用的是arm架構的檔案,打開arm檔案夾:
其中mach開頭的是和裝置有關的檔案,比如exynos是和三星有關的,我們使用的是imx-common,是以要使用這個檔案夾,cpu也是和CPU有關的檔案,打開之後:
我們使用的開發闆是armv7的,u-boot.lds就是連結檔案。
1.2 board
board檔案夾裡面的檔案是和闆子有關的,我們打開裡面的飛思卡爾的檔案夾
evk字尾是正點原子在這個基礎上開發的,移植uboot的時候要參考這個檔案夾
1.3 config
此檔案夾為 uboot 配置檔案,uboot 是可配置的,但是你要是自己從頭開始一個一個項目的配置,那就太麻煩了,是以一般半導體或者開發闆廠商都會制作好一個配置檔案。我們可以在這個做好的配置檔案基礎上來添加自己想要的功能,這些半導體廠商或者開發闆廠商制作好的配置檔案統一命名為“xxx_defconfig”,xxx 表示開發闆名字,這些 defconfig 檔案都存放在configs檔案夾,是以,NXP 官方開發闆和正點原子的開發闆配置檔案肯定也在這個檔案夾中,
我們使用的mx6ull_14x14_ddr512_emmc_deconfig
在編譯uboot之前一定要用這個配置檔案
1.4 u_boot.xxx.cmd檔案
這些檔案都是編譯生成的,是一些指令檔案
.u-boot.bin.cmd
裡面定義了一個變量叫cmd_u-boot.bin 拷貝了u-boot-nodtb.bin一份改成u-boot.bin
那我們就看u-boot-nodtb.bin
u-boot-nodtb.bin.cmd
使用arm-linux-gnueabihf-objcopy将elf檔案轉化為bin檔案
那就是u-boot.elf 變成u-boot-nodtb.bin
u-boot.cmd
注意和上面的bin.cmd分開,這個是生成elf的,是以猜測是連結檔案
輸出是u-boot, 後面也可以不用加elf,和最開始交叉編譯的聯系起來
還有一個是用來燒寫用的,把bin變成imx檔案,就是.u-boot.imx.cmd
1.5 u-boot.xxx
1.6 .config檔案
配置檔案,在上面有一個make mx6ull_14x14_ddr512_emmc_deconfig就會生成
可以看出.config 檔案中都是以“CONFIG_”開始的配置項,這些配置項就是 Makefile 中的變量,是以後面都跟有相應的值,uboot 的頂層 Makefile 或子 Makefile 會調用這些變量值。在.config 中會有大量的變量值為‘y’,這些為‘y’的變量一般用于控制某項功能是否使能,為'y’的話就表示功能使能,比如:
2.屏蔽我們不要的檔案
在vscode中建立一個.vscode檔案夾
在裡面建立一個setting.json排除不需要的檔案
{
"search.exclude":
{
"**/*.o":true,
"**/*.su":true,
"**/*.cmd":true,
"arch/arc":true,
"arch/avr32":true,
"arch/blackfin":true,
"arch/m68k":true,
"arch/microblaze":true,
"arch/mips":true,
"arch/nds32":true,
"arch/nios2":true,
"arch/openrisc":true,
"arch/powerpc":true,
"arch/sandbox":true,
"arch/sh":true,
"arch/sparc":true,
"arch/x86":true,
"arch/arm/mach*":true,
"arch/arm/cpu/arm11*":true,
"arch/arm/cpu/arm720t":true,
"arch/arm/cpu/arm9*":true,
"arch/arm/cpu/armv7m":true,
"arch/arm/cpu/armv8":true,
"arch/arm/cpu/pxa":true,
"arch/arm/cpu/sa1100":true,
"board/[a-e]*":true,
"board/[g-z]*":true,
"board/[0-9]*":true,
"board/[A-Z]*":true,
"board/fir*":true,
"board/freescale/b*":true,
"board/freescale/l*":true,
"board/freescale/m5*":true,
"board/freescale/mp*":true,
"board/freescale/c29*":true,
"board/freescale/cor*":true,
"board/freescale/mx7*":true,
"board/freescale/mx2*":true,
"board/freescale/mx3*":true,
"board/freescale/mx5*":true,
"board/freescale/p*":true,
"board/freescale/q*":true,
"board/freescale/t*":true,
"board/freescale/v*":true,
"configs/[a-l]*":true,
"configs/[n-z]*":true,
"configs/[A-Z]*":true,
"configs/M[a-z]*":true,
"configs/M[A-Z]*":true,
"configs/M[0-9]*":true,
"configs/m[a-w]*":true,
"configs/m[0-9]*":true,
"configs/[0-9]*":true,
"include/configs/[a-l]*":true,
"include/configs/[n-z]*":true,
"include/configs/[A-Z]*":true,
"include/configs/m[a-w]*":true,
},
"files.exclude":
{
"**/*.o":true,
"**/*.su":true,
"**/*.cmd":true,
"arch/arc":true,
"arch/avr32":true,
"arch/blackfin":true,
"arch/m68k":true,
"arch/microblaze":true,
"arch/mips":true,
"arch/nds32":true,
"arch/nios2":true,
"arch/openrisc":true,
"arch/powerpc":true,
"arch/sandbox":true,
"arch/sh":true,
"arch/sparc":true,
"arch/x86":true,
"arch/arm/mach*":true,
"arch/arm/cpu/arm11*":true,
"arch/arm/cpu/arm720t":true,
"arch/arm/cpu/arm9*":true,
"arch/arm/cpu/armv7m":true,
"arch/arm/cpu/armv8":true,
"arch/arm/cpu/pxa":true,
"arch/arm/cpu/sa1100":true,
"board/[a-e]*":true,
"board/[g-z]*":true,
"board/[0-9]*":true,
"board/[A-Z]*":true,
"board/fir*":true,
"board/freescale/b*":true,
"board/freescale/l*":true,
"board/freescale/m5*":true,
"board/freescale/mp*":true,
"board/freescale/c29*":true,
"board/freescale/cor*":true,
"board/freescale/mx7*":true,
"board/freescale/mx2*":true,
"board/freescale/mx3*":true,
"board/freescale/mx5*":true,
"board/freescale/p*":true,
"board/freescale/q*":true,
"board/freescale/t*":true,
"board/freescale/v*":true,
"configs/[a-l]*":true,
"configs/[n-z]*":true,
"configs/[A-Z]*":true,
"configs/M[a-z]*":true,
"configs/M[A-Z]*":true,
"configs/M[0-9]*":true,
"configs/m[a-w]*":true,
"configs/m[0-9]*":true,
"configs/[0-9]*":true,
"include/configs/[a-l]*":true,
"include/configs/[n-z]*":true,
"include/configs/[A-Z]*":true,
"include/configs/m[a-w]*":true,
}
}
其中"search.exclude"裡面是需要在搜尋結果中排除的檔案或者檔案夾,"files.exclude"是左側工程目錄中需要排除的檔案或者檔案夾。我們需要将 arch/avr32 檔案夾下的所有檔案從搜尋結果和左側的工程目錄中都排除掉,是以在"search.exclude"和"files.exclude"中輸入
3.Makefile分析(我真的看的爆炸)
3.1 版本号
3.2 MakeFlags變量
make 是支援遞歸調用的,也就是在 Makefile 中使用“make”指令來執行其他的 Makefile檔案,一般都是子目錄中的 Makefile 檔案。假如在目前目錄下存在一個“subdir”子目錄,這個子目錄中又有其對應的 Makefile 檔案,那麼這個工程在編譯的時候其主目錄中的 Makefile 就可以調用子目錄中的 Makefile,以此來完成所有子目錄的編譯。主目錄的 Makefile 可以使用如下代碼來編譯這個子目錄:
$(MAKE) -C subdir
subdir就是子目錄,有時候需要将變量導入子目錄,export就是導入,unxeport就是不導入,需要注意的是,“SHELL”和“MAKEFLAGS”,這兩個變量除非使用“unexport”聲明,否則的話在整個make的執行過程中,它們的值始終自動的傳遞給子make
3.3 指令輸出
uboot 預設編譯是不會在終端中顯示完整的指令,都是短指令
在終端中輸出短指令雖然看起來很清爽,但是不利于分析 uboot 的編譯過程。可以通過設定變量“V=1“來實作完整的指令輸出
在Makefile檔案中有許多下面的
$(Q)$(MAKE) $(build)=tool
如果V = 0, Q=@,就不會在中斷輸出指令了;否則就會輸出指令
3.4 靜默輸出
由上一節可知,如果V=1就輸出很多指令,如果V不等于0就會短指令輸出,有時候不需要輸出指令,這時候就是靜默輸出。make -s也可以實作。
3.5 設定編譯結果輸出目錄
3.6 代碼檢查
make C=1使能代碼檢查,C=2是全部檔案檢查
3.7 子產品編譯
在 uboot 中允許單獨編譯某個子產品,使用指令“make M=dir”即可,舊文法“make SUBDIRS=dir”也是支援的。頂層 Makefile 中的代碼如下:
3.8 擷取主機架構和系統
從圖 31.3.8.1 可以看出目前電腦主機架構為“x86_64”,shell 中的“|”表示管道,意思是将左邊的輸出作為右邊的輸入,sed -e 是替換指令,“sed -e s/i.86/x86/”表示将管道輸入的字元串中的“i.86”替換為“x86”,其他的“sed -s”指令同理。對于我的電腦而言,HOSTARCH=x86_64。
可以看出此時的主機 OS 為“Linux”,使用管道将“Linux”作為後面“tr '[:upper:]'
'[:lower:]'”的輸入,“tr '[:upper:]' '[:lower:]'”表示将所有的大寫字母替換為小寫字母,是以得到“linux”。最後同樣使用管道,将“linux”作為“sed -e's/(cygwin)./cygwin/'”的輸入,用于将cygwin.替換為 cygwin。是以,HOSTOS=linux。
3.9 設定目标架構、交叉編譯器和配置檔案
3.10 調用Script/Kbuild
主 Makefile 會調用檔案 scripts/Kbuild.include 這個檔案
3.11 交叉編譯工具變臉設定
3.12 導出其他變量
ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR
這 7 個變量在頂層 Makefile 是找不到的,說明這 7 個變量是在其他檔案裡面定義的,先來
看一下這 7 個變量都是什麼内容
在 uboot 根目錄下有個檔案叫做 config.mk,這 7 個變量就是在 config.mk 裡面定義的
接下來需要找到 CONFIG_SYS_ARCH、CONFIG_SYS_CPU、CONFIG_SYS_BOARD、CONFIG_SYS_VENDOR 和 CONFIG_SYS_SOC 這 5 個變量的值。這 5 個變量在 uboot 根目錄下的.config 檔案中有定義,定義如下:
3.13 make xxx_deconfig過程
在編譯 uboot 之前要使用“make xxx_defconfig”指令來配置 uboot
version_h := include/generated/version_autogenerated.h
timestamp_h := include/generated/timestamp_autogenerated.h
no-dot-config-targets := clean clobber mrproper distclean \
help %docs check% coccicheck \
ubootversion backup
config-targets := 0
mixed-targets := 0
dot-config := 1
ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
dot-config := 0
endif
endif
ifeq ($(KBUILD_EXTMOD),)
ifneq ($(filter config %config,$(MAKECMDGOALS)),)
config-targets := 1
ifneq ($(words $(MAKECMDGOALS)),1)
mixed-targets := 1
endif
endif
endif
ifeq ($(mixed-targets),1)
# ===========================================================================
# We're called with mixed targets (*config and build targets).
# Handle them one by one.
PHONY += $(MAKECMDGOALS) __build_one_by_one
$(filter-out __build_one_by_one, $(MAKECMDGOALS)): __build_one_by_one
@:
__build_one_by_one:
$(Q)set -e; \
for i in $(MAKECMDGOALS); do \
$(MAKE) -f $(srctree)/Makefile $$i; \
done
else
ifeq ($(config-targets),1)
# ===========================================================================
# *config targets only - make sure prerequisites are updated, and descend
# in scripts/kconfig to make the *config target
KBUILD_DEFCONFIG := sandbox_defconfig
export KBUILD_DEFCONFIG KBUILD_KCONFIG
config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
else
# ===========================================================================
# Build targets only - this includes vmlinux, arch specific targets, clean
# targets and others. In general all targets except *config targets.
ifeq ($(dot-config),1)
# Read in config
-include include/config/auto.conf
定義了變量 no-dot-config-targets。
定義了變量 config-targets,初始值為 0。
定義了變量 mixed-targets,初始值為 0。
# ===========================================================================
# Rules shared between *config targets and build targets
# Basic helpers built in scripts/
PHONY += scripts_basic
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;
PHONY += outputmakefile
# outputmakefile generates a Makefile in the output directory, if using a
# separate output directory. This allows convenient use of make in the
# output directory.
outputmakefile:
ifneq ($(KBUILD_SRC),) #經過剛才的判斷,KBUILD_SRC為空,是以不會執行下面的語句
$(Q)ln -fsn $(srctree) source
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
$(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif
3.14 makefile.build腳本分析
是在“scripts/basic”中查找符合“tpl/%”的部分,然後将“tpl/”取消掉,但是“scripts/basic”沒有“tpl/”,是以 src= scripts/basic。
第 12 行和第 9 行一樣,隻是這裡處理的是“spl”,“scripts/basic”裡面也沒有“spl/”,是以src 繼續為 scripts/basic。 第 15 行因為變量 obj 和 src 相等,是以 prefix=.。
3.15 make過程
ifeq ($(CONFIG_OF_SEPARATE),y)
u-boot-dtb.bin: u-boot-nodtb.bin dts/dt.dtb FORCE
$(call if_changed,cat)
u-boot.bin: u-boot-dtb.bin FORCE
$(call if_changed,copy)
else
u-boot.bin: u-boot-nodtb.bin FORCE
$(call if_changed,copy)
endif