分类: LINUX
2009-10-04 00:42:40
# 定义三个变量表示vivi版本号
VERSION = 0
PATCHLEVEL = 1
SUBLEVEL = 4
VIVIRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)
# 定义体系结构为arm
# :=表示给变量赋值并立即展开生效.
ARCH := arm
# GNU make函数调用的格式类似于变量的引用,以"$"开始表示一个引用.语法是:
# $(FUNCTION ARGUMENTS)或${FUNCTION ARGUMENTS}
# make内建函数shell的参数是一个命令,该函数的返回值是此命令在shell中
# 执行的结果.
#
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
else if [ -x /bin/bash ]; then echo /bin/bash; \
else echo sh; fi ; fi)
# 定义变量TOPDIR指示VIVI顶层目录
TOPDIR := $(shell /bin/pwd)
# 定义Linux内核头文件所在路径.
#
# change this to point to the Linux include directory
#
LINUX_INCLUDE_DIR = /opt/host/armv4l/include/
# 定义VIVI头文件所在路径.
VIVIPATH = $(TOPDIR)/include
# 指定本地编译器为gcc,本地编译器参数HOSTCFLAGS.
HOSTCC = gcc
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
# 指定交叉编译器前缀,后面会补充完整.
CROSS_COMPILE = /opt/host/armv4l/bin/armv4l-unknown-linux-
#CROSS_COMPILE = /opt/host/armv4l/bin/armv4l-redhat-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导出前面定义的变量给子Makefile.见<
# 注意:export导出的变量不会覆盖子Makefile中定义的变量,也就是说,如果子Makefile中定义了同名的变量,
# 在子Makefile中仍然是子Makefile中定义的变量有效.
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
# 目标all依赖文件do-it-all
# 如果根目录下没有.config文件,do-it-all依赖于config.如果根目录下有
# .config文件,用include包含.config文件.do-it-all依赖于Version vivi.
all: do-it-all
# ifeq条件语句用于比较两个参数是否相等.
# make内建函数wildcard,格式为$(wildcard PATTERN),函数的作用是列出
# 当前目录下所有符合模式"PATTERN"格式的文件名,"PATTERN"可以使用shell
# 可以识别的通配符,包括"?"(单字符)和"*"(多字符).
ifeq (.config,$(wildcard .config))
# "include"指示符告诉make暂停读取当前的Makefile,而转去读取"include"
# 指定的一个或多个文件,完成以后再继续当前Makefile的读取.
# "include"的语法是include FILENAMES, "FILENAMES"是shell所支持的文件
# 名,可以使用通配符.
include .config
else
CONFIGURATION = config
do-it-all: config
endif
do-it-all: Version vivi
#
# standard CFLAGS
#
CPPFLAGS := -I$(VIVIPATH) -I$(LINUX_INCLUDE_DIR)
#CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
# -fomit-frame-pointer -fno-strict-aliasing -fno-common
CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fPIC -fomit-frame-pointer
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
# "+="表示对一个变量值进行追加操作.前面变量即可以用"="也可以用":="
# 定义.
# CONFIG_SERIAL在.config文件中定义.
DRIVERS-y :=
DRIVERS-$(CONFIG_SERIAL) += drivers/serial/serial.o
DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtd.o
DRIVERS := $(DRIVERS-y)
CLEAN_FILES = \
vivi-elf \
vivi \
vivi.nm \
vivi.map
#
# Location of the gcc arm libs.
#
ARM_GCC_LIBS = /opt/host/armv4l/lib/gcc-lib/armv4l-unknown-linux/2.95.2
#ARM_GCC_LIBS = /opt/host/armv4l/lib/gcc-lib/armv4l-redhat-linux/2.95.3
OBJCOPYFLAGS = -R .comment -R .stab -R .stabstr
CLIBS = -L$(ARM_GCC_LIBS) -lgcc -lc
LINKFLAGS = -Tarch/vivi.lds -Bstatic
DISTCLEAN_FILES = \
include/autoconf.h include/version.h \
scripts/lxdialog/*.o scripts/lxdialog/lxdialog \
.menuconfig.log \
.config .config.old TAGS tags
# 包含arch/Makefile.
include arch/Makefile
export CPPFLAGS CFLAGS AFLAGS
export DRIVERS LDFLAGS
#<<跟我一起写Makefile>>P26,通常make会把要执行的命令首先在屏幕上显示出来,当我们用@字符在命令行前时,
#这个命令将不会被显示出来.
Version: dummy
@rm -f include/compile.h
#nm软件主要功能是列出目标文件中的符号,这样可以帮助程序员定位和分析执行程序和目标文件中的符号信息和它的属性.
#如果没有目标文件作为参数被列出,nm假定目标文件为"a.out".
#nm的-v参数表示按符号对应地址的顺序排序,而不是按符号名的字符顺序.
#nm的-l参数表示对每个符号,使用调试信息去试图找到文件名和行号,对于已经定义的符号,查找符号地址的行号.对于未定义
#的符号,查找指向符号重定位入口的行号.如果可以找到行号信息,在其他符号信息之后显示行号信息.
#objcopy软件可以将一种格式的目标文件内容进行转换,并输出为另一种格式的目标文件.objcopy使用GNU BFD库读/写目标文件
#通过这个GNU BFD库,objcopy能够以一种不同于源目标文件的格式来生成目标文件.
#objcopy的-O参数表示使用后面的参数做为写入输出文件的目标格式.
#objcopy的-S参数表示不复制源文件中的重定位和符号信息.
#objcopy的-R参数表示从输出文件中除去名字为后面跟的参数的任何节,可以多次使用这个选项.
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)
# 作用还不明确
oldconfig:
$(CONFIG_SHELL) scripts/Configure -d arch/config.in
config:
$(CONFIG_SHELL) scripts/Configure arch/config.in
# 首先进入scripts/lxdialog目录,在该目录下执行make all
menuconfig: include/version.h
$(MAKE) -C scripts/lxdialog all
$(CONFIG_SHELL) scripts/Menuconfig arch/config.in
clean:
find . \( -name '*.o' -o -name core -o -name ".*.flags" \) -type f -print \
| grep -v lxdialog/ | xargs rm -f
rm -f $(CLEAN_FILES)
distclean: clean
rm -f $(DISTCLEAN_FILES)
# 模式替换函数patsubst,格式为$(patsubst PATTERN, REPLACEMENT, TEXT)
# 函数功能:搜索"TEXT"中以空格分开的单词,将符合模式"PATTERN"的字符替换
# 为"REPLACEMENT".参数"PATTERN"中可以使用模式通配符"%",它和一个字中
# 任意个数的字符相匹配.如果"REPLACEMENT"中也含有通配符%,则这个%被和
# "PATTERN"中通配符%匹配的文件代替.
linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS))
$(patsubst %, _dir_%, $(SUBDIRS)) : include/version.h
$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C $(patsubst _dir_%, %, $@)
$(TOPDIR)/include/version.h: include/version.h
$(TOPDIR)/include/compile.h: include/compile.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 $@
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 $<
TAGS: dummy
etags `find include -name '*.h'`
find $(SUBDIRS) init -name '*.[ch]' | xargs etags -a
# Exuberant ctags works better with -I
tags: dummy
CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \
ctags $$CTAGSF `find include -name '*.h'` && \
find $(SUBDIRS) init -name '*.[ch]' | xargs ctags $$CTAGSF -a
# %是不是用到了通用规则.%代表任意非空字符.
%: ./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