普通字体为Makefile正文
红色粗体为我加的注释
蓝色粗体为需要注意的地方
Makefile
# 看Makefile文件,发现学习bash编程有多么重要
VERSION = 0
PATCHLEVEL = 1
SUBLEVEL = 4
# 版本,即VIVIRELEASE=0.1.4
VIVIRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)
ARCH := arm
# 执行shell命令,
# -1 判断 $$BASH 是为否为可执行,所以返回1,即不为真。
# -2 判断/bin/bash 是否为可执行,返回0,即真
# 所以最后 CONFIG_SHELL := /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 := vivi顶层目录路径
TOPDIR := $(shell /bin/pwd)
#
# change this to point to the Linux include directory
#
LINUX_INCLUDE_DIR = /opt/host/armv4l/include/
VIVIPATH = $(TOPDIR)/include
HOSTCC = gcc
# -Wstrict-prototypes 如果函数的专用明或定义没有指出参数类型,编译器就发出报警
# -fomit-frame-pointer 对于不需要帧指针的函数,不要在寄存器中保存帧指针,这样
# 能够避免保存、设置和恢复帧指针的指同时对许多函数提供一个额外的寄存器。但这
# 样在大多数机器上将无法调试,某些机器上,如Vax,这个选项无效,因为标准调用
# 序列自动处理帧指针,通过假装不存在而不保存任何东西,机器描述宏
# FRAME_POINTER_REQUIRED控制目标机是否支持这个选项
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 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: do-it-all
# .config是否存在,如果存在就 include .config
ifeq (.config,$(wildcard .config))
include .config
else
CONFIGURATION = config
do-it-all: config
endif
# do-it-all 依赖于 Version vivi
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
# -fPIC 如果支持这种机器,编译器就输出位置无关代码,适用于动态链接情况,即使分
# 支需要大范围转移
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 :=
# 注意下面这里,如内核里的配置一样。当make menuconfig配置完以后,以顶层目录下
# 会产生.config文件。比如我配置了串口,则.config里会有 CONFIG_SERIAL=y
# 上面分析过,Makefile包含了.config,所以下面这一句就相当于
# DRIVERS-y += drivers/serial/serial.o ,以这种方式,DRIVERS-y这个变量就可包含
# 所有的驱动目标文件(.o文件).
# 而若在.config里没有配置这项的话,驱动类的.o文件会被"DRIVERS-"引用,这个
# 变量是不被最终的目标文件vivi所依赖的,所以它不起作用
# 其他配置项都采用此机制
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
# -Tarch/vivi.lds 指定了链接脚本为 arch/vivi.lds
# arch/vivi.lds 是在arch/Makefile文件中生成的,具体情况参照该Makefile文件
# 注意其中有个TEXTADDR参数,指定链接地址,这个地址很关键
# -Bstatic 不链接共享库,即相当于所谓的静态编译
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
include arch/Makefile
export CPPFLAGS CFLAGS AFLAGS
export DRIVERS LDFLAGS
# Version 下面会删除 include/compile.h 可以去看看这个文件的内容
Version: dummy
@rm -f include/compile.h
# 重点,这里是vivi的依赖
# 这里分析时可以先查看各个依赖是如何处理的,比如搜索 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)
$(NM) -v -l vivi-elf > vivi.map
$(OBJCOPY) -O binary -S vivi-elf vivi $(OBJCOPYFLAGS)
# 上面执行链接命令,及其nm 和 objcopy命令 生成所需文件
# LD = $(CROSS_COMPILE)ld , -v 会显示所用ld的版本
# LINKFLAGS = -Tarch/vivi.lds -Bstatic 链接器带的选项
# CORE_FILES = init/main.o init/version.o lib/lib.o ,lib.o是在linuxsubdirs这个
# 依赖的处理过程中,执行子目录中的Makefile,在lib目录中生成
# DRIVERS := $(DRIVERS-y) ,它会包含所有配置中加入的驱动类.o目标文件
# LIBS := lib/priv_data/priv_data.o
# CLIBS = -L$(ARM_GCC_LIBS) -lgcc -lc 链接的库
# OBJCOPYFLAGS = -R .comment -R .stab -R .stabstr ,elf格式转换为二进制时,去
# 除elf文件中的.comment .stabstr两个段,-S 去除elf文件中的重定位信息和符号信
# 息
oldconfig:
$(CONFIG_SHELL) scripts/Configure -d arch/config.in
config:
$(CONFIG_SHELL) scripts/Configure arch/config.in
# make menuconfig 执行的
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 是模式替换函数,%是模式通配符,代表一个单词中的若干个字符
# 前面有 SUBDIRS = drivers lib
# 所以最后为 linuxsubdirs: _dir_drivers _dir_lib
linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS))
$(patsubst %, _dir_%, $(SUBDIRS)) : include/version.h
$(make) cflags="$(cflags) $(cflags_kernel)" -c $(patsubst _dir_%, %, $@)
# 上面的 $(patsubst _dir_%, %, $@) 又替换回为,为 drivers lib
# make -c 即进入子目录中执行其中的Makefile
$(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 , 是把此Makefile里定义的版本信息传送到
# include/version.h 中
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
附 arch/Makeifle
# Select CPU dependent flags. Note that order of declaration is important;
# the options further down the list override previous items.
#
# Note! For APCS-26 YOU MUST HAVE AN APCS-26 LIBGCC.A
#
# -mapcs-32 产生32位的程序代码 ,新版本编译器好像不支持这个选项了
apcs-y :=-mapcs-32
# This selects which instruction set is used.
arch-y :=
# -march=xxx 指定架构版本,每个架构版本在指令集上有所不同。
# arm920t 属于armv4指令集的.gcc根据这个选项来决定产生哪个指令集的汇编代码
arch-$(CONFIG_CPU_32v4) :=-march=armv4
# This selects how we optimise for the processor.
tune-y :=
# -mtune=xxx 指定arm系列,如s3c2410属于arm920tdmi系列的
tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi
tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
# -mshort-load-bytes 这个新版本的编译器已经不支持了,2.95.3还支持
# -msoft-float 相当于 -mfloat-abi=soft 即 指定软件浮点,许多硬浮点的编译器编
# 译它就会出错
CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
# -mno-fpu 新版本的编译器已经不支持这个选项
AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float
ifeq ($(CONFIG_CPU_32),y)
PROCESSOR = armv
TEXTADDR = 0x00000000
endif
LDSCRIPT = arch/vivi.lds.in
ifeq ($(CONFIG_ARCH_SA1100),y)
MACHINE = sa1100
TEXTADDR = 0x00000000
endif
ifeq ($(CONFIG_ARCH_S3C2400),y)
MACHINE = s3c2400
ifeq ($(CONFIG_S3C2400_GAMEPARK),y)
TEXTADDR = 0x00000000
ifeq ($(CONFIG_S3C2400_GAMEPARK_OSSWITCH),y)
TEXTADDR = 0x00100000
endif
ifeq ($(CONFIG_S3C2400_GAMEPARK_ON_RAM),y)
TEXTADDR = 0x0C000000
endif
else
TEXTADDR = 0x00000000
endif
endif
ifeq ($(CONFIG_ARCH_S3C2410),y)
MACHINE = s3c2410
ifeq ($(CONFIG_S3C2410_NAND_BOOT),y)
TEXTADDR = 0x33f00000
else
TEXTADDR = 0x00000000
endif
endif
ifeq ($(CONFIG_ARCH_PXA250),y)
MACHINE = pxa250
TEXTADDR = 0x00000000
endif
ifeq ($(CONFIG_VIVI_ADDR),y)
TEXTADDR = 0x$(CONFIG_VIVI_TEXTADDR)
endif
export MACHINE PROCESSOR TEXTADDR
HEAD := arch/$(MACHINE)/head.o
# If we have a machine-specific directory, then include it in the build.
MACHDIR := arch/$(MACHINE)
ifeq ($(MACHDIR),$(wildcard $(MACHDIR)))
SUBDIRS += $(MACHDIR)
CORE_FILES := $(MACHDIR)/$(MACHINE).o $(CORE_FILES)
endif
CLEAN_FILES += arch/vivi.lds
vivi: $(HEAD) arch/vivi.lds
# 生成 vivi.lds
arch/vivi.lds: $(LDSCRIPT) dummy
@sed s/TEXTADDR/$(TEXTADDR)/ $(LDSCRIPT) >$@
#
# Configuration targets. Use these to select a
# configuration for your architecture
%_config:
@( \
CFG=$(@:_config=); \
if [ -f arch/def-configs/$$CFG ]; then \
[ -f .config ] && mv -f .config .config.old; \
cp arch/def-configs/$$CFG .config; \
echo "*** Default configuration for $$CFG installed"; \
echo "*** Next, you may run 'make oldconfig'"; \
else \
echo "$$CFG does not exist"; \
fi; \
)
阅读(643) | 评论(0) | 转发(0) |