解析一遍,然后才是根据“目标-依赖”关系来建立目标。
这里的$(CURDIR)是 Makefile 自己的环境变量,它等于当前目录,展开即为:
srctree=/home/work/u-boot-2014.04
objtree=/home/work/u-boot-2014.04
src=/home/work/u-boot-2014.04
obj=/home/work/u-boot-2014.04
VPATH=/home/work/u-boot-2014.04
MKCONFIG=/home/work/u-boot-2014.04/mkconfig
接下来得到宿主机架构和宿主机系统:
HOSTARCH=x86
HOSTOS=linux
这里定义了编译过程中要使用到的一些编译、链接工具,我们需要指定 CROSS_COMPILE 为
arm-linux- ,可以直接修改 Makefile,或者在编译时通过命令行指定:
root@zjh:/home/work/u-boot-2014.04# make all CROSS_COMPILE=arm-linux-
这里决定了我们执行 make smdkc100_config 和 make all 在 Makefile 中的走向。 用到了 Makefile 的函
数 filter 和 filter-out,不清楚的可以查看《GNU make 中文手册》。 MAKECMDGOALS 是 Makefile 的变量,
它保存了我们执行 make 时所带的命令行参数。
当我们执行 make smdkc100_config 时, $(filter config %config,$(MAKECMDGOALS))会返回字符串
smdkc100,不为空, 因此得到 config-targets := 1
当我们执行 make all 时, 这里没有一项匹配的,最终得到:
config-targets = 0
mixed-targets = 0
dot-config = 1
接下来有几个 if……else ifeq……endif 分支:
ifeq ($(mixed-targets),1)
……
else
ifeq ($(config-targets),1)
当执行 make smdkc100_config 时将进入到这个分支
……
else
当执行 make all 时将进入这个分支
……
endif #ifeq ($(config-targets),1)
endif #ifeq ($(mixed-targets),1)
下面分析执行 make all 时进入的那个分支
首先包含头文件 include/config.mk, include/config.mk 在 5.2 节有说明
包含指令 include 前面的 - 表示当包含的文件不存在时, make 不输出任何信息,也不退出。
第 478 行,如果不存在 include/config.mk,则输出错误信息,如果没有配置,就不存在这个文件:
这里从相关目录取出链接脚本文件,然后赋给变量 LDSCRIPT
这里导出变量 CONFIG_SYS_TEXT_BASE, 表示代码段的基地址,在单板配置文件 smdkc100.h 中定义
下面定义了一些目标:
head-y := $(CPUDIR)/start.o
head-$(CONFIG_4xx) += arch/powerpc/cpu/ppc4xx/resetvec.o
head-$(CONFIG_MPC85xx) += arch/powerpc/cpu/mpc85xx/resetvec.o
HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makefile),y,n)
libs-y += lib/
libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
libs-y += $(CPUDIR)/
ifdef SOC
libs-y += $(CPUDIR)/$(SOC)/
endif
libs-$(CONFIG_OF_EMBED) += dts/
libs-y += arch/$(ARCH)/lib/
libs-y += fs/
libs-y += net/
libs-y += disk/
libs-y += drivers/
……
u-boot-init := $(head-y)
u-boot-main := $(libs-y)
# Always append ALL so that arch config.mk's can add custom ones
ALL-y += u-boot.srec u-boot.bin System.map
ALL-$(CONFIG_NAND_U_BOOT) += u-boot-nand.bin
ALL-$(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin
ALL-$(CONFIG_RAMBOOT_PBL) += u-boot.pbl
ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin
ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.img
ALL-$(CONFIG_TPL) += tpl/u-boot-tpl.bin
ALL-$(CONFIG_OF_SEPARATE) += u-boot.dtb u-boot-dtb.bin
ALL-$(CONFIG_OF_HOSTFILE) += u-boot.dtb
ifneq ($(CONFIG_SPL_TARGET),)
ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
上面这些 CONFIG_都没有配置,所有最终$(ALL-y)展开为
u-boot.srec u-boot.bin System.map
我们分析了那么久,终于找到目标 all 了,它依赖于$(ALL-y), $(ALL-y)会被展开为多个目标,然后
make 会找到每个目标,根据每个目标的依赖关系进行编译。 我们最终需要得到 u-boot.bin
从这得知 u-boot 依赖于$(u-boot-init) $(u-boot-main) u-boot.lds
$(u-boot-init) 展开为: arch/arm/cpu/armv7/start.o
$(u-boot-main) 展开为: $(libs-y), $(libs-y)展开为各个目录下的相关库。
这里依赖的链接脚本为: arch/arm/cpu/u-boot.lds
这里根据.h 头文件生成被所有 Makefile 包含的 autoconf.mk
gcc 通过使用 –M –dM 可以输出输入文件中的所有宏和 gcc 自己的宏, 这里把输出的宏保存到一个
临时文件,然后交给 sed 处理, sed 根据一个脚本 define2mk.sed 定义的规则把这些宏输出到 autoconf.mk,
下面是 define2mk.sed 的内容:
define2mk.sed 只处理以 CONFIG_ 为前缀的宏,看下 include/autoconf.mk 的内容就能明白它的处理
规则。