makefile是个很复杂的东西,但是只要有耐心层层剥下,也能看到你想看到的东西。很遗憾的事,很多人都没有耐心去层层看,我也是。
对于makefile,我也仅仅从基础上了解了它在uboot中的原理和作用,其实你不一定要完全了解,但是你又不能完全不了解,这就是这个世界的矛盾。
makefile 第一步
最开始当然要看顶层目录下的makefile文件,当你执行make命令是就是默认这个makefile。一般在最开始,你需要告诉makefile你要生成哪种uboot,命令如下:
- make *****_config
- %_config:: unconfig
- @$(MKCONFIG) -A $(@:_config=)
- unconfig:
- @rm -f $(obj)include/config.h $(obj)include/config.mk \
- $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp \
- $(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep
- MKCONFIG := $(SRCTREE)/mkconfig
而@:_config=表示将你输入的******_config替换为******,也就是将后面的去掉,因此命令实际上就成了
- $(SRCTREE)/mkconfig -A ******
mkconfig的作用
有很多文章写mkconfig的过程,我就不乱讲了,我也讲不太清楚,或者只能简单讲清楚。
简单来说,mkconfig会根据你输入的参数,比如-A , ******(单板号)去查询根目录下的boards.cfg文件,这个文件很关键,比如内容如下:
- # Target ARCH CPU Board name Vendor SoC Options
- ###########################################################################################################
- integratorcp_cm1136 arm arm1136 integrator armltd - integratorcp:CM1136
- imx31_phycore arm arm1136 - - mx31
- imx31_phycore_eet arm arm1136 imx31_phycore - mx31 imx31_phycore:IMX31_PHYCORE_EET
- qong arm arm1136 - davedenx mx31
- mx31ads arm arm1136 - freescale mx31
- mx31pdk arm arm1136 - freescale mx31 mx31pdk:NAND_U_BOOT
- tt01 arm arm1136 - hale mx31
- imx31_litekit arm arm1136 - logicpd mx31
- flea3 arm arm1136 - CarMediaLab mx35
- mx35pdk arm arm1136 - freescale mx35
比如以tt01为例,当你输入make tt01_config的时候,mkconfig就会在borad.cfg里面找到这一行。
找到这一行之后,它的所有属性就出来了,比如你的ARCH=arm,CPU=arm1136等等,这些属性都会被mkconfig收集起来写入两个文件中,这两个文件就叫做include/config.mk和include/config.h
mkconfig中生成include/config.mk如下:
- 1 ARCH = arm
- 2 CPU = arm1136
- 3 BOARD = tt01
- 4 VENDOR = hale
- 5 SOC = mx31
- 1 /* Automatically generated - do not edit */
- 2 #define CONFIG_SYS_ARCH "arm"
- 3 #define CONFIG_SYS_CPU "arm1136"
- 4 #define CONFIG_SYS_BOARD "tt01"
- 5 #define CONFIG_SYS_VENDOR "hale"
- 6 #define CONFIG_SYS_SOC "mx31"
- 7 #define CONFIG_BOARDDIR board/hale/tt01
- 8 #include <config_cmd_defaults.h>
- 9 #include <config_defaults.h>
- 10 #include <configs/tt01.h>
- 11 #include <asm/config.h>
- 12 #include <config_fallbacks.h>
- 13 #include <config_uncmd_spl.h>
make的第二步
当make的第一步完成后,第二步就更简单了,直接输入make命令,然后就会按照你的预订配置编译了。
虽然操作简单了,但是实现过程更复杂了,如果要简单的说,那就是会执行All下面的所有操作
- all: $(ALL-y) $(SUBDIR_EXAMPLES)
- $(obj)u-boot.dtb: $(obj)u-boot
- $(MAKE) -C dts binary
- mv $(obj)dts/dt.dtb $@
- $(obj)u-boot-dtb.bin: $(obj)u-boot.bin $(obj)u-boot.dtb
- cat $^ >$@
- $(obj)u-boot.hex: $(obj)u-boot
- $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@
- $(obj)u-boot.srec: $(obj)u-boot
- $(OBJCOPY) -O srec $< $@
- $(obj)u-boot.bin: $(obj)u-boot
- $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
- $(BOARD_SIZE_CHECK)
- $(obj)u-boot.ldr: $(obj)u-boot
- $(CREATE_LDR_ENV)
- $(LDR) -T $(CONFIG_BFIN_CPU) -c $@ $< $(LDR_FLAGS)
- $(BOARD_SIZE_CHECK)
- $(obj)u-boot.ldr.hex: $(obj)u-boot.ldr
- $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ -I binary
- $(obj)u-boot.ldr.srec: $(obj)u-boot.ldr
- $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ -I binary
我这里没有列全,但是的确是从这里开始运行,直至生成所有应该生成的文件。
makefile与uboot目录的关系
uboot的目录是非常庞大的,包含各种单板各种架构,如何得知哪个架构,进入哪个目录编译,这是makefile必须清楚地。反而言之,用户如果要新增文件,应该怎么增加,应该如何修改makefile,也需要了解。
makefile的参数非常关键,也就是上面介绍的boards.cfg里面的参数。
ARCH=type,对应的源目录为 arch/arm
CPU=arm1136,对应的源目录为arch/arm/arm/cpu1136
SOC=mx31,对应的源目录为arch/arm/arm/cpu1136/mx32
这里对应了三个最关键的源目录路径,在arch/arm目录下有arm公有的东西,比如初始化之类的。在arch/arm/cpu/***目录下就是每个cpu自己的东西了,用户可以将cpu特定的一些函数写在这个目录下。arch/arm/arm/cpu1136/mx32就是当前Soc的特殊函数了,比如定时器,DDR初始化之类的。
VENDOR=hale,对应的头文件目录为board\hale,这里面定义了这个公司的所有头文件。
BOARD=tt01,对应的头文件目录为board\hale\tt01,这里面定义了这个单板的所有头文件。
综上所述,基本和单板相关的文件定义结构就清楚了,但是其他的一些定义,比如flash,net之类的,这些有公共部分,也有私有部分,这个与makefile就关系不大了,这部分以后再详述。