天天看點

uboot頂層Makefile

1. 工作目錄

uboot頂層Makefile

如上圖代碼,編譯之後将解壓包放到windows解壓觀看。

目錄如下:

檔案夾:

uboot頂層Makefile
uboot頂層Makefile

檔案:

uboot頂層Makefile

1.1 arch

這裡面存放着和架構有關的檔案

uboot頂層Makefile

我們用的是arm架構的檔案,打開arm檔案夾:

uboot頂層Makefile

其中mach開頭的是和裝置有關的檔案,比如exynos是和三星有關的,我們使用的是imx-common,是以要使用這個檔案夾,cpu也是和CPU有關的檔案,打開之後:

uboot頂層Makefile

我們使用的開發闆是armv7的,u-boot.lds就是連結檔案。

1.2 board

board檔案夾裡面的檔案是和闆子有關的,我們打開裡面的飛思卡爾的檔案夾

uboot頂層Makefile

evk字尾是正點原子在這個基礎上開發的,移植uboot的時候要參考這個檔案夾

1.3 config

此檔案夾為 uboot 配置檔案,uboot 是可配置的,但是你要是自己從頭開始一個一個項目的配置,那就太麻煩了,是以一般半導體或者開發闆廠商都會制作好一個配置檔案。我們可以在這個做好的配置檔案基礎上來添加自己想要的功能,這些半導體廠商或者開發闆廠商制作好的配置檔案統一命名為“xxx_defconfig”,xxx 表示開發闆名字,這些 defconfig 檔案都存放在configs檔案夾,是以,NXP 官方開發闆和正點原子的開發闆配置檔案肯定也在這個檔案夾中,

uboot頂層Makefile

我們使用的mx6ull_14x14_ddr512_emmc_deconfig

在編譯uboot之前一定要用這個配置檔案

uboot頂層Makefile

1.4 u_boot.xxx.cmd檔案

uboot頂層Makefile

這些檔案都是編譯生成的,是一些指令檔案

.u-boot.bin.cmd
uboot頂層Makefile

裡面定義了一個變量叫cmd_u-boot.bin 拷貝了u-boot-nodtb.bin一份改成u-boot.bin

那我們就看u-boot-nodtb.bin

u-boot-nodtb.bin.cmd
uboot頂層Makefile

使用arm-linux-gnueabihf-objcopy将elf檔案轉化為bin檔案

那就是u-boot.elf 變成u-boot-nodtb.bin

u-boot.cmd

注意和上面的bin.cmd分開,這個是生成elf的,是以猜測是連結檔案

uboot頂層Makefile

輸出是u-boot, 後面也可以不用加elf,和最開始交叉編譯的聯系起來

還有一個是用來燒寫用的,把bin變成imx檔案,就是.u-boot.imx.cmd

uboot頂層Makefile

1.5 u-boot.xxx

uboot頂層Makefile

1.6 .config檔案

配置檔案,在上面有一個make mx6ull_14x14_ddr512_emmc_deconfig就會生成

可以看出.config 檔案中都是以“CONFIG_”開始的配置項,這些配置項就是 Makefile 中的變量,是以後面都跟有相應的值,uboot 的頂層 Makefile 或子 Makefile 會調用這些變量值。在.config 中會有大量的變量值為‘y’,這些為‘y’的變量一般用于控制某項功能是否使能,為'y’的話就表示功能使能,比如:

uboot頂層Makefile

2.屏蔽我們不要的檔案

在vscode中建立一個.vscode檔案夾

uboot頂層Makefile

在裡面建立一個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 版本号

uboot頂層Makefile

3.2 MakeFlags變量

make 是支援遞歸調用的,也就是在 Makefile 中使用“make”指令來執行其他的 Makefile檔案,一般都是子目錄中的 Makefile 檔案。假如在目前目錄下存在一個“subdir”子目錄,這個子目錄中又有其對應的 Makefile 檔案,那麼這個工程在編譯的時候其主目錄中的 Makefile 就可以調用子目錄中的 Makefile,以此來完成所有子目錄的編譯。主目錄的 Makefile 可以使用如下代碼來編譯這個子目錄:

$(MAKE) -C subdir

subdir就是子目錄,有時候需要将變量導入子目錄,export就是導入,unxeport就是不導入,需要注意的是,“SHELL”和“MAKEFLAGS”,這兩個變量除非使用“unexport”聲明,否則的話在整個make的執行過程中,它們的值始終自動的傳遞給子make

uboot頂層Makefile

3.3 指令輸出

uboot 預設編譯是不會在終端中顯示完整的指令,都是短指令

uboot頂層Makefile

在終端中輸出短指令雖然看起來很清爽,但是不利于分析 uboot 的編譯過程。可以通過設定變量“V=1“來實作完整的指令輸出

uboot頂層Makefile

在Makefile檔案中有許多下面的

$(Q)$(MAKE) $(build)=tool

如果V = 0, Q=@,就不會在中斷輸出指令了;否則就會輸出指令

uboot頂層Makefile

3.4 靜默輸出

由上一節可知,如果V=1就輸出很多指令,如果V不等于0就會短指令輸出,有時候不需要輸出指令,這時候就是靜默輸出。make -s也可以實作。

uboot頂層Makefile

3.5 設定編譯結果輸出目錄

uboot頂層Makefile
uboot頂層Makefile

3.6 代碼檢查

make C=1使能代碼檢查,C=2是全部檔案檢查

3.7 子產品編譯

在 uboot 中允許單獨編譯某個子產品,使用指令“make M=dir”即可,舊文法“make SUBDIRS=dir”也是支援的。頂層 Makefile 中的代碼如下:

uboot頂層Makefile
uboot頂層Makefile

3.8 擷取主機架構和系統

uboot頂層Makefile

從圖 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 設定目标架構、交叉編譯器和配置檔案

uboot頂層Makefile
uboot頂層Makefile
uboot頂層Makefile

3.10 調用Script/Kbuild

主 Makefile 會調用檔案 scripts/Kbuild.include 這個檔案

3.11 交叉編譯工具變臉設定

uboot頂層Makefile

3.12 導出其他變量

uboot頂層Makefile

ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR

這 7 個變量在頂層 Makefile 是找不到的,說明這 7 個變量是在其他檔案裡面定義的,先來

看一下這 7 個變量都是什麼内容

uboot頂層Makefile

在 uboot 根目錄下有個檔案叫做 config.mk,這 7 個變量就是在 config.mk 裡面定義的

uboot頂層Makefile
uboot頂層Makefile
uboot頂層Makefile

接下來需要找到 CONFIG_SYS_ARCH、CONFIG_SYS_CPU、CONFIG_SYS_BOARD、CONFIG_SYS_VENDOR 和 CONFIG_SYS_SOC 這 5 個變量的值。這 5 個變量在 uboot 根目錄下的.config 檔案中有定義,定義如下:

uboot頂層Makefile

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      
uboot頂層Makefile
uboot頂層Makefile

定義了變量 no-dot-config-targets。

定義了變量 config-targets,初始值為 0。

定義了變量 mixed-targets,初始值為 0。

uboot頂層Makefile
uboot頂層Makefile
uboot頂層Makefile
# ===========================================================================
# 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      
uboot頂層Makefile
uboot頂層Makefile
uboot頂層Makefile

3.14 makefile.build腳本分析

uboot頂層Makefile

是在“scripts/basic”中查找符合“tpl/%”的部分,然後将“tpl/”取消掉,但是“scripts/basic”沒有“tpl/”,是以 src= scripts/basic。

第 12 行和第 9 行一樣,隻是這裡處理的是“spl”,“scripts/basic”裡面也沒有“spl/”,是以src 繼續為 scripts/basic。 第 15 行因為變量 obj 和 src 相等,是以 prefix=.。

uboot頂層Makefile
uboot頂層Makefile
uboot頂層Makefile
uboot頂層Makefile
uboot頂層Makefile
uboot頂層Makefile
uboot頂層Makefile

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      

繼續閱讀