免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1654 | 回复: 0
打印 上一主题 下一主题

Makefile 分析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-08-28 10:50 |只看该作者 |倒序浏览

Makefile 分析
Author: cyliu  
Data: 2007-07-01
/*-------------------------------------------------------------------------------*/
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 20
EXTRAVERSION = .7
NAME = Homicidal Dwarf Hamster
# 以上表明了内核版本。组合起来就是:2.6.20.7 ,yeah,这就是我分析的内核版本
# 注意写makefile时不要使用makefile的内建的规则和变量
#要想不打印"Entering directory ..."字样,请使用no-print-directory选项
MAKEFLAGS += -rR --no-print-directory
# 因为需要递归执行build, 所以必须注意要保证按照正确顺序执行make.
# 使用 'make V=1' 可以看到完整命令
ifdef V
  ifeq ("$(origin V)", "command line")
    KBUILD_VERBOSE = $(V)
  endif
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif
# 使用 'make C=1' 仅检查需要重新使用c编译器编译的文件
# 使用 'make C=2' 检查所有c编译器编译的文件
ifdef C
  ifeq ("$(origin C)", "command line")
    KBUILD_CHECKSRC = $(C)
  endif
endif
ifndef KBUILD_CHECKSRC
  KBUILD_CHECKSRC = 0
endif
# 使用 make M=dir 表明需要编译的模块目录
# 旧的语法make ... SUBDIRS=$PWD 依然支持
# 这里通过环境变量 KBUILD_EXTMOD来表示
ifdef SUBDIRS
  KBUILD_EXTMOD ?= $(SUBDIRS)
endif
ifdef M
  ifeq ("$(origin M)", "command line")
    KBUILD_EXTMOD := $(M)
  endif
endif
# kbuild 可以把输出文件放到一个分开的目录下
# 定位输出文件目录有两种语法支持:
# 两种方法都要求工作目录是内核源文件目录的根目录
# 1) O=
# 使用 "make O=dir/to/store/output/files/"
#
# 2) 设置 KBUILD_OUTPUT
# 设置环境变量 KBUILD_OUTPUT 来指定输出文件存放的目录
# export KBUILD_OUTPUT=dir/to/store/output/files/
# make
#
# 但是 O= 方式优先于KBUILD_OUTPUT环境变量方式
# KBUILD_SRC 会再obj目录的make调用
# KBUILD_SRC 到目前还不是为了给一般用户使用的
ifeq ($(KBUILD_SRC),)
ifdef O
  ifeq ("$(origin O)", "command line")
    KBUILD_OUTPUT := $(O)
  endif
endif
# 缺剩目标
PHONY := _all
_all:
ifneq ($(KBUILD_OUTPUT),)
# 调用输出目录的第二个make, 传递相关变量检查输出目录确实存在
saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
$(if $(KBUILD_OUTPUT),, \
     $(error output directory "$(saved-output)" does not exist))
PHONY += $(MAKECMDGOALS)
$(filter-out _all,$(MAKECMDGOALS)) _all:
    $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
    KBUILD_SRC=$(CURDIR) \
    KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
# Leave processing to above invocation of make
skip-makefile := 1
endif # ifneq ($(KBUILD_OUTPUT),)
endif # ifeq ($(KBUILD_SRC),)
ifeq ($(skip-makefile),)
PHONY += all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif
srctree        := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
TOPDIR        := $(srctree)
# FIXME - TOPDIR is obsolete, use srctree/objtree
objtree        := $(CURDIR)
src        := $(srctree)
obj        := $(objtree)
VPATH        := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
export srctree objtree VPATH TOPDIR
# SUBARCH 告诉 usermode build 当前的机器是什么体系.  它是第一个设置的,并且如果
# 是usermode build ,命令行中的 "ARCH=um" 优先下面的 ARCH 设置. 如果是 native build ,
# 设置ARCH , 获取正常的数值, 将会忽略SUBARCH .
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ )
# 交叉编译和选择不同的gcc/bin-utils
# ---------------------------------------------------------------------------
#
# 当交叉编译其他体系的内核时,ARCH 应该设置为目标体系.
# ARCH 可以再make执行间设置:
# make ARCH=ia64
# 另外一种方法是设置 ARCH 环境变量.
# 默认 ARCH 是当前执行的宿主机.
# CROSS_COMPILE 作为编译时所有执行需要使用的前缀
# 只有gcc 和 相关的 bin-utils 使用 $(CROSS_COMPILE)设置的前缀.
# CROSS_COMPILE 可以再命令行设置:
# make CROSS_COMPILE=ia64-linux-
# 另外 CROSS_COMPILE 也可以再环境变量中设置.
# CROSS_COMPILE 的默认值是空的
# Note: 一些体系的 CROSS_COMPILE 是再其 arch/*/Makefile中设置的
ARCH        ?= $(SUBARCH)
CROSS_COMPILE    ?=
# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)
KCONFIG_CONFIG    ?= .config
# SHELL used by kbuild
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
      else if [ -x /bin/bash ]; then echo /bin/bash; \
      else echo sh; fi ; fi)
