本文以uboot_1.1.6 对应的CPU是S3C2440 为例

uboot_1.1.6 根目录下的主Makefile开头:

VERSION =
PATCHLEVEL =
SUBLEVEL =
EXTRAVERSION =
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h

1、uboot的版本号分3个级别:
   VERSION:       主板本号
  PATCHLEVEL:     次版本号
  SUBLEVEL:     再次版本号
  EXTRAVERSION:  额外的版本信息
  
2、Makefile中版本号最终生成了一个变量U_BOOT_VERSION,U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) 即:U_BOOT_VERSION = 1. 1.6
3、include/version_autogenerated.h文件是编译过程中执行make xxxx_config 后自动生成的一个文件,所以源目录中没有,但是编译过后的uboot中就有了。被include/version.h文件包含。

 在\u-boot-1.1.6_jz2440\u-boot-1.1.6\cpu\arm920 中的START.S中会包含#include <version.h>:

#include <config.h>
#include <version.h>

version.h代码如下:

#ifndef    __VERSION_H__
#define __VERSION_H__ #include "version_autogenerated.h" #endif /* __VERSION_H__ */
version_autogenerated.h中代码如下:就是包含了一个UBOOT 版本好的宏定义。
#define U_BOOT_VERSION "U-Boot 1.1.6"

下列代码主要是获取目前使用计算机的架构信息:

HOSTARCH := $(shell uname -m | \
sed -e s/i./i386/ \
-e s/sun4u/sparc64/ \
-e s/arm.*/arm/ \
-e s/sa110/arm/ \
-e s/powerpc/ppc/ \
-e s/macppc/ppc/)

$(shell uname -m)表示执行uname –m的shell命令,在本计算机的Ubuntu虚拟机中执行 uname -m命令,返回 x86_64:

book@www.100ask.org:/$ uname -m
x86_64

sed –e s/abc/def 的意思是寻找结果里面是否有’abc’字样,如果有,就用‘def’字样将其代替。所以整条语句的意思就是,取出uname –m的结果,并在其中寻找是否有i.86字样,如果有就用i386代替,是否有arm.*(*是通配符),如果有,就用arm代替……,

本台机的结果是x86-64所以还保持原样,没有用其他字符替换,所以HOSTARCH=x86-64。

HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
sed -e 's/\(cygwin\).*/cygwin/') export HOSTARCH HOSTOS

获取主机操作系统信息,执行结果是将Linux中的大写字母全部换成小写字母。

book@www.100ask.org:/$ uname -s | tr '[:upper:]' '[:lower:]' | \
> sed -e 's/\(cygwin\).*/cygwin/'
linux

然后通过export   输出HOSTARCH和HOSTOS变量

下列代码支持uboot编译出的工程文件是放在源文件夹下还是指定的外部文件夹:

#########################################################################
#
# U-boot build supports producing a object files to the separate external
# directory. Two use cases are supported:
#
# ) Add O= to the make command line
# 'make O=/tmp/build all'
#
# ) Set environement variable BUILD_DIR to point to the desired location
# 'export BUILD_DIR=/tmp/build'
# 'make'
#
# The second approach can also be used with a MAKEALL script
# 'export BUILD_DIR=/tmp/build'
# './MAKEALL'
#
# Command line 'O=' setting overrides BUILD_DIR environent variable.
#
# When none of the above methods is used the local build is performed and
# the object files are placed in the source directory.
#

有两种方式通过1、通过命令行方式输出目录 'make O=/tmp/build all' 输出到tmp/build 目录。2、通过设置环境变量的方式,设置BUILD_DIR=/tmp/build。 命令行的方式会覆盖环境变量的方式。如果没有采用上述两种方式将使用源文件路径作为编译对象的输出文件夹。

ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif

通过$(origin O)判断是否 O变量来源于命令行,如果make O=/tmp/build all ,则BUILD_DIR := /tmp/build。

ifneq ($(BUILD_DIR),)                                    //如果$(BUILD_DIR)不等于空
saved-output := $(BUILD_DIR)                  //saved-output := 等于BUILD_DIR的内容, # Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})  //-d是判断BUILD_DIR是否存在。倘若不存在就创建。mkdir的-p参数代表若路径中的BUILD_DIR不存在就创建 # Verify if it was successful.                //核查BUILD_DIR是否创建成功
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)     //尝试进入BUILD_DIR 文件夹,如果能正常进入则将文件路劲赋值给BUILD_DIR 。
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))//判断BUILD_DIR 是否为空,为空将打印错误信息。
endif # ifneq ($(BUILD_DIR),)

