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 | \
首先执行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:]' | \
首先执行uname -s 查看开发平台的系统,结果为Linux,然后通过管道传送给tr命令,tr命令利用字符类[:lower:]和[:upper:]将Linux字符串转化为linux,然后再利用sed命令.最后的结果是HOSTOS=linux
export
这些变量传递给下一层的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
SRCTREE
TOPDIR
LNDIR
export
OPDIR SRCTREE OBJTREE这三个目录会给下层的makefile调用,需要在这里指定并export
OBJTREE和LNDIR为存放生成文件的目录,TOPDIR与SRCTREE为源码所在目录
MKCONFIG
export MKCONFIG
定义变量MKCONFIG:这个变量指向一个脚本,即顶层源码目录的mkconfig。
ifneq ($(OBJTREE),$(SRCTREE))
REMOTE_BUILD
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:
首先执行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
CPU
BOARD
VENDOR = samsung
SOC
生成include/config.h头文件,只有一行:
#include "config/smdk6410.h"
# load ARCH, BOARD, and CPU configuration
include $(OBJTREE)/include/config.mk
export
包含include/config.mk,导出ARCH CPU BOARD VENDOR SOC这五个变量
ifndef CROSS_COMPILE
ifeq ($(ARCH),arm)//ARCH
CROSS_COMPILE = arm-linux-
endif
endif
CROSS_COMPILE = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-
export
指定交叉编译器前缀,我只写出了与ARM相关的交叉编译前缀
/usr/local/arm/4.2.2-eabi/usr/bin/这个目录是安装交叉编译器的目录
# load other configuration
include $(TOPDIR)/config.mk
包含顶层目录下的config.mk,这个文件里面主要定义了交叉编译器及选项和编译规则
稍后分析顶层目录的config.mk
下面就是Uboot需要的目标文件和库文件,$(CPU)已经指定了CPU
与之相关的VENDOR = samsung
# U-Boot objects....order is important (i.e. start must be first)
OBJS
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
OBJS += cpu/$(CPU)/cplbhdlr.o
endif
OBJS := $(addprefix $(obj),$(OBJS))
addprefix为增加前缀函数
库文件,由各个目录下的makefile生成,链接时需要这些文件
这些文件涉及到的目录有lib_generic,board,cpu,lib_arm,fs,net,disk,rtc,dtt,drivers,post,common
将与平台相关的进行下面替换
$(ARCH)
$(CPU)
$(BOARD)
$(VENDOR) = samsung
$(SOC)
LIBS
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 \
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
.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:
$(obj)u-boot.hex:
$(obj)u-boot.srec:
$(obj)u-boot.bin:
$(obj)u-boot.img:
$(obj)u-boot.dis:
$(obj)u-boot:
$(OBJS):
$(LIBS):
$(SUBDIRS):
$(NAND_SPL):
$(U_BOOT_NAND):
version:
gdbtools:
updater:
env:
depend dep:
tags ctags:
etags:
$(obj)System.map:
下面接着分析
unconfig:
这句话已经分析过了,就是在mkconfig是先执行的操作,即删除上一次makeXXX时存在的头文件和包含文件
接下来很长一段是与平台和开发板相关的xxx_config定义,譬如在执行make smdk6410_config时
会找到如下定义:
smdk6410_config
最后是clean命令的定义
clean:
clobber:
ifeq ($(OBJTREE),$(SRCTREE))
mrproper \
distclean:
else
mrproper \
distclean:
endif
backup:
哈哈,终于结束了,下次再讲讲Uboot究竟是如何生成镜像文件的,任务好重啊,哈哈
原文地址 http://blog.sina.com.cn/s/blog_6bec9cbc0100xlub.html