HOSTCC       = gcc
HOSTCXX      = g++
HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
HOSTCXXFLAGS = -O2
# Decide whether to build built-in, modular, or both.
# Normally, just do built-in.
KBUILD_MODULES :=
KBUILD_BUILTIN := 1
#    如果仅编译模块 "make modules", 就不会编译内建的 objects.
#    当使用modversions编译 modules 时 , 就需要考虑build-in objects,
#    目的是再记录前确认 checksums 已经更新.
ifeq ($(MAKECMDGOALS),modules)
  KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
endif
#    If we have "make  modules", compile modules
#    in addition to whatever we do anyway.
#    Just "make" or "make all" shall build modules as well
ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
  KBUILD_MODULES := 1
endif
ifeq ($(MAKECMDGOALS),)
  KBUILD_MODULES := 1
endif
export KBUILD_MODULES KBUILD_BUILTIN
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
# Beautify output
# ---------------------------------------------------------------------------
#
# 一般,make再执行命令前会打印整个命令信息. 现在通过$($(quiet)$(cmd))方式
# 可以设置 $(quiet) 来选择不同的命令输出方式等.
#
#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $ /dev/null)
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
export ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
# When compiling out-of-tree modules, put MODVERDIR in the module
# tree rather than in the kernel tree. The kernel tree might
# even be read-only.
export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
# Files to ignore in find ... statements
RCS_FIND_IGNORE
:= \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name
.pc -o -name .hg -o -name .git \) -prune -o
export RCS_TAR_IGNORE :=
--exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS
--exclude .pc --exclude .hg --exclude .git
[未完,待续]
cyliu
2007-07-29 14:21
# ===========================================================================
# 下面是设置config和build 内核时共同使用的规则
# scripts里面是最基本的帮助builds,在scripts/basic目录下的makefile是所有build时都会用到的工具:fixdep/
PHONY += scripts_basic
scripts_basic:
    $(Q)$(MAKE) $(build)=scripts/basic
# 把对scripts/basic/makefile转化到scripts_basic处理
scripts/basic/%: scripts_basic ;
#这里先说说script目录里面的makefile文件作用
#makefile:配置目标,包括编译岛内核和模块方式的target
#makefile_clean:当然是删除了
#kbuild_include:一般的配置选项,会在makefile_build中调用
#makefile_build:build配置
#makefile_lib:module,vmlinux的配置
#makefile_host:配置binary
#makefile_modinst:安装module
#makefile_modpost:
PHONY += outputmakefile
# outputmakefile规则目的是在输出目录产生一个makefile文件。这会为make提供方便。这里是调用scripts/mkmakefile创建makfile文件
outputmakefile:
ifneq ($(KBUILD_SRC),)
    $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
        $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif
# 设置是.config,还是module,还是build命令
no-dot-config-targets := clean mrproper distclean \
             cscope TAGS tags help %docs check% \
             include/linux/version.h headers_% \
             kernelrelease kernelversion
config-targets := 0
mixed-targets  := 0
dot-config     := 1
ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
    ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
        dot-config := 0
    endif
endif
ifeq ($(KBUILD_EXTMOD),)
        ifneq ($(filter config %config,$(MAKECMDGOALS)),)
                config-targets := 1
                ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
                        mixed-targets := 1
                endif
        endif
endif
ifeq ($(mixed-targets),1)
# ===========================================================================
# We're called with mixed targets (*config and build targets).
# Handle them one by one.
%:: FORCE
    $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@