判断几个表示文件路径的全局变量的值,是指定的外部文件路径还是当前目录路径:

OBJTREE      := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) //如果BUILD_DIR不为空,OBJTREE := $(BUILD_DIR)否则就是当前目录$(CURDIR)
SRCTREE := $(CURDIR)   
TOPDIR := $(SRCTREE)
LNDIR := $(OBJTREE)
export   TOPDIR SRCTREE OBJTREE //输出几个全局变量
MKCONFIG    := $(SRCTREE)/mkconfig              //指定MKCONFIG等于当前目录下的mkconfig
export MKCONFIG                          //输出MKCONFIG

mkconfig文件位于uboot根目录下,我们在make uboot之前要先配置,mkconfig文件执行配置内容,关于mkconfig的分析将在另一篇文章中表述。

ifneq ($(OBJTREE),$(SRCTREE))   //OBJTREE 和SRCTREE不相等REMOTE_BUILD := 1
REMOTE_BUILD :=
export REMOTE_BUILD
endif
# $(obj) and (src) are defined in config.mk but here in main Makefile
# we also need them before config.mk is included which is the case for
# some targets like unconfig, clean, clobber, distclean, etc.

//obj和src的定义也出现在了顶层目录的config.mk中,但在此文件被包含进来以前

//如果想使用unconfig  clean, clobber, distclean,这些命令,需要将变量obj、src,提前包含进去。

ifneq ($(OBJTREE),$(SRCTREE)) //如果两个目录不相等
obj := $(OBJTREE)/
src := $(SRCTREE)/
else                //否则都为空
obj :=
src :=
endif
export obj src

加载配置命令make xxxx_config  后产生的 include/config.mk文件,

//config.mk主要是配置板级系统信息,用于uboot的make,config.mk如下:

ARCH = arm
CPU = arm920t
BOARD = 100ask24x0
SOC = s3c24x0

然后输出 ARCH CPU BOARD VENDOR SOC等变量。在执行make all之前,首先要执行make xxxx_config,执行mkconfig脚本,可以确定所用cpu的架构(ARCH)例如arm ,cpu的种类(CPU)例如arm920t,开发板(BOARD)例如smdk2410 ,soc(SOC)例如 s3c24x0,这些信息保存在mkconfig脚本生成的makefile包含文件include/config.mk中。include/config.mk会被包含进入顶层makefile中,根据这个文件所定义的变量值,从而确定用那些文件(依赖),例如lib_arm/,board/smdk2410,cpu/arm920t等等。这是一种大方向上的裁剪方式

ifeq ($(OBJTREE)/include/config.mk,$(wildcard $(OBJTREE)/include/config.mk))

# load ARCH, BOARD, and CPU configuration
include $(OBJTREE)/include/config.mk
export ARCH CPU BOARD VENDOR SOC

确定交叉编译工具链:

ifndef CROSS_COMPILE
ifeq ($(HOSTARCH),ppc)
CROSS_COMPILE =
else
ifeq ($(ARCH),ppc)
CROSS_COMPILE = powerpc-linux-
endif
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux- //$(ARCH) = arm 交叉编译工具链为arm-linux-
endif
............
export CROSS_COMPILE //输出交叉工具链

包含顶层目录的config.mk

# load other configuration
include $(TOPDIR)/config.mk

加载OBJS对象:

OBJS  = cpu/$(CPU)/start.o  //加载cpu文件夹下的arm920t/start.o

给OBJ加上前缀:

OBJS := $(addprefix $(obj),$(OBJS))//#将$(obj)做为前缀添加在$(OBJS)中每个文件的前面 $(addprefix prefix,names)参数prefix是前缀  将其添加在names(names代表文件名 之间用空格隔开)的前面

根据config.mk中的ARCH = arm CPU = arm920t   BOARD = 100ask24x0  SOC = s3c24x0   添加需要的库文件:

