转自:http://blog.csdn.net/boyskung/article/details/3211988
这里主要涉及到如下几个文件:
主目录中的Makfile、mkconfig、config.mk以及各子目录中的Makefile。因为子目录中Makefile太多,所以本文中以lib_arm目录中的Makefile为例进行分析。首先大概介绍一下这几个文件。
主目录中的Makefile是对整个工程的编译链接规则进行了描述。
子目录中的Makfile主要是编译一些源文件并进行归档,生成一些静态库。
config.mk定义了主目录和子目录makefile通用的变量。
Mkconfig是个脚本文件,负责对主目录中makefile进行配置的文件。创建一些符号链接,并在include目录下创建了两个文件:config.mk和config.h。config.mk包含了uboot运行的环境,包括体系结构、处理器和板子。Config.h中指明了板子相关的配置头文件。
下面对源码进行分析
HOSTARCH := $(shell uname -m | /
sed -e s/i.86/i386/ /
-e s/sun4u/sparc64/ /
-e s/arm.*/arm/ /
-e s/sa110/arm/ /
-e s/powerpc/ppc/ /
-e s/macppc/ppc/)
HOSTOS := $(shell uname -s | tr A-Z a-z | /
sed -e 's//(cygwin/).*/cygwin/')
这里是输出两个变量:主机体系结构和主机所用操作系统。
TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
export TOPDIR
输出uboot所在的当前目录。
include include/config.mk
export ARCH CPU BOARD VENDOR
# load other configuration
include $(TOPDIR)/config.mk
加载包含一些变量的两个config.mk文件。Include/config.mk文件就是由mkconfig脚本文产生的。
ifeq ($(ARCH),arm)
CROSS_COMPILE = /opt/host/armv4l/bin/armv4l-unknown-linux-
Endif
export CROSS_COMPILE
根据上面输出的ARCH变量,初始化交叉编译器的变量,确定使用什么样的编译器,并输出这个变量。
OBJS = cpu/$(CPU)/start.o
ifeq ($(CPU),i386)
OBJS += cpu/$(CPU)/start16.o
OBJS += cpu/$(CPU)/reset.o
endif
ifeq ($(CPU),ppc4xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc85xx)
OBJS += cpu/$(CPU)/resetvec.o
Endif
对OBJS变量的赋值
LIBS = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += rtc/librtc.a
LIBS += dtt/libdtt.a
LIBS += drivers/libdrivers.a
LIBS += drivers/sk98lin/libsk98lin.a
LIBS += post/libpost.a post/cpu/libcpu.a
LIBS += common/libcommon.a
对LIBS变量的赋值
SUBDIRS = tools /
examples /
post /
post/cpu
子目录变量SUBDIRS的赋值
ALL = u-boot.srec u-boot.bin System.map
all: $(ALL)
这里all是我们make时遇到的第一个目标,其依赖分别为u-boot.srec u-boot.bin System.map
。
u-boot.srec: u-boot
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@
u-boot.bin: u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
cp -f u-boot.bin /tftpboot
System.map: u-boot
@$(NM) $< | /
grep -v '/(compiled/)/|/(/.o$$/)/|/( [aUw] /)/|/(/./.ng$$/)/|/(LASH[RL]DI/)' | /
sort > System.map
这是all的三个依赖的建立,当make时,就会产生这三个目标。而他们又都是以uboot为依赖,只是形成的建立不同。
u-boot: depend $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*/(__u_boot_cmd_.*/)/-u/1/p'|sort|uniq`;/
$(LD) $(LDFLAGS) $$UNDEF_SYM $(OBJS) /
--start-group $(LIBS) $(PLATFORM_LIBS) --end-group /
-Map u-boot.map -o u-boot
这就是uboot的建立,他的依赖又分别是depend $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)。
depend dep:
@for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir .depend ; done
这里循环进入变量SUBDIRS指定的子目录,执行make .depend命令。
$(SUBDIRS):
$(MAKE) -C $@ all
循环进入变量SUBDIRS指定的子目录,执行make all命令。
$(LIBS):
$(MAKE) -C `dirname $@`
进入LIBS变量指定文件所在的目录里,执行make命令。`dirname $@`从文件名中去除不是目录的后缀,如
dirname lib_$(ARCH)/lib_$(ARCH).a结果就是lib_$(ARCH)目录 。
$(LDSCRIPT)变量在顶层目录下的config.mk中定义,是链接脚本
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
$(LD) $(LDFLAGS) $$UNDEF_SYM $(OBJS) /
--start-group $(LIBS) $(PLATFORM_LIBS) --end-group /
最后由这个规则链接生成uboot文件
s3c2410_config : unconfig
@./mkconfig $(@:_config=) arm arm920t s3c2410
当执行make s3c2410_config来生成配置文件时,这个规则将被执行。它首执行依赖unconfig的规则:
unconfig:
rm -f include/config.h include/config.mk
这里强行删除上一次生成的配置文件。
然后执行脚本 mkconfig并传递相应参数
@./mkconfig $(@:_config=) arm arm920t s3c2410
$(@:_config=)获得目标板,即s3c2410_config中去掉”_config”的部分s3c2410. 后面的参数依次是体系结构、cpu和开发板名称。
下面就来分析一下mkconfig这个脚本文件
#!/bin/sh –e #指定运行SHELL的程序
#默认创建新的配置文件
APPEND=no # Default: Create new config file
# $#是输入参数的个数
while [ $# -gt 0 ] ; do #当参数个数大于0时
case "$1" in #检测第一个参数的值
--) shift ; break ;; #参数左移一个,然后退出
-a) shift ; APPEND=yes ;; #参数左移一个,设APPEND的值,
*) break ;; #不是以上的值就退出
esac
done
#参数个数小于4或大于5,退出
[ $# -lt 4 ] && exit 1
[ $# -gt 5 ] && exit 1
echo "Configuring for $1 board..."
#进入include目录
cd ./include
#
# Create link to architecture specific headers
#
#删除旧的链接,根据传递进来的参数,创建新的链接
rm -f asm
ln -s asm-$2 asm
rm -f asm-$2/arch
ln -s arch-$3 asm-$2/arch
#如果第二个参数即体系结构是arm
if [ "$2" = "arm" ] ; then
rm -f asm-$2/proc
ln -s proc-armv asm-$2/proc
fi
#
# Create include file for Make
#
echo "ARCH = $2" > config.mk #创建config.mk文件,并将ARCH变量添加到文件中
echo "CPU = $3" >> config.mk #将变量CPU添加到文件中
echo "BOARD = $4" >> config.mk #将变量BOARD添加到文件中
[ "$5" ] && echo "VENDOR = $5" >> config.mk #如果有第五个参数,也添加到文件中
#现在回想一下前面提到的makdfile文件中的一段代码
ifeq (include/config.mk,$(wildcard include/config.mk))
# load ARCH, BOARD, and CPU configuration
include include/config.mk
export ARCH CPU BOARD VENDOR
在这里就是引用刚才生成的config.mk中的各变量,
#
# Create board specific header file
#
#下面就是创建一个头文件include/config.h, 根据APPEND的值决定是否创建新的文件
if [ "$APPEND" = "yes" ] # Append to existing config file
then
echo >> config.h
else
> config.h # Create new config file
fi
#下面两行向config.h中添加内容
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/$1.h>" >>config.h #这里包含了板子相关的配置文件
#include/configs/s3c2410.h
exit 0
在前面的makefile的分析中,我们也看到LD、LDFLAGS这样的变量。这些变量在makefile中并没有定义。他是通过一个语句
# load other configuration
include $(TOPDIR)/config.mk
将含有这些变量的文件包含到当前makfile文件,看一下这个顶层目录下的config.mk中的内容:
# clean the slate ...
PLATFORM_RELFLAGS =
PLATFORM_CPPFLAGS =
PLATFORM_LDFLAGS =
#
# When cross-compiling on NetBSD, we have to define __PPC__ or else we
# will pick up a va_list declaration that is incompatible with the
# actual argument lists emitted by the compiler.
#
# [Tested on NetBSD/i386 1.5 + cross-powerpc-netbsd-1.3]
ifeq ($(ARCH),ppc)
ifeq ($(CROSS_COMPILE),powerpc-netbsd-)
PLATFORM_CPPFLAGS+= -D__PPC__
endif
ifeq ($(CROSS_COMPILE),powerpc-openbsd-)
PLATFORM_CPPFLAGS+= -D__PPC__
endif
endif
ifeq ($(ARCH),arm)
ifeq ($(CROSS_COMPILE),powerpc-netbsd-)
PLATFORM_CPPFLAGS+= -D__ARM__
endif
ifeq ($(CROSS_COMPILE),powerpc-openbsd-)
PLATFORM_CPPFLAGS+= -D__ARM__
endif
endif
ifdef ARCH
sinclude $(TOPDIR)/$(ARCH)_config.mk # include architecture dependend rules
endif
ifdef CPU
sinclude $(TOPDIR)/cpu/$(CPU)/config.mk # include CPU specific rules
endif
ifdef VENDOR
BOARDDIR = $(VENDOR)/$(BOARD)
else
BOARDDIR = $(BOARD)
endif
ifdef BOARD
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk # include board specific rules
endif
#########################################################################
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; /
else if [ -x /bin/bash ]; then echo /bin/bash; /
else echo sh; fi ; fi)
ifeq ($(HOSTOS)-$(HOSTARCH),darwin-ppc)
HOSTCC = cc
else
HOSTCC = gcc
endif
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
HOSTSTRIP = strip
#########################################################################
#
# Include the make variables (CC, etc...)
#
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB = $(CROSS_COMPILE)RANLIB
RELFLAGS= $(PLATFORM_RELFLAGS)
DBGFLAGS= -g #-DDEBUG
OPTFLAGS= -Os #-fomit-frame-pointer
ifndef LDSCRIPT
#LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
endif
OBJCFLAGS += --gap-fill=0xff
gccincdir := $(shell $(CC) -print-file-System.map。