uboot的编译开始是从别处拿来代码,里面涉及到一些相关路径和我本地不一样,不知道怎么做。
后来知道先make distclean;
uboot里的 include/autoconf.mk.dep是编译配置生成的。
Uboot需要先make XXX_config,其中XXX,见uboot下boards.cfg
然后才能make u-boot。
有篇文章讲了些:http://hhming8283.blog.163.com/blog/static/77687239201482622613712/
这个得解释一下了。首先%_config是一个模式匹配目标,也就是以_config结尾的所有目标都符合这个处理规则。那am335x_boneblack_config自然也符合了。这里还用了make中的双冒号(::)规则,那就来了解一下双冒号规则。
首先需要明确的是:Makefile中,一个目标可以出现在多个规则中。但是这些规则必须是同一类型的规则,要么都是普通规则,要么都是双冒号规则。而不允许一个目标同时出现在两种不同类型的规则中。双冒号规则和普通规则的处理的不同点表现在以
下几个方面:
1. 双冒号规则中,当依赖文件比目标更新时。规则将会被执行。对于一个没有依赖而只有命令行的双冒号规则,当引用此目标时,规则的命令将会被无条件执行。而普通规则,当规则的目标文件存在时,此规则的命令永远不会被执行(目标文件永远是最新的)。
2. 当同一个文件作为多个双冒号规则的目标时。这些不同的规则会被独立的处理,而不是像普通规则那样合并所有的依赖到一个目标文件。这就意味着对这些规则的处理就像多个不同的普通规则一样。就是说多个双冒号规则中的每一个的依赖文件被改变之后,make只执行此规则定义的命令,而其它的以这个文件作为目标的双冒号规则将不会被执行。
这里为什么要用::规则没整明白,知道的留个言,不胜感激。
依赖unconfig目标将被重建,他也是一个伪目标,目的就是删除上次编译产生的配置文件。然后%_config将被重新make,命令行@$(MKCONFIG) -A $(@:_config=)被执行。其中,由于MKCONFIG := $(SRCTREE)/mkconfig SRCTREE就是uboot的顶层目录,所以$(MKCONFIG)被变量替换成mkconfig,$(@:_config=)是字符串替换,就是将目标字符串am335x_boneblack_config中的_config替换成空。然后调用命令mkconfig -A am335x_boneblack。mkconfig是一个shell脚本,最终的目的只用一个,根据boards.cfg文件里与am335x_boneblack匹配的board行所提供的参数Target Architecture CPU Board [VENDOR] [SOC]来产生一个config.h和config.mk。config.h是uboot源码的顶层配置头文件,它包括了对uboot产生影响的所有配置选项(至少我现在这么认为)。这个配置文件包含的内容如下:
/* Automatically generated - do not edit */
#define CONFIG_SERIAL1 1
#define CONFIG_CONS_INDEX 1
#define CONFIG_EMMC_BOOT 1
#define CONFIG_SYS_ARCH "arm"
#define CONFIG_SYS_CPU "armv7"
#define CONFIG_SYS_BOARD "am335x"
#define CONFIG_SYS_VENDOR "ti"
#define CONFIG_SYS_SOC "am33xx"
#define CONFIG_BOARDDIR board/ti/am335x
#include <config_cmd_defaults.h>
#include <config_defaults.h>
#include <configs/am335x_evm.h>
#include <asm/config.h>
#include <config_fallbacks.h>
#include <config_uncmd_spl.h>
这里面值得关注的是包含了几个头文件,这几个头文件都是在<u-boot_root>/include目录下的头文件,并不存在于am335x_boneblack/include目录下。
config.mk为make提供了几个变量,并根据boards.cfg中匹配行所提供的参数为这几个变量赋值,后面make将会用到的。
ARCH = arm
CPU = armv7
BOARD = am335x
VENDOR = ti
SOC = am33xx
这样,am335x_boneblack_config目标已经被重建,结果只是生成了两个配置文件,即<u-boot_root>/ am335x_boneblack/include/config和<u-boot_root>/ am335x_boneblack/include/config.mk。紧接着回头去看规则am335x_boneblack: am335x_boneblack_config; $(MAKE),发现规则的命令是一个make命令,好了,还得第三次make。这次make即没有目标,也没有参数。但是,这次是继前一次make的递归执行,make会将那些已经初始化的环境变量(在执行make之前已经存在的环境变量)和使用命令行指定的变量(如命令“make CFLAGS +=-g”或者“make–e CFLAGS +=-g”)还有使用export声明的变量传递给子make程序。所有的变量已经在上一层make中得到了赋值,而且当前的make依然在当前的路径下执行,Makefile依然是上一层make使用的。但是这一次由于文件<u-boot_root>/am335x_boneblack/include/config.mk的存在,是整个Makefile的执行完全发生了变化。此时,make会读取并执行ifeq ($(obj)include/config.mk, $(wildcard $(obj)include/config.mk))与#####################################################################
else # !config.mk之间的内容了。
首先就是读取makefile文件嘛,然后试图去重建所读取的makefile文件。
Reading makefiles...
Reading makefile `Makefile'...
Reading makefile `/opt/u-boot/am335x_boneblack/include/autoconf.mk.dep' (search path) (don't care) (no ~ expansion)...
Reading makefile `/opt/u-boot/am335x_boneblack/include/autoconf.mk' (search path) (don't care) (no ~ expansion)...
Reading makefile `/opt/u-boot/am335x_boneblack/include/config.mk' (search path) (no ~ expansion)...
Reading makefile `/opt/u-boot/config.mk' (search path) (no ~ expansion)...
Reading makefile `/opt/u-boot/am335x_boneblack/include/generated/cc_options.mk' (search path) (don't care) (no ~ expansion)...
Reading makefile `/opt/u-boot/am335x_boneblack/include/autoconf.mk' (search path) (don't care) (no ~ expansion)...
Reading makefile `/opt/u-boot/am335x_boneblack/include/config.mk' (search path) (don't care) (no ~ expansion)...
Reading makefile `/opt/u-boot/arch/arm/config.mk' (search path) (don't care) (no ~ expansion)...
Reading makefile `/opt/u-boot/arch/arm/cpu/armv7/config.mk' (search path) (don't care) (no ~ expansion)...
Reading makefile `/opt/u-boot/arch/arm/cpu/armv7/am33xx/config.mk' (search path) (don't care) (no ~ expansion)...
Reading makefile `/opt/u-boot/board/ti/am335x/config.mk' (search path) (don't care) (no ~ expansion)...
Reading makefile `/opt/u-boot/am335x_boneblack/.boards.depend' (search path) (don't care) (no ~ expansion)...
make[1]: Entering directory `/opt/u-boot'
Generating /opt/u-boot/am335x_boneblack/include/autoconf.mk
Generating /opt/u-boot/am335x_boneblack/include/autoconf.mk.dep
make[1]: Leaving directory `/opt/u-boot'
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
这次读取的makefile文件很多,其中有两个makefile文件am335x_boneblack/include/autoconf.mk和am335x_boneblack/include/autoconf.mk.dep是不存在的,由于包含两个头文件用的是sinclude所以make没有报错。但是Makefile里是有关于这两文件的显示的中间规则的,所以,make读取完所有的makefile文件后重新创建了这两个文件。
包含这两个文件已经说明了包含这两个文件的原因:
# Include autoconf.mk before config.mk so that the config options are available
# to all top level build files. We need the dummy all: target to prevent the
# dependency target in autoconf.mk.dep from being the default.
all:
sinclude $(obj)include/autoconf.mk.dep
sinclude $(obj)include/autoconf.mk
创建规则:
#
# Auto-generate the autoconf.mk file (which is included by all makefiles)
#
# This target actually generates 2 files; autoconf.mk and autoconf.mk.dep.
# the dep file is only include in this top level makefile to determine when
# to regenerate the autoconf.mk file.
$(obj)include/autoconf.mk.dep: $(obj)include/config.h include/common.h
@$(XECHO) Generating $@ ; \
set -e ; \
: Generate the dependancies ; \
$(CC) -x c -DDO_DEPS_ONLY -M $(CFLAGS) $(CPPFLAGS) \
-MQ $(obj)include/autoconf.mk include/common.h > $@
$(obj)include/autoconf.mk: $(obj)include/config.h
@$(XECHO) Generating $@ ; \
set -e ; \
: Extract the config macros ; \
$(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \
sed -n -f tools/scripts/define2mk.sed > $@.tmp && \
mv $@.tmp $@
后面还会有两个makefile文件会被创建,但是他们并不是通过include或者sinclude包含进来的。他们的创建方法大致相同,这里就不再一一介绍了。回到make的执行流程中来吧,重建完这两个makefile文件后,make会再一次的重新读取所有的makefile。这一次make认为所有的makefile文件都已经是最新的了,所以就可以执行终极目标的命令行了。终极目标是什么?还是得从Makefile上看。此时你会发现Makefile的第一个目标是all:,是个伪目标,而且依赖和命令行都是空的,为什么?再往后面看你会发现后面还有一个伪目标all:而且是有依赖的。
all: $(ALL-y) $(SUBDIR_EXAMPLES)
那make会这么处理这个伪目标all呢?all是第一个出现在Makefile中的目标,所以all会被make最为终极目标,这无可争议。伪目标all出现两次,make会将最后一次读取的all的依赖和规则的命令行覆盖前面的。如果没有第一个all,会怎么样呢?看一下autoconf.mk.dep里面的内容你就知道了,里面第一行就是一个目标,然后后面有n多个依赖的头文件。如果不加这个all,那么它里面这个规则的目标将会成为make的终极目标,显然这并不是我们的初衷。
好了,伪目标all的依赖便是make的终极目标,就是要最终要编译的uboot。需要编译的多少跟你之前的配置有关系。后面都是在使用我们之前写好的配置文件。那说了这么多,到底都有哪些配置文件呢?
首先就必须有boards.cfg,我们首先必须将我们的板子的相关参数填写到这里面来。根据boards.cfg生成了一个config.h的配置文件。这个文件里直接或者间接的包含了所有的配置头文件。
#include <config_cmd_defaults.h>
#include <config_defaults.h>
#include <configs/am335x_evm.h>
#include <asm/config.h>
#include <config_fallbacks.h>
#include <config_uncmd_spl.h>
其中红色的头文件是在boards.cfg的options域里面的<board config name>同名的配置文件。详细的参数配置都在这个头文件里了。有可能<board config name>.h中还会包含其他的头文件,那是你自己组织的原因了,跟uboot本身无关。
另外捎带说一下,关于这个board name并不是随便自己定义的。如果你想自己定义也没问题,make会根据你的定义到相关目录下去找关于这个板子的初始化程序。在config里会看到这一行#define CONFIG_BOARDDIR board/ti/am335x尽到这个文件夹里去看下你就知道了。