LIBS  = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
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
LIBS += drivers/usb/libusb.a
LIBS += drivers/sk98lin/libsk98lin.a
LIBS += common/libcommon.a
LIBS += $(BOARDLIBS)

给LIBS加上obj前缀,定义LIBS为伪目标,添加GCC库

LIBS := $(addprefix $(obj),$(LIBS))
.PHONY : $(LIBS)
# Add GCC lib #添加GCC库
PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc

伪目标SUBDIRS 用于执行tools、examples、post、post\cpu子目录下的make文件

# 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声明伪目

在执行make后的返回信息中可以看到此段代码的make过程,分别进入了tools、examples、post、post\cpu子目录下执行了该目录下的make文件:

for dir in tools examples post post/cpu ; do make -C $dir _depend ; done
make[]: Entering directory '/work/system/u-boot-1.1.6/tools'
make[]: Nothing to be done for '_depend'.
make[]: Leaving directory '/work/system/u-boot-1.1.6/tools'
make[]: Entering directory '/work/system/u-boot-1.1.6/examples'
make[]: Nothing to be done for '_depend'.
make[]: Leaving directory '/work/system/u-boot-1.1.6/examples'
make[]: Entering directory '/work/system/u-boot-1.1.6/post'
make[]: Nothing to be done for '_depend'.
make[]: Leaving directory '/work/system/u-boot-1.1.6/post'
make[]: Entering directory '/work/system/u-boot-1.1.6/post/cpu'
make[]: Nothing to be done for '_depend'.
make[]: Leaving directory '/work/system/u-boot-1.1.6/post/cpu'
make -C tools all
make[]: Entering directory '/work/system/u-boot-1.1.6/tools'
make[]: Leaving directory '/work/system/u-boot-1.1.6/tools'
make -C examples all
make[]: Entering directory '/work/system/u-boot-1.1.6/examples'
make[]: Nothing to be done for 'all'.
make[]: Leaving directory '/work/system/u-boot-1.1.6/examples'
make -C post all
make[]: Entering directory '/work/system/u-boot-1.1.6/post'
make[]: Nothing to be done for 'all'.
make[]: Leaving directory '/work/system/u-boot-1.1.6/post'
make -C post/cpu all
make[]: Entering directory '/work/system/u-boot-1.1.6/post/cpu'
make[]: Nothing to be done for 'all'.
make[]: Leaving directory '/work/system/u-boot-1.1.6/post/cpu'

若定义了CONFIG_NAND_U_BOOT,那么将总目标all中添加$(obj)u-boot-nand.bin,否则不添加

把$(obj)从$(OBJS)、$(LIBS)中删除 。  $(subst from,to,text)  在文本"text"中用"to"替换所有的"from"

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))

顶层Makefile的总目标all是一个伪目标,有几个分目标(目标文件)组成:(obj)u−boot.srec(obj)u−boot.srec(obj)u-boot.bin (obj)System.map(obj)System.map(U_BOOT_NAND)。

用户也可以添加其他目标,如(obj)u−boot.dis、(obj)u−boot.dis、(obj)u-boot.img、$(obj)u-boot.hex等等。由于是一个伪目标,所以只要输入命令make all,总会重建几个分目标。

ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)

在顶层目录的config.mk中:CROSS_COMPILE = arm-linux-

OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
......
OBJCFLAGS += --gap-fill=0xff
all:        $(ALL)

$(obj)u-boot.hex:    $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@
//arm-linux-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
$(obj)u-boot.srec: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@
//展开为arm-linux-objcopy--gap-fill=0xff -O binary u-boot u-boot.bin
//编译命令中的“-O binary”选项指定了输出的文件为二进制文件。而“--gap-fill=0xff”选项指定使用“0xff”填充段与段间的空闲区域。
//这条编译命令实现了ELF格式的U-Boot文件到BIN格式的转换。
$(obj)u-boot.bin: $(obj)u-boot            
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@

