vivi中顶层Makefile的分析
来源:互联网 发布:淘宝联盟微信推广技巧 编辑:程序博客网 时间:2024/05/21 17:37
VERSION = 0
PATCHLEVEL = 1
SUBLEVEL = 4
VIVIRELEASE=$(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 = gcc
HOSTCFLAGS = -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)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC)-E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
MAKEFILES = $(TOPDIR)/.config
MD5SUM = md5sum
PERL = perl
AWK = awk
export 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文件
else
CONFIGURATION = config
do-it-all: config
#如果不存在则定义变量CONFIGURATION,并且对变量进行赋值
#定义目标和依赖di-it-all: config
endif
do-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 flags
CFLAGS := $(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.o
LIBS := lib/priv_data/priv_data.o
SUBDIRS = drivers lib
#定义核心文件,库和子目录,这些变量在下面都会用到
DRIVERS-y :=
DRIVERS-$(CONFIG_SERIAL)+= drivers/serial/serial.o
DRIVERS-$(CONFIG_MTD)+= drivers/mtd/mtd.o
DRIVERS := $(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 symbolic
LINKFLAGS = -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 AFLAGS
export 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.in
config:
$(CONFIG_SHELL) scripts/Configure arch/config.in
menuconfig: 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.c
init/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 1
dummy:
else
dummy:
endif
include Rules.make
- vivi中顶层Makefile的分析
- vivi分析-顶层Makefile
- vivi的Makefile分析
- TX2440 vivi的makefile分析
- u-boot顶层的makefile分析
- openwrt顶层Makefile分析
- openwrt顶层Makefile分析
- Linux顶层Makefile分析
- openwrt顶层Makefile分析
- openwrt顶层Makefile分析
- Uboot顶层Makefile分析
- 浅析vivi的Makefile
- vivi的Makefile注释
- vivi的Makefile分析 - xgc94418297的日志 - 网易博客
- VIVI中堆栈设置的分析
- u-boot顶层Makefile分析
- U-Boot顶层Makefile分析
- Linux顶层Makefile文件分析
- Makefile wildcard notdir patsubst 简介
- Java程序生成Jar、exe及安装文件
- Makefile wildcard notdir patsubst 简介
- 第十一章 字符串和字符串函数(练习)总结 140606
- CentOS 重置root用户的密码
- vivi中顶层Makefile的分析
- 服务器提供商运营者
- Pascal's Triangle II
- linux的echo命令
- A*
- 操作系统学习总结四
- 发现新浪一注册漏洞
- Java 自定义窗体(标题栏、窗体背景)
- python实现的链表