uboot1.1.6顶层makefile详解

 

VERSION = 1//主版本号
PATCHLEVEL = 1//次版本号
SUBLEVEL = 6//修正版本号
EXTRAVERSION =//版本号扩展
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)//这个Uboot的版本为1.1.6
VERSION_FILE = $(obj)include/version_autogenerated.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/)
首先执行uname -m得到I686,通过管道传送给sed命令,然后sed命令将执行sed -e s/i.86/i386/,将I686替换成i386,最后的结果是HOSTARCH=i386.
I686 表示Ubuntu, sed命令是替换命令

HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
     sed -e 's/\(cygwin\).*/cygwin/')
首先执行uname -s 查看开发平台的系统,结果为Linux,然后通过管道传送给tr命令,tr命令利用字符类[:lower:]和[:upper:]将Linux字符串转化为linux,然后再利用sed命令.最后的结果是HOSTOS=linux

export HOSTARCH HOSTOS
这些变量传递给下一层的Makefile

Uboot支持将目标文件生成在外部的文件夹中,有两种命令可以实现。
1,加入O=命令
2,设定环境变量BUILD_DIR
如果以上两种方式都没有定义,那么它将会被存放在源码目录下
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
上面的意思是如果定义了O命令,并且O=指定的目录和command line指定的目录一样
BUILD_DIR就为O=定义的目录
origin函数不像其它的函数,他并不操作变量的值,只是告诉你这个变量从哪里来

ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
再判断BUILD_DIR是否为0,若不为0,则save-output即保存BUILD_DIR指定的输出目录

# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
build_dir是不是一个目录 ,如果没有就创建, [ ] 就是个条件判断语句

BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
先打开这个目录,再调用Pwd显示当前路径,在将这个路径值赋给BUILD_DIR
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
endif # ifneq ($(BUILD_DIR),)
如果BUILD_DIR还不存在的话,则输出saved-output中的目录does not exist


OBJTREE  := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE  := $(CURDIR)
TOPDIR  := $(SRCTREE)
LNDIR  := $(OBJTREE)
export TOPDIR SRCTREE OBJTREE
OPDIR SRCTREE OBJTREE这三个目录会给下层的makefile调用,需要在这里指定并export
OBJTREE和LNDIR为存放生成文件的目录,TOPDIR与SRCTREE为源码所在目录

MKCONFIG := $(SRCTREE)/mkconfig
export MKCONFIG
定义变量MKCONFIG:这个变量指向一个脚本,即顶层源码目录的mkconfig。

ifneq ($(OBJTREE),$(SRCTREE))
REMOTE_BUILD := 1
export REMOTE_BUILD
endif
如果输出目录与源码目录不等,则设定REMOTE_BUILD项,并导出

ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src
如果输出目录OBJTREE与SRCTREE即当前的Uboot目录不等的话,对obj和src进行赋值,否则则obj,src为空。
obj src会在主目录中的config.mk定义,但在主makefile包含config.mk之前也需要,譬如unconfig, clean, clobber, distclean

ifeq ($(OBJTREE)/include/config.mk,$(wildcard $(OBJTREE)/include/config.mk))
在分析这个及以下命令之前,我们需要了解在在编译U-BOOT之前,先要执行# make smdk6410_config
smdk6410_config是Makefile的一个目标,定义如下:
smdk6410_config : unconfig
 @$(MKCONFIG) $(@:_config=) arm s3c64xx smdk6410 samsung s3c6410
unconfig:
 @rm -f $(obj)include/config.h $(obj)include/config.mk \
  $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp
首先执行unconfig,obj src为上面所定义的,这个命令清理上一次执行make *_config时生成的头文件和makefile的包含文件。主要是include/config.h 和include/config.mk文件。

然后再执行@$(MKCONFIG) $(@:_config=) arm s3c64xx smdk6410 samsung s3c6410
MKCONFIG 是顶层目录下的mkcofig脚本文件,后面五个是传入的参数。顶层目录下的mkcofig稍后分析
主要生成生成Makefile包含文件include/config.mk,用五个传入的参数定义五个变量
ARCH   = arm
CPU    = s3c64xx
BOARD  = smdk6410
VENDOR = samsung
SOC    = s3c6410

生成include/config.h头文件,只有一行:
#include "config/smdk6410.h"


# load ARCH, BOARD, and CPU configuration
include $(OBJTREE)/include/config.mk
export ARCH CPU BOARD VENDOR SOC
包含include/config.mk,导出ARCH CPU BOARD VENDOR SOC这五个变量

ifndef CROSS_COMPILE
ifeq ($(ARCH),arm)//ARCH   = arm
CROSS_COMPILE = arm-linux-
endif
endif

CROSS_COMPILE = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-
export CROSS_COMPILE

指定交叉编译器前缀,我只写出了与ARM相关的交叉编译前缀
/usr/local/arm/4.2.2-eabi/usr/bin/这个目录是安装交叉编译器的目录