else
ifeq ($(config-targets),1)
# ===========================================================================
#仅配置linux
# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
# KBUILD_DEFCONFIG may point out an alternative default configuration
# used for 'make defconfig'
include $(srctree)/arch/$(ARCH)/Makefile
export KBUILD_DEFCONFIG
config %config: scripts_basic outputmakefile FORCE
    $(Q)mkdir -p include/linux include/config
    $(Q)$(MAKE) $(build)=scripts/kconfig $@
else
# ===========================================================================
# 仅编译内核
ifeq ($(KBUILD_EXTMOD),)
# Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scripts twice
# in parallel
PHONY += scripts
scripts: scripts_basic include/config/auto.conf
    $(Q)$(MAKE) $(build)=$(@)
#下面就不用说了吧
# Objects we will link into vmlinux / subdirs we need to visit
init-y        := init/
drivers-y    := drivers/ sound/
net-y        := net/
libs-y        := lib/
core-y        := usr/
endif # KBUILD_EXTMOD
ifeq ($(dot-config),1)
# Read in config
-include include/config/auto.conf
ifeq ($(KBUILD_EXTMOD),)
# Read in dependencies to all Kconfig* files, make sure to run
# oldconfig if changes are detected.
-include include/config/auto.conf.cmd
# To avoid any implicit rule to kick in, define an empty command
$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
# If .config is newer than include/config/auto.conf, someone tinkered
# with it and forgot to run make oldconfig.
# if auto.conf.cmd is missing then we are probably in a cleaned tree so
# we execute the config step to be sure to catch updated Kconfig files
include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
    $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
else
# external modules needs include/linux/autoconf.h and include/config/auto.conf
# but do not care if they are up-to-date. Use auto.conf to trigger the test
PHONY += include/config/auto.conf
include/config/auto.conf:
    $(Q)test -e include/linux/autoconf.h -a -e $@ || (        \
    echo;                                \
    echo "  ERROR: Kernel configuration is invalid.";        \
    echo "         include/linux/autoconf.h or $@ are missing.";    \
    echo "         Run 'make oldconfig && make prepare' on kernel src to fix it.";    \
    echo;                                \
    /bin/false)
endif # KBUILD_EXTMOD
else
# Dummy target needed, because used as prerequisite
include/config/auto.conf: ;
endif # $(dot-config)
cyliu
2007-07-29 14:40
# ===========================================================================
# 仅编译内核
ifeq ($(KBUILD_EXTMOD),)
# Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scripts twice
# in parallel
PHONY += scripts
scripts: scripts_basic include/config/auto.conf
    $(Q)$(MAKE) $(build)=$(@)
#下面就不用说了吧
# Objects we will link into vmlinux / subdirs we need to visit
init-y        := init/
drivers-y    := drivers/ sound/
net-y        := net/
libs-y        := lib/
core-y        := usr/
endif # KBUILD_EXTMOD
.....
all: vmlinux
#配置gcc选项
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
CFLAGS        += -Os
else
CFLAGS        += -O2
endif
....
# 缺剩的编译的内核镜像
export KBUILD_IMAGE ?= vmlinux
#
# vmlinux与map安装路径,默认时boot目录
export    INSTALL_PATH ?= /boot
#
#module安装目录
#
MODLIB    = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB
#
#  如果定义了INSTALL_MOD_STRIP,在安装module后会strip这些安装的modules
ifdef INSTALL_MOD_STRIP
ifeq ($(INSTALL_MOD_STRIP),1)
mod_strip_cmd = $(STRIP) --strip-debug
else
mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
endif # INSTALL_MOD_STRIP=1
else
mod_strip_cmd = true
endif # INSTALL_MOD_STRIP
export mod_strip_cmd
#如果不是安装module
ifeq ($(KBUILD_EXTMOD),)
core-y        += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
vmlinux-dirs    := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
             $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
             $(net-y) $(net-m) $(libs-y) $(libs-m)))
vmlinux-alldirs    := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
             $(init-n) $(init-) \
             $(core-n) $(core-) $(drivers-n) $(drivers-) \
             $(net-n)  $(net-)  $(libs-n)    $(libs-))))
init-y        := $(patsubst %/, %/built-in.o, $(init-y))
core-y        := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y    := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y        := $(patsubst %/, %/built-in.o, $(net-y))
libs-y1        := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2        := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y        := $(libs-y1) $(libs-y2)
# Build vmlinux
...
#配置syms
...
#以下是内核link时的配置
....
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/66601/showart_1150788.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP