00、通识
版本号
VERSION = 2016 //主版本号
PATCHLEVEL = 03 //补丁版本号
SUBLEVEL = //次版本号
EXTRAVERSION = //附加版本信息
NAME = //名字有关的,一般不使用这两个
MAKEFLAGS 变量
export VARIABLE //导出变量给子 make
unexport VARIABLE //不导出变量给子 make
MAKEFLAGS += -rR --include-dir=$(CURDIR)
MAKEFLAGS /SHELL 值始终自动的传递给子make 除非使用“unexport”声明
-rR : 表示禁止使用内置的隐含规则和变量定义
--include-dir : 指明搜索路径
$(CURDIR): 表示当前目录
编译选项
V=1 来实现完整的命令输出
O=out 指定输出目录
C = 1 使能代码检查
M=dir 单独编译某个模块
HOSTARCH 主机架构
HOSTOS 系统
ARCH 架构 //ARCH = arm
CROSS_COMPILE 交叉编译工具 //arm-linux-gnueabihf- (只到 “ - ”)
CC = $(CROSS_COMPILE)gcc //CC 为编译gcc的简短语法
常用变量
ARCH = arm
CPU = armv7
BOARD = mx6ullevk
VENDOR = freescale
SOC = mx6
CPUDIR = arch/arm/cpu/armv7
BOARDDIR = freescale/mx6ullevk
ARCH、CPU、BOARD、VENDOR、SOC、CPUDIR、BOARDDIR 等变量定义在 config.mk 文件:
config.mk:
ARCH := $(CONFIG_SYS_ARCH:"%"=%)
CPU := $(CONFIG_SYS_CPU:"%"=%) //"%"=% 取双引号里面的值
.....
= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值
01、清除过程
make distclean 或者 make mrproper
会调用顶层的Makefile的 distclean 规则。
02、配置工程,生成.config配置文件
make xxx_defconfig
会调用顶层的Makefile的 %config 规则。
%config 规则: %通配符,当输入“make xxx_defconfig”的时候就会匹配到%config 目标:
%config: scripts_basic outputmakefile FORCE
第一步:依赖部分
目标 %config 依赖于 scripts_basic、outputmakefile、FORCE
1、FORCE目标:
FORCE 在顶层 Makefile的 1610 行有如下定义:
PHONY += FORCE
FORCE:
FORCE 是没有规则和依赖的,所以每次都会重新生成 FORCE。当 FORCE 作为其他目标的依赖时,由于 FORCE 总是被更新过的,因此依赖所在的规则总是会执行的。即将FORCE当做依赖时,对应的目标规则总是会被执行。
2、scripts_basic目标:
目标不依赖其它目标,会执行以下规则命令:
$(Q)$(MAKE) $(build)=scripts/basic
其中:
Q是显示方式:静默make -s;详细make V=1;不显示make V=0
MAKE=make
build定义在scripts\kbuild.include
build := -f $(srctree)/scripts/Makefile.build obj
展开后:
build := -f ./scripts/Makefile.build obj
展开后:
@make -f ./scripts/Makefile.build obj=scripts/basic
@rm -f .tmp_quiet_recordmcount
最终会调用文件./scripts/Makefile.build
3、outputmakefile目标:
可以通过echo查看KBUILD_SRC为空
mytest:
@echo KBUILD_SRC = $(KBUILD_SRC)
所以该目标规则没有执行如何命令。
第二步:命令部分
目标 %config 依赖于 scripts_basic、outputmakefile、FORCE ,执行以下命令:
$(Q)$(MAKE) $(build)=scripts/kconfig $@
展开:
make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
也跟文件./scripts/Makefile.build 有关
第三步:Makefile.build
上面的分析最后指向以下两条命令:
make -f ./scripts/Makefile.build obj=scripts/basic
make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
1、 scripts_basic 目标对应的命令:
make -f ./scripts/Makefile.build obj=scripts/basic
打开文件 scripts/Makefile.build,有如下代码:
# Modified for U-Boot
prefix := tpl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
prefix := spl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
prefix := .
endif
endif
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)
使用@echo打印各个变量值,结果如下:
src= scripts/basic
kbuild-dir = ./scripts/basic
kbuild-file = ./scripts/basic/Makefile
include ./scripts/basic/Makefile
其中src的值即为obj=scripts/basic的值。
make执行时未指定目标,会执行Makefile.build中的默认目标,如下:
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
$(subdir-ym) $(always)
@:
其中KBUILD_BUILTIN = 1、KBUILD_MODULES = 0,展开后即为:
__build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
@:
五个变量中除去 $(always) 其他都为空 , $(always) = scripts/basic/fixdep,因此需要先编译 scripts/basic/fixdep.c生成fixdep这个软件,Makefile.build包含了scripts/basic/目录下的Makefile:
include ./scripts/basic/Makefile
2、 %config 目标对应的命令:
make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
src的值即为obj=scripts/basic的值,所以Makefile.build中各个变量值如下:
src= scripts/kconfig
kbuild-dir = ./scripts/kconfig
kbuild-file = ./scripts/kconfig/Makefile
include ./scripts/kconfig/Makefile
include包含了./scripts/kconfig目录下的Makefile,执行make时会调用scripts/kconfig/ Makefile中的内容,此文件有如下所示内容:
%_defconfig: $(obj)/conf
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
# Added for U-Boot (backward compatibility)
%_config: %_defconfig
@:
目标%_defconfig 刚好和我们输入的 xxx_defconfig 匹配,依赖为$(obj)/conf,展开后就是 scripts/kconfig/conf。接下来就是检查并生成依赖scripts/kconfig/conf。
得到 scripts/kconfig/conf 以后就要执行目标%_defconfig 的命令:
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
将其展开就是:
@ scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig
结果是将配置输出到.config 文件中,最终生成 uboot 根目录下的.config 文件。
整体流程图:
参考正点原子linux驱动开发指南,使用conf程序去生成.config;另一种旧版使用mkconfig 去生成config.mk 、config.h。
03.make 生成 u-boot.bin 等文件
make //编译u-boot,未指定目标将执行Makefile中默认目标
没有指明目标,使用默认的目标。
如果 KBUILD_EXTMOD(编译模块) 为空的话 _all 依赖于all:
all: $(ALL-y)
其中all依赖于ALL-y,即依赖于 u-boot.srec、u-boot.bin、u-boot.sym等:
u-boot.bin 依赖 u-boot-nodtb.bin、FORCE目标:
u-boot-nodtb.bin 依赖 u-boot、FORCE目标:
u-boot 依赖 \((u-boot-init)、\)(u-boot-main)、u-boot.lds、FORCE目标:
即u-boot 依赖 \((head-y)、\)(libs-y) :
u-boot 依赖 $(head-y):
head-y在 arch/arm/Makefile 定义,即 u-boot 依赖 start.o :
head-y := arch/arm/cpu/$(CPU)/start.o
u-boot 依赖 $(libs-y):
libs-y 在顶层 Makefile 中定义,为依赖的源码文件目录:
u-boot 依赖 $(head-y),即依赖 $(patsubst %/, %/built-in.o, $(libs-y)) :
$(patsubst <pattern>,<replacement>,<text>)
名称:模式字符串替换函数
功能:查找 <text> 中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式
<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符 % ,
表示任意长度的字串。如果 <replacement> 中也包含 % ,那么,<replacement>中的这
个 % 将是 <pattern> 中的那个 % 所代表的字串。(可以用 \ 来转义,以 \% 来表示真实含义的 % 字符)
返回:函数返回被替换过后的字符串。
表示 u-boot 依赖 libs-y 所指定的所有源码路径下的 built-in.o 文件
结论
u-boot 依赖 start.o、 built-in.o 文件,u-boot 将 built-in.o、start.o 文件链接在一起
04.链接
u-boot.lds 为链接脚本,将 arch/arm/cpu/armv7/start.o 和各个子目录下的 built-in.o 链接在一起生成 u-boot。
05.备注
make xxx_defconfig:用于配置 uboot,这个命令最主要的目的就是生成.config 文件。
make:用于编译 uboot,这个命令的主要工作就是生成二进制的 u-boot.bin 文件和其他的一些与 uboot 有关的文件,比如 u-boot.imx 等。