# load other configuration
include $(TOPDIR)/config.mk
包含顶层目录下的config.mk,这个文件里面主要定义了交叉编译器及选项和编译规则
稍后分析顶层目录的config.mk

下面就是Uboot需要的目标文件和库文件,$(CPU)已经指定了CPU    = s3c64xx
与之相关的VENDOR = samsung

# U-Boot objects....order is important (i.e. start must be first)

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
ifeq ($(CPU),mpc86xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),bf533)
OBJS += cpu/$(CPU)/start1.o cpu/$(CPU)/interrupt.o cpu/$(CPU)/cache.o
OBJS += cpu/$(CPU)/cplbhdlr.o cpu/$(CPU)/cplbmgr.o cpu/$(CPU)/flush.o
endif

OBJS := $(addprefix $(obj),$(OBJS))
addprefix为增加前缀函数

库文件,由各个目录下的makefile生成,链接时需要这些文件
这些文件涉及到的目录有lib_generic,board,cpu,lib_arm,fs,net,disk,rtc,dtt,drivers,post,common
将与平台相关的进行下面替换
$(ARCH)   = arm
$(CPU)    = s3c64xx
$(BOARD)  = smdk6410
$(VENDOR) = samsung
$(SOC)    = s3c6410

LIBS  = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
BOARDDIR好像为VENDOR = samsung
LIBS += cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \
 fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += rtc/librtc.a
LIBS += dtt/libdtt.a
LIBS += drivers/libdrivers.a
LIBS += drivers/nand/libnand.a
LIBS += drivers/nand_legacy/libnand_legacy.a
# add to support onenand. by scsuh
LIBS += drivers/onenand/libonenand.a
ifeq ($(CPU),mpc83xx)
LIBS += drivers/qe/qe.a
endif
LIBS += drivers/sk98lin/libsk98lin.a
LIBS += post/libpost.a post/cpu/libcpu.a
LIBS += common/libcommon.a
LIBS += $(BOARDLIBS)

LIBS := $(addprefix $(obj),$(LIBS))
.PHONY : $(LIBS)


加入GCC的库,CC和CFLAGS都是make的隐含变量,CC表示C编译器,cflags表示执行CC时的命令行参数
# Add GCC lib
PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc


# The "tools" are needed early, so put this first
# Don't include stuff already done in $(LIBS)
SUBDIRS = tools \
   examples \
   post \
   post/cpu
.PHONY : $(SUBDIRS)
.PHONY是什么伪目标,不是很懂

ifeq ($(CONFIG_NAND_U_BOOT),y)
NAND_SPL = nand_spl
U_BOOT_NAND = $(obj)u-boot-nand.bin
endif

__OBJS := $(subst $(obj),,$(OBJS))
__LIBS := $(subst $(obj),,$(LIBS))
$(subst text, to, from)字符串替换函数,将$(obj)中的$(OBJS)置空

下面最终生成各种镜像文件
ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)
最后要生成的文件,U_BOOT_NAND在前面定义了,为u-boot-nand.bin

all依赖于$(ALL) 最终生成镜像文件,注意各种依赖关系
all:  $(ALL)

$(obj)u-boot.hex: $(obj)u-boot
  $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@

$(obj)u-boot.srec: $(obj)u-boot
  $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@

$(obj)u-boot.bin: $(obj)u-boot
  $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
  $(OBJDUMP) -d $< > $<.dis

$(obj)u-boot.img: $(obj)u-boot.bin
  ./tools/mkimage -A $(ARCH) -T firmware -C none \
  -a $(TEXT_BASE) -e 0 \
  -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
   sed -e 's/"[  ]*$$/ for $(BOARD) board"/') \
  -d $< $@

$(obj)u-boot.dis: $(obj)u-boot
  $(OBJDUMP) -d $< > $@

$(obj)u-boot:  depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
  UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed  -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
  cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
   --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
   -Map u-boot.map -o u-boot

$(OBJS):
  $(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))

$(LIBS):
  $(MAKE) -C $(dir $(subst $(obj),,$@))

$(SUBDIRS):
  $(MAKE) -C $@ all

$(NAND_SPL): version
  $(MAKE) -C nand_spl/board/$(BOARDDIR) all

$(U_BOOT_NAND): $(NAND_SPL) $(obj)u-boot.bin
  cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin

version:
  @echo -n "#define U_BOOT_VERSION \"U-Boot " > $(VERSION_FILE); \
  echo -n "$(U_BOOT_VERSION)" >> $(VERSION_FILE); \
  echo -n $(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion \
    $(TOPDIR)) >> $(VERSION_FILE); \
  echo "\"" >> $(VERSION_FILE)

gdbtools:
  $(MAKE) -C tools/gdb all || exit 1

updater:
  $(MAKE) -C tools/updater all || exit 1