//uboot.img只是比uboot.bin多了个头,而这个头包括了如何/从哪里执行这个uboot.
//uboot.bin一般是按照具体地址烧写,而uboot.img则包含地址等信息,无需按照地址下载,所以这个也决定了uboot.bin适用于Norflash,而uboot.img更适合SD卡
$(obj)u-boot.img: $(obj)u-boot.bin
./tools/mkimage -A $(ARCH) -T firmware -C none \
-a $(TEXT_BASE) -e \ //加载代码运行地址
-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \ //将$(obj)include/version_autogenerated.h文件中的任意字符+U_BOOT_VERSION 替换成空 替换后是字符串"U-Boot 1.1.6"
sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
-d $< $@
//展开arm-linux-objdump -d uboot > uboot.dis 反汇编
$(obj)u-boot.dis: $(obj)u-boot
$(OBJDUMP) -d $< > $@

$(obj)u-boot.bin依赖于$(obj)u-boot ,$(obj)u-boot 又依赖于depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)

$(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

depend依赖:

depend dep:        //note:depend 和dep 是两个目标,执行的命令一样
for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; done

依次进入$(SUBDIRS) 表示的子目录tools、examples、post、post\cpu中,并执行make _depend命令,生成各个子目录的.depend文件,在.depend文件中列出每个目标文件的依赖文件。

//make 执行过程:

for dir in tools examples post post/cpu ; do make -C $dir _depend ; done

关于_depend,位于根目录下的rules.mk。.depend依赖于 $(src)Makefile   、  $(TOPDIR)/config.mk   、   $(SRCS),然后执行命令,将 $(SRCS)中各个源文件的依赖关系取出放入到.depend文件,
属于Makefile自动生成依赖的一种做法。

_depend:    $(obj).depend

$(obj).depend:    $(src)Makefile $(TOPDIR)/config.mk $(SRCS)
@rm -f $@
@for f in $(SRCS); do \
g=`basename $$f | sed -e 's/\(.*\)\.\w/\1.o/'`; \            //`basename`是在Makefile中使用shell命令,shell中的basename是去除掉文件前面的目录(路径)信息,
                                                 //比如/root/test.c变成test.c,sed -e 's/\(.*\)\.\w/\1.o/'是正则表达式用于匹配字符串和替换字符串
$(CC) -M $(HOST_CFLAGS) $(CPPFLAGS) -MQ $(obj)$$g $$f >> $@ ; \
done

关于sed -e 's/\(.*\)\.\w/\1.o/'

sed的替换命令,常见的是 s/正则表达搜索/替换为/

\(.*\)匹配任意字符,并且放在了捕获括号中,用来做后向引用的,\1 引用前面正则表达式中第一个捕获括号里面的内容
\.是一个点
\w用于匹配字母,数字或下划线字符;
作用:把文件扩展名的首个字符替换成o,比如lowlevel_init.s,被替换成lowlevel_init.o

关于$(CC) -M $(HOST_CFLAGS) $(CPPFLAGS) -MQ $(obj)$$g $$f >> $@ ;

首先忽略$(HOST_CFLAGS) ,$(CPPFLAGS)。 $(HOST_CFLAGS)没有找到定义应该为空。

gcc -M -MQ  $(obj)$$g $$f >> .depend  将g=`basename $$f | sed -e 's/\(.*\)\.\w/\1.o/'`; 转换好的.o文件和其他依赖文件($$f 即.s和.c)(如果有)一起追加到 .depend 中

最后一起包含进去

sinclude $(obj).depend

以 \u-boot-1.1.6\board\100ask24x0 目录下生成的依赖文件.depend为例子:

 lowlevel_init.o: lowlevel_init.S \
/work/system/u-boot-1.1./include/config.h \
/work/system/u-boot-1.1./include/configs/100ask24x0.h \
/work/system/u-boot-1.1./include/cmd_confdefs.h \
/work/system/u-boot-1.1./include/version.h \
/work/system/u-boot-1.1./include/version_autogenerated.h
100ask24x0.o: 100ask24x0.c /work/system/u-boot-1.1./include/common.h \
/work/system/u-boot-1.1./include/config.h \
/work/system/u-boot-1.1./include/configs/100ask24x0.h \
/work/system/u-boot-1.1./include/cmd_confdefs.h \
/work/system/u-boot-1.1./include/linux/bitops.h \
/work/system/u-boot-1.1./include/asm/bitops.h \
/work/system/u-boot-1.1./include/linux/types.h \
/work/system/u-boot-1.1./include/linux/config.h \
/work/system/u-boot-1.1./include/linux/posix_types.h \
/work/system/u-boot-1.1./include/linux/stddef.h \
/work/system/u-boot-1.1./include/asm/posix_types.h \
/work/system/u-boot-1.1./include/asm/types.h \
/work/system/u-boot-1.1./include/linux/string.h \
/work/system/u-boot-1.1./include/asm/string.h \
/work/system/u-boot-1.1./include/asm/ptrace.h \
/work/system/u-boot-1.1./include/asm/proc/ptrace.h \
/work/tools/gcc-3.4.-glibc-2.3./lib/gcc/arm-linux/3.4./include/stdarg.h \
/work/system/u-boot-1.1./include/part.h \
/work/system/u-boot-1.1./include/ide.h \
/work/system/u-boot-1.1./include/flash.h \
/work/system/u-boot-1.1./include/image.h \
/work/system/u-boot-1.1./include/asm/u-boot.h \
/work/system/u-boot-1.1./include/asm/global_data.h \
/work/system/u-boot-1.1./include/asm/mach-types.h \
/work/system/u-boot-1.1./include/asm/setup.h \
/work/system/u-boot-1.1./include/asm/u-boot-arm.h \
/work/system/u-boot-1.1./include/s3c2410.h \
/work/system/u-boot-1.1./include/s3c24x0.h
boot_init.o: boot_init.c /work/system/u-boot-1.1./include/common.h \
/work/system/u-boot-1.1./include/config.h \
/work/system/u-boot-1.1./include/configs/100ask24x0.h \
/work/system/u-boot-1.1./include/cmd_confdefs.h \
/work/system/u-boot-1.1./include/linux/bitops.h \
/work/system/u-boot-1.1./include/asm/bitops.h \
/work/system/u-boot-1.1./include/linux/types.h \
/work/system/u-boot-1.1./include/linux/config.h \
/work/system/u-boot-1.1./include/linux/posix_types.h \
/work/system/u-boot-1.1./include/linux/stddef.h \
/work/system/u-boot-1.1./include/asm/posix_types.h \
/work/system/u-boot-1.1./include/asm/types.h \
/work/system/u-boot-1.1./include/linux/string.h \
/work/system/u-boot-1.1./include/asm/string.h \
/work/system/u-boot-1.1./include/asm/ptrace.h \
/work/system/u-boot-1.1./include/asm/proc/ptrace.h \
/work/tools/gcc-3.4.-glibc-2.3./lib/gcc/arm-linux/3.4./include/stdarg.h \
/work/system/u-boot-1.1./include/part.h \
/work/system/u-boot-1.1./include/ide.h \
/work/system/u-boot-1.1./include/flash.h \
/work/system/u-boot-1.1./include/image.h \
/work/system/u-boot-1.1./include/asm/u-boot.h \
/work/system/u-boot-1.1./include/asm/global_data.h \
/work/system/u-boot-1.1./include/asm/mach-types.h \
/work/system/u-boot-1.1./include/asm/setup.h \
/work/system/u-boot-1.1./include/asm/u-boot-arm.h \
/work/system/u-boot-1.1./include/s3c2410.h \
/work/system/u-boot-1.1./include/s3c24x0.h

version

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)

