charming2440
全部博文(190)
2014年(9)
2011年(32)
2010年(149)
dzminglo
nasca
戰神神戰
tomcodin
wayneshe
cool138
听风_12
godslion
Kuangjay
REFRESHM
分类: LINUX
2010-05-29 18:22:19
VERSION = 0PATCHLEVEL = 1SUBLEVEL = 4VIVIRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)#定义vivi的版本信息ARCH := arm#定义平台消息#检查系统是采用哪个BASH#-x检查文件是否存在if [ -x /bin/bash ]注意格式CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ else if [ -x /bin/bash ]; then echo /bin/bash; \ else echo sh; fi ; fi)TOPDIR := $(shell /bin/pwd)#定义顶层目录## change this to point to the Linux include directory##定义linux头文件的目录,在下面编译中会用到LINUX_INCLUDE_DIR = /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include#vivi头文件的路径VIVIPATH = $(TOPDIR)/include#宿主机的的gcc,版本根据主机变化而变化#定义了gcc的参数,-Wall表示打开警告信息#-Wstrict-prototypes为定义参数类型的变量和函数输出警告#-O2对代码进行优化#-fomit-frame-pointer忽略帧指针HOSTCC = gccHOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer#定义交叉编译器的变量地址CROSS_COMPILE = /usr/local/arm/4.3.2/bin/arm-linux-## Include the make variables (CC, etc...)#AS = $(CROSS_COMPILE)asLD = $(CROSS_COMPILE)ldCC = $(CROSS_COMPILE)gccCPP = $(CC) -EAR = $(CROSS_COMPILE)arNM = $(CROSS_COMPILE)nmSTRIP = $(CROSS_COMPILE)stripOBJCOPY = $(CROSS_COMPILE)objcopyOBJDUMP = $(CROSS_COMPILE)objdumpMAKEFILES = $(TOPDIR)/.configMD5SUM = md5sumPERL = perlAWK = awkexport VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE \ CONFIG_SHELL TOPDIR VIVIPATH HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \ CPP AR NM STRIP OBJCOPY OBJDUMP MAKE MAKEFILES MD5SUM PERL AWK#对外部声明以上的变量,即在其他的MAKEFILE文件也可以使用以上的变量all: do-it-all#定义目标和依赖ifeq (.config,$(wildcard .config))#'wildcard' 的函 数,它有一个参数,功能是展开成一列所有符合由其参数描述的文#件名,文件间以空格间隔#上面这句的目的就是在当前目录下查找,config文件include .config#如果当前目录下存在.config文件,则包含.config文件elseCONFIGURATION = configdo-it-all: config#如果不存在则定义变量CONFIGURATION,并且对变量进行赋值#定义目标和依赖di-it-all: configendifdo-it-all: Version vivi#追加do-it-all的依赖文件#上面的函数的目的就是在vivi的根目录下查找.config文件,如果存在则包含.config;#do-it-all依赖的文件为Version和vivi#如果不存在,则定义变量CONFIGURATION变量;#do-it-all的依赖文件Version和vivi## standard CFLAGS#CPPFLAGS := -I$(VIVIPATH) -I$(LINUX_INCLUDE_DIR)#定义编译器预处理的参数#-I表示在头文件的搜索路径中添加(-Idir)dir目录#CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \# -fomit-frame-pointer -fno-strict-aliasing -fno-common#normal flagsCFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fPIC -fomit-frame-pointer#交叉编译器的参数,基本上宿主gcc的参数相同,参见上面的解释#补充一个-fPIC,与地址无关。具体作用不明白???#symbol table make up#CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fPIC -fomit-frame-pointer -ggdb AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)#汇编器选项CORE_FILES = init/main.o init/version.o lib/lib.oLIBS := lib/priv_data/priv_data.oSUBDIRS = drivers lib#定义核心文件,库和子目录,这些变量在下面都会用到DRIVERS-y :=DRIVERS-$(CONFIG_SERIAL) += drivers/serial/serial.oDRIVERS-$(CONFIG_MTD) += drivers/mtd/mtd.oDRIVERS := $(DRIVERS-y)#定义变量DRIVERS-y,看到这里我们就知道了为什么要包含.config文件的原因(在vivi根目#录下存在.config的情况下,打开.config文件,里面就会有CONFIG_SERIAL和CONFIG_MTD的#定义,如果在组态的时候增加了相关的选项,则就将其赋值为y)#那如果没有.config的情况下,则在do-it-all的依赖中添加了一个config依赖文件;#而利用make config来配置,从而生成.config文件。因此作用是相同的。CLEAN_FILES = \ vivi-elf \ vivi \ vivi.nm \ vivi.map#定义需要清除的文件## Location of the gcc arm libs.#ARM_GCC_LIBS = /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib#定义交叉编译库目录OBJCOPYFLAGS = -R .comment -R .stab -R .stabstr#定义objcopy的参数,objcopy包含了很多参数,具体的看使用手册#-R选项是用来删掉包含了二进制文件不需要的内容的那些部分。CLIBS = -L$(ARM_GCC_LIBS) -L/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/usr/lib -L/usr/local/arm/4.3.2/lib/gcc/arm-none-linux-gnueabi/4.3.2/armv4t/ -lgcc -lc#定义CLIBS; -Ldir 表示在-I选项的搜索路径列表中添加dir目录#-lgcc -lc标准的库文件。具体是什么我也不知道,有待研究#laputa symbolicLINKFLAGS = -Tarch/vivi.lds -Bstatic #连接参数;-T表示使用连接脚本,这个脚本会替代"ld"的缺省连接脚本。所以命令文件必#须指定所有需要的东西以精确描述输出文件#-Bstatic表示不连接共享库,DISTCLEAN_FILES = \ include/autoconf.h include/version.h \ scripts/lxdialog/*.o scripts/lxdialog/lxdialog \ .menuconfig.log \ .config .config.old #定义需要删除的文件include arch/Makefile#包含子目录的Makefile文件。vivi中的Makefile使用分层管理的机制#这样的好处就是方便管理export CPPFLAGS CFLAGS AFLAGSexport DRIVERS LDFLAGS#向外部声明变量Version: dummy @rm -f include/compile.h#定义目标Version,其依赖文件是dummy,#命令就是删除include/compile.h文件#执行本命令时不再屏幕上打印命令的内容vivi: include/version.h $(CONFIGURATION) init/main.o init/version.o linuxsubdirs $(LD) -v $(LINKFLAGS) \ $(HEAD) \ $(CORE_FILES) \ $(DRIVERS) \ $(LIBS) \ -o vivi-elf $(CLIBS) $(NM) -v -l vivi-elf > vivi.map $(OBJCOPY) -O binary -S vivi-elf vivi $(OBJCOPYFLAGS)#定义目标vivi,其中vivi包含的目标比较多,有则包括,没有则需要首先编译获得#这个时候我们发现,linuxsubdirs没有定义,而且HEAD也没有,但是我们在前面的时候就有一个#include arch/Makefile。我们进去到arch目录下去看看该目录的Makefile文件#HEAD := arch/$(MACHINE)/head.o#linuxsubdirs我还没找到#后来继续往下面看的时候发现linuxsubdirs有定义,这样就告诉我们,有时候不需要钻入#死胡同里面,没准路就在前面的拐角处#NM函数和OBJCOPY函数的功能看相关资料#在这里的意思分别是将vivi-elf文件的变量和函数的地址放在文件vivi.map中#利用vivi-elf生成二进制文件vivi,取出不必要的信息oldconfig: $(CONFIG_SHELL) scripts/Configure -d arch/config.inconfig: $(CONFIG_SHELL) scripts/Configure arch/config.inmenuconfig: include/version.h $(MAKE) -C scripts/lxdialog all $(CONFIG_SHELL) scripts/Menuconfig arch/config.in#关于上面的3个分析,网上有很多资料,我就不详细分析,需要注意的是menuconfig目标#该目标首先是进入scripts/lxdialog目录然后执行make命令,其实也就是一个图形界面的#操作clean: find . \( -name '*.o' -o -name core -o -name ".*.flags" \) -type f -print \ | grep -v lxdialog/ | xargs rm -f rm -f $(CLEAN_FILES)#clean目标,一共用到了find,grep,xargs 3个命令。#相关的命令分析请看我的linux命令解析部分,宗旨这个函数的目的就是在当前目录下#找到所有的.o,.flags和core的普通文件(搜索的路径中不包括lxdialog),并且打印出来#然后删除它们,并且删除CLEAN_FILES文件distclean: clean rm -f $(DISTCLEAN_FILES)linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS))$(patsubst %, _dir_%, $(SUBDIRS)) : include/version.h $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C $(patsubst _dir_%, %, $@)#上面的就是需要看patsubst函数的用法# $@表示一个目标名种的目标文件# make -C 表示进入该目录再执行make命令$(TOPDIR)/include/version.h: include/version.h$(TOPDIR)/include/compile.h: include/compile.h##定义了在include目录下的两个目标文件,version.h,compile.h#在DISTCLEAN_FILES的依赖文件中,有compile.h文件,因此可以看出compile.h和version.h两个文件是需要#配置的过程中生成的。那么这两个文件又是怎么生成的,它们的作用是什么?下面我们具体分析。##include/compile.h: $(CONFIGURATION) include/version.h @echo -n \#define UTS_VERSION \"\#$(VIVIRELEASE) > .ver @if [ -f .name ]; then echo -n \-`cat .name` >> .ver; fi @echo ' '`date`'"' >> .ver @echo \#define VIVI_COMPILE_TIME \"`date +%T`\" >> .ver @echo \#define VIVI_COMPILE_BY \"`whoami`\" >> .ver @echo \#define VIVI_COMPILE_HOST \"`hostname`\" >> .ver @if [ -x /bin/dnsdomainname ]; then \ echo \#define VIVI_COMPILE_DOMAIN \"`dnsdomainname`\"; \ elif [ -x /bin/domainname ]; then \ echo \#define VIVI_COMPILE_DOMAIN \"`domainname`\"; \ else \ echo \#define VIVI_COMPILE_DOMAIN ; \ fi >> .ver @echo \#define VIVI_COMPILER \"`$(CC) $(CFLAGS) -v 2>&1 | tail -1`\" >> .ver @mv -f .ver $@include/version.h: @echo \#define VIVI_RELEASE \"$(VIVIRELEASE)\" > .ver @echo \#define VIVI_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)` >> .ver @echo '#define VIVI_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' >>.ver @mv -f .ver $@#上面两个说明了compile.h和version.h文件的生成过程,这里需要注意的就是echo的用法# echo -n表示不换行# 其他的date,whoami,hostname则分别查看相关命令的用法init/version.o: init/version.c include/compile.h $(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.cinit/main.o: init/main.c $(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $<%: ./arch/def-configs/% $(MAKE) distclean cp arch/def-configs/$* ./.config -f $(MAKE) oldconfig $(MAKE) ifdef CONFIGURATION..$(CONFIGURATION): @echo @echo "You have a bad or nonexistent" .$(CONFIGURATION) ": running 'make" $(CONFIGURATION)"'" @echo $(MAKE) $(CONFIGURATION) @echo @echo "Successful. Try re-making (ignore the error that follows)" @echo exit 1dummy:elsedummy:endifinclude Rules.make
上一篇:Makefile wildcard notdir patsubst 简介
下一篇:linux echo命令使用
登录 注册