env:
  $(MAKE) -C tools/env all || exit 1

depend dep:
  for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; done

tags ctags:
  ctags -w -o $(OBJTREE)/ctags `find $(SUBDIRS) include \
    lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) \
    fs/cramfs fs/fat fs/fdos fs/jffs2 \
    net disk rtc dtt drivers drivers/sk98lin common \
   \( -name CVS -prune \) -o \( -name '*.[ch]' -print \)`

etags:
  etags -a -o $(OBJTREE)/etags `find $(SUBDIRS) include \
    lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) \
    fs/cramfs fs/fat fs/fdos fs/jffs2 \
    net disk rtc dtt drivers drivers/sk98lin common \
   \( -name CVS -prune \) -o \( -name '*.[ch]' -print \)`

$(obj)System.map: $(obj)u-boot
  @$(NM) $< | \
  grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \
  sort > $(obj)System.map
下面接着分析
unconfig:
 @rm -f $(obj)include/config.h $(obj)include/config.mk \
  $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp
这句话已经分析过了,就是在mkconfig是先执行的操作,即删除上一次makeXXX时存在的头文件和包含文件

接下来很长一段是与平台和开发板相关的xxx_config定义,譬如在执行make smdk6410_config时
会找到如下定义:
smdk6410_config : unconfig
 @$(MKCONFIG) $(@:_config=) arm s3c64xx smdk6410 samsung s3c6410

最后是clean命令的定义
clean:
 find $(OBJTREE) -type f \
  \( -name 'core' -o -name '*.bak' -o -name '*~' \
  -o -name '*~' -o -name '.depend*' \
  -o -name '*.o'  -o -name '*.a'  \) -print \
  | xargs rm -f
 rm -f u-boot*
 rm -f $(obj)examples/hello_world $(obj)examples/timer \
       $(obj)examples/eepro100_eeprom $(obj)examples/sched \
       $(obj)examples/mem_to_mem_idma2intr $(obj)examples/82559_eeprom \
       $(obj)examples/smc91111_eeprom $(obj)examples/interrupt \
       $(obj)examples/test_burst
 rm -f $(obj)tools/img2srec $(obj)tools/mkimage $(obj)tools/envcrc \
  $(obj)tools/gen_eth_addr
 rm -f $(obj)tools/mpc86x_clk $(obj)tools/ncb
 rm -f $(obj)tools/easylogo/easylogo $(obj)tools/bmp_logo
 rm -f $(obj)tools/gdb/astest $(obj)tools/gdb/gdbcont $(obj)tools/gdb/gdbsend
 rm -f $(obj)tools/env/fw_printenv $(obj)tools/env/fw_setenv
 rm -f $(obj)board/cray/L1/bootscript.c $(obj)board/cray/L1/bootscript.image
 rm -f $(obj)board/netstar/eeprom $(obj)board/netstar/crcek $(obj)board/netstar/crcit
 rm -f $(obj)board/netstar/*.srec $(obj)board/netstar/*.bin
 rm -f $(obj)board/trab/trab_fkt $(obj)board/voiceblue/eeprom
 rm -f $(obj)board/integratorap/u-boot.lds $(obj)board/integratorcp/u-boot.lds
 rm -f $(obj)include/bmp_logo.h
 rm -f $(obj)nand_spl/u-boot-spl $(obj)nand_spl/u-boot-spl.map

clobber: clean
 find $(OBJTREE) -type f \( -name .depend \
  -o -name '*.srec' -o -name '*.bin' -o -name u-boot.img \) \
  -print0 \
  | xargs -0 rm -f
 rm -f $(OBJS) $(obj)*.bak $(obj)ctags $(obj)etags $(obj)TAGS $(obj)include/version_autogenerated.h
 rm -fr $(obj)*.*~
 rm -f $(obj)u-boot $(obj)u-boot.map $(obj)u-boot.hex $(ALL)
 rm -f $(obj)tools/crc32.c $(obj)tools/environment.c $(obj)tools/env/crc32.c
 rm -f $(obj)tools/inca-swap-bytes $(obj)cpu/mpc824x/bedbug_603e.c
 rm -f $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm
 [ ! -d $(OBJTREE)/nand_spl ] || find $(obj)nand_spl -lname "*" -print | xargs rm -f

ifeq ($(OBJTREE),$(SRCTREE))
mrproper \
distclean: clobber unconfig
else
mrproper \
distclean: clobber unconfig
 rm -rf $(OBJTREE)/*
endif

backup:
 F=`basename $(TOPDIR)` ; cd .. ; \
 gtar --force-local -zcvf `date "+$$F-%Y-%m-%d-%T.tar.gz"` $$F

哈哈,终于结束了,下次再讲讲Uboot究竟是如何生成镜像文件的,任务好重啊,哈哈

 

转载http://www.cnblogs.com/winceARM/archive/2010/10/16/1853066.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值