U-BOOT中Makefile分析

 from: 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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值