本文以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. $\LaTeX$数学公式大全13

    $13\ Text\ Mode:\ Accents\ and\ Symbols$ $\AA$ \AA $\S$ \S

  2. 从零开始学习Gradle之三---多项目构建

       随着信息化的快速发展,IT项目变得越来越复杂,通常都是由多个子系统共同协作完成.对于这种多系统.多项目的情况,很多构建工具都已经提供了不错的支持,像maven.ant.Gradle除了借鉴了an ...

  3. DB 分库分表的基本思想和切分策略

    DB 分库分表的基本思想和切分策略 一.基本思想 Sharding的基本思想就要把一个数据库切分成多个部分放到不同的数据库(server)上,从而缓解单一数据库的性能问题.不太严格的讲,对于海量数据的 ...

  4. (四)C语言之函数

  5. Mybatis不使用Spring框架(Druid)

    1.Mysql database CREATE TABLE mockrecord (id INT(10) unsigned PRIMARY KEY NOT NULL COMMENT 'mock记录编号 ...

  6. 在Ubuntu 16.04配置VNC Server (灰屏问题解决)

      使用命令安装 sudo apt install xfce4 xfce4-goodies tightvncserver 编辑vnc启动文件,安全期间最好备份一下 mv ~/.vnc/xstartup ...

  7. Druid连接池(无框架)

    关于连接池有不少技术可以用,例如c3p0,druid等等,因为druid有监控平台,性能在同类产品中算top0的.所以我采用的事druid连接池. 首先熟悉一个技术,我们要搞明白,为什么要用他, 他能 ...

  8. Android jni/ndk编程二:jni数据类型转换(primitive,String,array)

    一.数据类型映射概述 从我们开始jni编程起,就不可能避开函数的参数与返回值的问题.java语言的数据类型和c/c++有很多不同的地方,所以我们必须考虑当在java层调用c/c++函数时,怎么正确的把 ...

  9. Postman系列之测试用例管理(二)

    实验简介 本文主要讲解Postman对多个测试用例的管理,让测试进行更有序,易于管理. 实验目的 Postman 测试集(Collections)管理的相关内容,它用来保存我们的 Request ,可 ...

  10. 【转载】如何在 Kaggle 首战中进入前 10%

    本文转载自如何在 Kaggle 首战中进入前 10% 转载仅出于个人学习收藏,侵删 Introduction 本文采用署名 - 非商业性使用 - 禁止演绎 3.0 中国大陆许可协议进行许可.著作权由章 ...