$(SUBDIRS)依赖

# 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)

$(SUBDIRS)目标执行:进入所有目标文件夹执行makefile文件

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

LIBS依赖

LIBS  = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
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
LIBS += drivers/usb/libusb.a
LIBS += drivers/sk98lin/libsk98lin.a
LIBS += common/libcommon.a
LIBS += $(BOARDLIBS) LIBS := $(addprefix $(obj),$(LIBS))
.PHONY : $(LIBS)

LIBS执行命令:依次进入LIBS目标文件夹 执行makefile ,

$(dir NAMES…)取目录函数,

$(subst FROM,TO,TEXT)
函数名称:字符串替换函数—subst。
函数功能:把字串“TEXT”中的“FROM ”字符替换为“TO”。
返回值:替换后的新字符串

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

LDSCRIPT:

LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds    //board/100ask24x0/u-boot.lds

uboot 主Makefile 分析。的更多相关文章

  1. uboot主Makefile分析(t配置和编译过程详解)

    1.编译uboot前需要三次make make distcleanmake x210_sd_configmake -j4 make distclean为清楚dist文件. make x210_sd_c ...

  2. uboot主Makefile分析

    VERSION = 1 PATCHLEVEL = 3 SUBLEVEL = 4 EXTRAVERSION = U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(S ...

  3. uboot 主Makefile分析

    一. Makefile 配置 1.1. make xxx_config 1.1.1. 笔者实验时是make x210_sd_config a. x210_sd_config是Makefile下的一个目 ...

  4. uboot总结:uboot配置和启动过程1(主Makefile分析)

    说明:文件位置:在uboot的目录下,文件名为:Makefile 从文件的头部开始分析 1.24-29行,配置uboot的版本信息. VERSION = PATCHLEVEL = SUBLEVEL = ...

  5. TQ210 —— S5PV210 uboot顶层Makefile分析

    转自:http://blog.csdn.net/wqx521/article/details/52469759 # (C) Copyright 2000-2008 # Wolfgang Denk, D ...

  6. u-boot子目录Makefile分析

    一.概述 u-boot的子目录Makefile是整个Makefile体系的重要组成部分,决定了对应子目录的编译过程. 二.分析 以cpu/arm920t/Makefile为例进行说明 (1)首先,调用 ...

  7. u-boot顶层Makefile分析

    1.u-boot制作命令 make forlinx_nand_ram256_config: make all; 2.顶层mkconfig分析,参考 U-BOOT顶层目录mkconfig分析 mkcon ...

  8. uboot 顶层makefile细节分析

    uboot的源文件众多,学习庞然大物首先找到脊椎--顶层的makfile,逐一破解.但是,uboot的makefile同样是一个庞然大物,所以也要找到它的主线.倘若过分专注部分细节,很难做到把握全局, ...

  9. tiny210——uboot移植Makefile文章分析

    这东西已经写,我们没有时间发布,如今,终于有时间稍微长送记录汇总uboot学习过程.具体了.以后忘了也能够再温习回来嘛有些特殊字符显示得乱掉了 Makefile追踪技巧: 技巧1:能够先从编译目标開始 ...

随机推荐

  1. Android学习_7/25

     常用控件 Android控件使用规律:先定义id,再指定宽度和高度,然后适当加入一些控件特有的属性 1.         TextView 在界面上显示一段文本 2.         Button ...

  2. finally的一个妙用

    ●传统用法try-catch-finally大家都会用:try包裹可能抛出异常的代码:catch捕获异常并对其处理:finally做一些资源关闭等回收工作.简单明了一句话就能说清. 稍微进阶一些的,大 ...

  3. flask-数据库 进阶

    1. 级联操作 Cascade意为“级联操作”,就是在操作一个对象的同时,对相关的对象也执行某些操作.我们通过一个Post模型和Comment模型来演示级联操作,分别表示文章(帖子)和评论,两者为一对 ...

  4. ftp协议在linux上的配置

    第一步:安装 yum install -y vsftpd 第二步:启动ftp服务:vsftpd [root@localhost ~]# systemctl start vsftpd 第三步:查看启动状 ...

  5. js对象之间的"继承"的五种方法

    今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有一个"动物"对象的构造函数. function Animal(){ this.species = & ...

  6. Java Jsch SFTP 递归下载文件夹

    Java Program For Downloading Folder Content recursively from SFTP Server How to download folder from ...

  7. react 的定义组件(了解)

    react 中定义组件的方法 1. 定义组件 React.createClass() (被淘汰了) 定义组件中的函数 methods 的中的 this 统统指向 组件 2. 函数定义组件 定义的组件时 ...

  8. PS技巧集合

    一.把图片变模糊 图像——调整——色阶——输出色阶——滤镜——模糊——高斯模糊——半径 二.图片换色 点击右下角弹层下方的“fx”——颜色叠加——色样颜色

  9. Kafka集群安裝部署(自带Zookeeper)

    kafka简介 kafka官网:http://kafka.apache.org/ kafka下载页面:http://kafka.apache.org/downloads kafka配置快速入门:htt ...

  10. JAVA学习记录<一>

    一: JAVA初体验: 1.JAVA简介: 2.环境搭建: 3:MyEclipse的使用简介: 4:程序的移植:项目的导入,导出. 5:学习JAVA的经验: 多写,多问,总结和复习!!!