#定义版本信息的四个变量:发行版本号、版本号、补丁程度、次版本号
VERSION = 0
PATCHLEVEL = 1
SUBLEVEL = 4
#发行版本号由 版本号:补丁程度:次版本号 组成
VIVIRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)
#定义针对arm平台
#“:=”表示直接展开式的变量赋值,ARCH 的值不会随着arm变量的值的改变而改变
ARCH := arm
#定义shell命令解释器的变量CONFIG_SHELL,shell函数需要一个shell命令做为参数,
#函数的返回值是这个shell命令的执行结果,make仅仅对它的回返结果进行处理
#这里用来判断bash的路径,并把bash的路径赋值给CONFIG_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 := $(shell /bin/pwd)
#
# change this to point to the Linux include directory
#
LINUX_INCLUDE_DIR = /opt/host/armv4l/include/
#定义vivi头文件所在的路径
VIVIPATH = $(TOPDIR)/include
#定义本地的编译器及其参数
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
#导出前面定义的变量,给子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
#all并没有定义生成规则
all: do-it-all
#wildcard 函数作用是列出当前目录下所有符合参数格式的文件名
#ifeq 判断参数是否相等
#整段的作用是判断当前目录下有没有.config这个文件,若有,则包含.config这个文件;
#若无,则定义变量CONFIGURATION为config,并且do-it-all依赖于config
ifeq (.config,$(wildcard .config))
include .config
else
CONFIGURATION = config
do-it-all: config
endif
#定义do-it-all依赖于Version 和 vivi,若上段无.config这个文件,则还多依赖了config
#do-it-all没有生成规则
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
#定义驱动,“+=”表示变量追加
DRIVERS-y :=
DRIVERS-$(CONFIG_SERIAL) += drivers/serial/serial.o
DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtd.o
DRIVERS := $(DRIVERS-y)
#定义make clean 要删除的文件
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
#定义OBJCOPY的参数
OBJCOPYFLAGS = -R .comment -R .stab -R .stabstr
#指定库及库搜索路径
CLIBS = -L$(ARM_GCC_LIBS) -lgcc -lc
#指定链接器命令行参数
LINKFLAGS = -Tarch/vivi.lds -Bstatic
#定义执行make distclean 时要删除的文件
DISTCLEAN_FILES = /
include/autoconf.h include/version.h /
scripts/lxdialog/*.o scripts/lxdialog/lxdialog /
.menuconfig.log /
.config .config.old TAGS tags
#包含结构的Makefile
include arch/Makefile
#导出变量CPPFLAGS CFLAGS AFLAGS
export CPPFLAGS CFLAGS AFLAGS
#导出变量DRIVERS LDFLAGS
export DRIVERS LDFLAGS
#Version的规则,删除include/compile.h,“@”表示命令不回显
Version: dummy
@rm -f include/compile.h
#生成vivi的规则,依赖于include/version.h $(CONFIGURATION) init/main.o init/version.o #linuxsubdirs
vivi: include/version.h $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(LD) -v $(LINKFLAGS) /
$(HEAD) /
$(CORE_FILES) /
$(DRIVERS) /
$(LIBS) /
-o vivi-elf $(CLIBS)
#列出目标文件vivi-elf的符号清单到vivi.map文件中
$(NM) -v -l vivi-elf > vivi.map
#把elf格式的可执行程序 vivi-elf 转换成待烧写的镜像文件 vivi
$(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
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)
#linuxsubdirs的生成规则,由此进到子目录,执行子目录的Makefile
#patsubst字符替换函数,用在这里是把drivers lib 替换成_dir_drivers _dir_lib
linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS))
#生成_dir_drivers _dir_lib的规则
#“-C”表示改变目录,$(patsubst _dir_%, %, $@)表示执行完后把生成的目标文件替换成#drivers lib
#名字来回替换的原因:driver或lib是子目录的名字,已经存在于文件中,这样就不会执行#Makefile中的规则
#因此,为了不和它们混淆,产生不必要的麻烦,就对目标的名字进行了替换。
$(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中,其中的“@”表示不回显,“/”表示它后面的“#”不是注释
##define VIVI_RELEASE /"$(VIVIRELEASE)/"
##define VIVI_VERSION_CODE `expr $(VERSION) //* 65536 + $(PATCHLEVEL) //* 256 + $(SUBLEVEL)`
##define VIVI_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
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
#把.ver 改名成include/version.h
@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
#生成main.o的规则
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
#包含make的规则
#为什么能写在最后呢,而不是写在开头呢?
#因为make分两阶段执行.
#第一阶段:读取所有的makefile文件(包括“MAKIFILES”变量指定的、指示符“include”#指定的、
#以及命令行选项“-f(--file)”指定的makefile文件),内建所有的变量、明确规则和隐含规
#则,
#并建立所有目标和依赖之间的依赖关系结构链表。
#第二阶段:根据第一阶段已经建立的依赖关系结构链表决定哪些目标需要更新,并使用对
#应的规则来重建这些目标。
include Rules.make
=========================================================================
附加Rules.make文件:
#
# This file contains rules which are shared between multiple Makefiles.
#
#
# False targets.
#
#定义伪目标dummy
.PHONY: dummy
#
# Special variables which should not be exported
#
#不导出变量,防止影响其它文件的同名变量
unexport EXTRA_AFLAGS
unexport EXTRA_CFLAGS
unexport EXTRA_LDFLAGS
unexport EXTRA_ARFLAGS
unexport SUBDIRS
unexport SUB_DIRS
unexport ALL_SUB_DIRS
unexport O_TARGET
unexport obj-y
unexport obj-n
unexport obj-
unexport export-objs
unexport subdir-y
unexport subdir-m
unexport subdir-n
unexport subdir-
#
# Get things started.
#
first_rule: sub_dirs
$(MAKE) all_targets
both-m := $(filter $(mod-subdirs), $(subdir-y))
SUB_DIRS := $(subdir-y)
ALL_SUB_DIRS := $(sort $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-))
#
# Common rules
#
%.s: %.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -S $< -o $@
%.i: %.c
$(CPP) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) $< > $@
%.o: %.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -c -o $@ $<
@ ( /
echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@))))' ; /
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; /
echo 'endif' /
) > $(dir $@)/.$(notdir $@).flags
%.o: %.s
$(AS) $(AFLAGS) $(EXTRA_CFLAGS) -o $@ $<
%.s: %.S
$(CPP) $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$@) $< > $@
%.o: %.S
$(CC) $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$@) -c -o $@ $<
%.lst: %.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $<
$(TOPDIR)/scripts/makelst $* $(TOPDIR) $(OBJDUMP)
#
#
#O_TARGET L_TARGET在子Makefile中定义
all_targets: $(O_TARGET) $(L_TARGET)
#
# Rule to compile a set of .o files into one .o file
#
ifdef O_TARGET
$(O_TARGET): $(obj-y)
rm -f $@
ifneq "$(strip $(obj-y))" ""
$(LD) $(EXTRA_LDFLAGS) -r -o $@ $(filter $(obj-y), $^)
else
#打包成目标文件
$(AR) rcs $@
endif
@ ( /
echo 'ifeq ($(strip $(subst $(comma),:,$(EXTRA_LDFLAGS) $(obj-y))),$$(strip $$(subst $$(comma),:,$$(EXTRA_LDFLAGS) $$(obj-y))))' ; /
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; /
echo 'endif' /
) > $(dir $@)/.$(notdir $@).flags
endif # O_TARGET
#
# Rule to compile a set of .o files into one .a file
#
ifdef L_TARGET
$(L_TARGET): $(obj-y)
rm -f $@
$(AR) $(EXTRA_ARFLAGS) rcs $@ $(obj-y)
@ ( /
echo 'ifeq ($(strip $(subst $(comma),:,$(EXTRA_ARFLAGS) $(obj-y))),$$(strip $$(subst $$(comma),:,$$(EXTRA_ARFLAGS) $$(obj-y))))' ; /
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; /
echo 'endif' /
) > $(dir $@)/.$(notdir $@).flags
endif
#
# This make dependencies quickly
#
fastdep: dummy
$(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS) -- $(wildcard *.[chS]) > .depend
ifdef ALL_SUB_DIRS
$(MAKE) $(patsubst %,_sfdep_%,$(ALL_SUB_DIRS)) _FASTDEP_ALL_SUB_DIRS="$(ALL_SUB_DIRS)"
endif
ifdef _FASTDEP_ALL_SUB_DIRS
$(patsubst %,_sfdep_%,$(_FASTDEP_ALL_SUB_DIRS)):
$(MAKE) -C $(patsubst _sfdep_%,%,$@) fastdep
endif
#
# A rule to make subdirectories
#
#sort按字母排序函数,在这里先把$(SUB_DIRS)替换成_subdir_$(SUB_DIRS)的形式,再按
#字母顺序排序
subdir-list = $(sort $(patsubst %,_subdir_%,$(SUB_DIRS)))
sub_dirs: dummy $(subdir-list)
ifdef SUB_DIRS
$(subdir-list) : dummy
$(MAKE) -C $(patsubst _subdir_%,%,$@)
endif
#
# A rule to do nothing
#
dummy:
#
# This is useful for testing
#
script:
$(SCRIPT)
#
# include dependency files if they exist
#
ifneq ($(wildcard .depend),)
include .depend
endif
ifneq ($(wildcard $(TOPDIR)/.hdepend),)
include $(TOPDIR)/.hdepend
endif
#
# Find files whose flags have changed and force recompilation.
# For safety, this works in the converse direction:
# every file is forced, except those whose flags are positively up-to-date.
#
FILES_FLAGS_UP_TO_DATE :=
# For use in expunging commas from flags, which mung our checking.
comma = ,
FILES_FLAGS_EXIST := $(wildcard .*.flags)
ifneq ($(FILES_FLAGS_EXIST),)
include $(FILES_FLAGS_EXIST)
endif
FILES_FLAGS_CHANGED := $(strip /
$(filter-out $(FILES_FLAGS_UP_TO_DATE), /
$(O_TARGET) $(L_TARGET) $(active-objs) /
))
# A kludge: .S files don't get flag dependencies (yet),
# because that will involve changing a lot of Makefiles. Also
# suppress object files explicitly listed in $(IGNORE_FLAGS_OBJS).
# This allows handling of assembly files that get translated into
# multiple object files (see arch/ia64/lib/idiv.S, for example).
FILES_FLAGS_CHANGED := $(strip /
$(filter-out $(patsubst %.S, %.o, $(wildcard *.S) $(IGNORE_FLAGS_OBJS)), /
$(FILES_FLAGS_CHANGED)))
ifneq ($(FILES_FLAGS_CHANGED),)
$(FILES_FLAGS_CHANGED): dummy
endif