Chinaunix首页 | 论坛 | 博客
  • 博客访问: 173689
  • 博文数量: 33
  • 博客积分: 731
  • 博客等级: 上士
  • 技术积分: 757
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-02 22:51
文章存档

2018年(1)

2017年(2)

2013年(1)

2012年(29)

我的朋友

分类:

2012-11-07 09:51:55

原文地址:vivi分析-顶层Makefile 作者:changyongID

普通字体为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; \
    )
阅读(667) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~