http://blog.chinaunix.net/u2/72383/showart_1083225.html
分析了一下u-boot1.3.2的Makefile,基本的结构如下:
主目录下有一个Makefile,一个config.mk,一个mkconfig脚本。
(一) 首先用户需要make
smdk2410_config,这样Makefile会掉用mkconfig脚本生成include/config.mk这里面包含了
ARCH,BOARD,CPU,SOC等变量,这些变量可以供其它的makefile使用,作为一个基本配置.
如果还没有掉用make
smdk2410_config,那么include/config.mk是不存在的,这样当make
all的时候,会出错,因为Makefile里会依据该文件是否存在给all目标提供不同的规则和命令,当存在include/config.mk时,是
一些正常的规则,当不存在的时候,是出错提示。
mkconfig脚本的作用不仅仅是生成include/config.mk文件,他还依据用户是否指定目标文件夹来创建目录,将生成的文件放到非源码的目录。此外还生成一个include/config.h文件,这个文件很简单,只有一句话:
#include <$1.h> 当然这里的$1时要被替换成不同的board名字的.这个取决于我们在主Makefile中xxxx_config目标中的xxxx是什么. 这里可以以smdk2410.h为例子.
(二)在源码目录(而非include)还有一个自带的config.mk,一般每个子目录中
的Makefile都要包含这个config.mk,因为这个config.mk里面定义了一些变量,这些变量对这些子目录的Makefile是有意义
的,如$obj, $src等都定义了子目录的目标文件和源码路径,这些是依据CURDIR变量来推算的,因为子目录一般都是由父目录掉用make
-C过来的,当进入子目录开始make后,CURDIR自动就成为了当前的working
dir,因此就可以推算出当前子目录的路径。当然这个config.mk还有别的内容.包括:
将不同CPU,BOARD目录下的原有的config.mk包含进来。
还有一个很重要的内容:
CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
这个定义就制定了在编译的时候告诉编译器生成的代码的基地址是TEXT_BASE,参看u-boot的relocation部分的资料。当然在连接的时候也需要指定这个值。即在连接参数里指定TEXT_BASE:
LDFLAGS += -Ttext $(TEXT_BASE)
此外,还指定了连接脚本 -T $(LDSCRIPT)
最后这个文件中包含一些规则,将.S转换成.s的规则。由.S生成.o,由.c生成.o
(三)include/autoconf.mk的作用.
它依赖于include/config.h文件,因此要首先make
xxxx_config,以生成include/config.h。此外由于include/autoconf.mk的生成是通过将include
/common.h中的带CONFIG_的宏筛选出来得到的,此外还生成了一个依赖文件,且这个依赖文件也是依据common.h生成的,这个依赖的目标
就是include/autoconf.mk,其第一个prerequsite就是include/common.h。而,common.h中
include了config.h,这样可知include/autoconf.mk实际上依赖于config.h以及common.h中的依赖。
下面是Makefie中的一段节选:
# Auto-generate the autoconf.mk file (which is included by all makefiles)
# 因为autoconf.mk中包含了用户自己定义在common.h中的一些宏
# 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. 之所以说可以告诉我们when to regenerate
# the autoconf.mk file,是因为在autoconf.mk文件中包含autoconf.mk: common.h
# 这样的依赖,一旦common.h改变了,autoconf.mk就的改变
# -M的意思是说生成dependency文件.
# -MQ是用来指定生成的dependency文件中的target是什么,如不指定,模认为xxxx.o
# 即 gcc -M inlcude/common.h >$@.dep 生成的结果为:
# include/common.o : ... 即自动以.o为target,这不是我们想要的,我们想要
# autoconfig.mk作为target,因此要-MQ来手动指定,而且,include/common.h会自动
# 作为一个prequisite.
# 结果,common.h的依赖的所有的文件,包括common.h都被写入include/autoconf.mk.dep
# 文件。这样include/autoconf.mk依赖于common.h以及common.h中的一些依赖,而接下来
# 的一些要被编译的target有全都依赖于include/autoconf.mk,因此,一旦common.h有所
# 修改,全部都的重新编译.
# $(CPP) -dM file 会将file中使用的宏全部输出到标准输出.并且将预处理器的预定义
# 宏也输出了. 因此这里有了一个查看于处理器自定义的宏的方法:
# touch foo.h; cpp -dM foo.h,因为foo.h是个空文件,因此输出的都是预定义宏.
# sed -n是quiet模式,sed使用tools/define2mk.sed脚本来处理输出的宏.将宏处理成
# 了一种适合make处理的autoconf的格式.而且只提取出了common.h中的#define CONFIG_XXX模式的宏,即用户在common.h中自己定义的宏.
$(obj)include/autoconf.mk: $(obj)include/config.h $(VERSION_FILE)
@$(XECHO) Generating include/autoconf.mk ; \
set -e ; \
: Generate the dependancies ; \
$(CC) -M $(HOST_CFLAGS) $(CPPFLAGS) -MQ $@ include/common.h > $@.dep ; \
: Extract the config macros ; \
$(CPP) $(CFLAGS) -dM include/common.h | sed -n -f tools/scripts/define2mk.sed > $@
# 将由common.h生成的依赖规则包含进来,sinclude,就算没有该文件,也不会出错.
sinclude $(obj)include/autoconf.mk.dep
其它的规则总将include/autoconf.mk作为一个prerequsite,这样一旦common.h或者config.h等有更新,整个工程都得重新生成.
(四)rules.mk的使用
在规则中,看到很多_depend,这个东西,其实是定义在rules.mk里面的,在各个makefile里面,包含了这个rules.mk,因此可以
通过make -C subdir _depend命令来生成位于各个subdir下的dependency文件,然后生成的文件有被包含进来。
这个u-boot的makefile里面还包含了许多有趣的命令,可以学习一下。
阅读(1488) | 评论(0) | 转发(0) |