Kernel顶层Makefile文件分析

注: 基于Linux 2.6.25
新函数

origin函数
简介:函数origin并不操作变量的值,只是告诉你这个变量是来自哪里
语法:$(origin <variable>)
返回值:
"undefined":在这前还没有定已过
"default":默认的定义。。不太明白
"environment":来自环境变量
"file":变量被定义在makefile文件内
"commandline":是在环境变量中定义
"override":是被override指示符重新定义的
"automatic":是一个命令运行中的自动化变量,这个也不太懂

error函数
简介:输出错误信息,并且退出执行
语法: $(error <String>)

shell函数
简介:执行shell命令
语法: $(shell <Shell Command String>)

if 函数
简介: 一个简单if else
语法:
if <condition>,<then-part>
if <condition>,<then-part>,<else-part>

?= 条件复制
简介: 如果变量在之前未赋值,则对他赋值
语法: VAR1 ?= $

= 赋值

:= 赋值

+= 赋值

语法:$(findstring <targetStr>, <srcStr>)
描述:在srcStr中查找targetStr,如果找到回返回些什么,如果没找到,返回空

语法:$(dir <filepath>)
描述:获取filepath中的目录部分,如/foo/bar.c,返回/foo

语法:$(notdir <filepath>)
描述:获取filepath中除去目录的部分,如/foo/bar.c,返回bar.c

语法:$(basename <filepath>)
描述:去掉filepath中的.extension扩展名

VERSION = 2               #主版本号
PATCHLEVEL = 6            #次版本号
SUBLEVEL = 25             #子版本号
EXTRAVERSION =            #额外版本号
NAME = Funky Weasel is Jiggy wit it    #此版本的名字

# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
# More info can be located in ./README
# Comments in this file are targeted only to the developer, do not
# expect to learn how to build the kernel reading this file.

# Do not:
# o  use make's built-in rules and variables
#    (this increases performance and avoids hard-to-debug behaviour);
# o  print "Entering directory ...";
MAKEFLAGS += -rR --no-print-directory  # 设置Make不使用内置的规则和变量,并且在递归进行编译的时候,不打印"Entering directory"

# We are using a recursive build, so we need to do a little thinking
# to get the ordering right.
#
# Most importantly: sub-Makefiles should only ever modify files in
# their own directory. If in some directory we have a dependency on
# a file in another dir (which doesn't happen often, but it's often
# unavoidable when linking the built-in.o targets which finally
# turn into vmlinux), we will call a sub make in that other dir, and
# after that we are sure that everything which is in that other dir
# is now up to date.
#
# The only cases where we need to modify files which have global
# effects are thus separated out and done before the recursive
# descending is started. They are now explicitly listed as the
# prepare rule.

# To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commands

# 设置打印消息级别,通过调用make 时添加的参数V=NUM来修改
ifdef V
  ifeq ("$(origin V)", "command line")
    KBUILD_VERBOSE = $(V)
  endif
endif
# 默认的KBUILD_VERBOSE的值被设置为0,也就意味着在编译过程中,只输出
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

# Call a source code checker (by default, "sparse") as part of the
# C compilation.
#
# Use 'make C=1' to enable checking of only re-compiled files.
# Use 'make C=2' to enable checking of *all* source files, regardless
# of whether they are re-compiled or not.
#
# See the file "Documentation/sparse.txt" for more details, including
# where to get the "sparse" utility.

# 设置语法检查级别,默认级别为0
ifdef C
  ifeq ("$(origin C)", "command line")
    KBUILD_CHECKSRC = $(C)
  endif
endif
ifndef KBUILD_CHECKSRC
   KBUILD_CHECKSRC = 0
endif

# Use make M=dir to specify directory of external module to build
# Old syntax make ... SUBDIRS=$PWD is still supported
# Setting the environment variable KBUILD_EXTMOD take precedence
# 下面是为了支持旧语法格式的Makefile的设置,不用理。
ifdef SUBDIRS
  KBUILD_EXTMOD ?= $(SUBDIRS)
endif
ifdef M
  ifeq ("$(origin M)", "command line")
     KBUILD_EXTMOD := $(M)
  endif
endif


# kbuild supports saving output files in a separate directory.
# To locate output files in a separate directory two syntaxes are supported.
# In both cases the working directory must be the root of the kernel src.
# 1) O=
# Use "make O=dir/to/store/output/files/"
#
# 2) Set KBUILD_OUTPUT
# Set the environment variable KBUILD_OUTPUT to point to the directory
# where the output files shall be placed.
# export KBUILD_OUTPUT=dir/to/store/output/files/
# make
#
# The O= assignment takes precedence over the KBUILD_OUTPUT environment
# variable.
#上面这里是介绍可以设置kbuild过程中的输出文件目的地址,有两种方式,一种是在make 参数中设置(make -O dir),第二种方式是设置环境变量(export KBUILD_OUTPU=dir)

# KBUILD_SRC is set on invocation of make in OBJ directory
# KBUILD_SRC is not intended to be used by the regular user (for now)
ifeq ($(KBUILD_SRC),)  #如果KBUILD_SRC值为空,就执行下面的操作,正常情况下要执行
#上面说的这个功能当前对一般用户没有用,那就先不理了

# OK, Make called in directory where kernel src resides
# Do we want to locate output files in a separate directory?
#这个不是应该是和上面那大堆注释对应的吗?怎么放到了这里。。功能就是如果命令行中定义了O变量来修改输出目录,就用用户定义的这个目录。
ifdef O
  ifeq ("$(origin O)", "command line")
    KBUILD_OUTPUT := $(O)
  endif
endif


# That's our default target when none is given on the command line
#这里不太懂,大概意思是如果make没有给出任意参数,就执行这个默认的
PHONY := _all
_all:

# Cancel implicit rules on top Makefile
#取消隐式推倒原则,不懂有什么用
$(CURDIR)/Makefile Makefile: ;

# 如果输出目录值不为空,正常情况下进入
ifneq ($(KBUILD_OUTPUT),)
# Invoke a second make in the output directory, passing relevant variables
# check that the output directory actually exists
# 上面说在输出目录中执行第二个make命令,传入相关变量,并且检查输出目录是否存在
# 下面的
saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
$(if $(KBUILD_OUTPUT),, \
     $(error output directory "$(saved-output)" does not exist))

# MAKECMDGOALS 是make的一个环境变量,保存所有目标列表
# 下面这个命令将所有指明的目标列表和sub-make加入到PHONY中
PHONY += $(MAKECMDGOALS) sub-make

# 下面这个命令很是不明白,大概是用来过滤,太复杂了
# 简单分析下,过滤掉MAKECMDGOALS中的_all sub-make和$(CURDIR)/Makefile,并将它们都赋值为sub-make
$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
$(Q)@:

# 这个就是sub-make的值,大致就是将顶层Makefile定义的规则传给下层文件夹中的Makefile中
sub-make: FORCE
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
KBUILD_SRC=$(CURDIR) \
KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile \
$(filter-out _all sub-make,$(MAKECMDGOALS))

# Leave processing to above invocation of make
# 表示执行完了子makefile,返回顶层make
skip-makefile := 1
endif # ifneq ($(KBUILD_OUTPUT),)  #结束ifneq
endif # ifeq ($(KBUILD_SRC),)      #结束ifeq

# We process the rest of the Makefile if this is the final invocation of make
# 表示如果skip-makefile为空,这按照分类执行,也就是不是整体进行make
ifeq ($(skip-makefile),)

# If building an external module we do not care about the all: rule
# but instead _all depend on modules
# 如果make 外部模块,就不用执行all,之编译模块就可以了
PHONY += all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif

# 将srctree设置为源码根目录
srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
TOPDIR := $(srctree)
# FIXME - TOPDIR is obsolete, use srctree/objtree
# 将objtree设定位当前目录
objtree := $(CURDIR)
# 将src设置为源码根目录
src := $(srctree)
将obj设定位当前目录
obj := $(objtree)

VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))

# 将上面这些变量输出为环境变量,可以给子makefile贡献
export srctree objtree VPATH TOPDIR


# SUBARCH tells the usermode build what the underlying arch is.  That is set
# first, and if a usermode build is happening, the "ARCH=um" on the command
# line overrides the setting of ARCH below.  If a native build is happening,
# then ARCH is assigned, getting whatever value it gets normally, and 
# SUBARCH is subsequently ignored.
# 获取CPU的具体型号,存在SUBARCH中,SUBARCH代表Host的架构
# sed -e -s/i.86/i386,表示匹配i.86的用i386替换
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/ \
  -e s/sh.*/sh/ )

# Cross compiling and selecting different set of gcc/bin-utils
# ---------------------------------------------------------------------------
#
# When performing cross compilation for other architectures ARCH shall be set
# to the target architecture. (See arch/* for the possibilities).
# ARCH can be set during invocation of make:
# make ARCH=ia64
# Another way is to have ARCH set in the environment.
# The default ARCH is the host where make is executed.
# 当执行交叉编译的时候,要将ARCH的值设置为目标的架构,支持的交媾可以在arch目录下看到
# ARCH可以在执行make命令时设置,如make ARCH=arm
# 默认的ARCH是和Host相同


# CROSS_COMPILE specify the prefix used for all executables used
# during compilation. Only gcc and related bin-utils executables
# are prefixed with $(CROSS_COMPILE).
# CROSS_COMPILE can be set on the command line
# make CROSS_COMPILE=ia64-linux-
# Alternatively CROSS_COMPILE can be set in the environment.
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
# 下面是处理交叉编译这块的,交叉编译需要知道Host的架构和Target的架构吧
# CROSS_COMPILE是编译时所有命令的前缀,可以在执行make的时候指定如make CROSS_COMPILE=ia64-linux-
# CROSS_COMPILE也可以通过环境变量来设定
# 默认情况下是不需要CROSS_COMPILE来执行的,也就是不交叉编译
export KBUILD_BUILDHOST := $(SUBARCH)  # 将Host架构与子Make共享
ARCH ?= $(SUBARCH)   # 默认Host的架构与Target架构相同
CROSS_COMPILE ?=              # 默认CROSS_COMPILE为空

#下面不知哪里调用
# Architecture as present in compile.h
UTS_MACHINE  := $(ARCH)
SRCARCH  := $(ARCH)

#对x86结构的特殊照顾,不明白原因
# Additional ARCH settings for x86
ifeq ($(ARCH),i386)
        SRCARCH := x86
endif
ifeq ($(ARCH),x86_64)
        SRCARCH := x86
endif

# 声称的配置文件名
KCONFIG_CONFIG ?= .config

# 设定kbuild使用的Shell
# 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)

# 设定编译器,和全局编译FLAGS
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.
# 下面决定是只编译build-in或modular,也可两个都编译
# 通常情况下,只编译built-in

KBUILD_MODULES :=
KBUILD_BUILTIN := 1  # 编译built-in

# If we have only "make modules", don't compile built-in objects.
# When we're building modules with modversions, we need to consider
# the built-in objects during the descend as well, in order to
# make sure the checksums are up to date before we record them.
# 如果只是make modules的话,就不要编译built-in objects

# 如果执行的是 make modules ,则在这里重新设置KBUILD_BUILTIN := 1
ifeq ($(MAKECMDGOALS),modules)
  KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
endif

# If we have "make <whatever> modules", compile modules
# in addition to whatever we do anyway.
# Just "make" or "make all" shall build modules as well
# 如果执行的是make all/_all/modules有额外goal,则KBUILD_MODULES := 1
ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
  KBUILD_MODULES := 1
endif

# 只执行make,KBUILD_MODULES := 1
ifeq ($(MAKECMDGOALS),)
  KBUILD_MODULES := 1
endif

# 导出给子make
export KBUILD_MODULES KBUILD_BUILTIN
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD

# Beautify output
# ---------------------------------------------------------------------------
#
# Normally, we echo the whole command before executing it. By making
# that echo $($(quiet)$(cmd)), we now have the possibility to set
# $(quiet) to choose other forms of output instead, e.g.
#
#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@       这个是简化版的输出
#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<   这个是原版的输出
#
# If $(quiet) is empty, the whole command will be printed.
# If it is set to "quiet_", only the short version will be printed. 
# If it is set to "silent_", nothing will be printed at all, since
# the variable $(silent_cmd_cc_o_c) doesn't exist.
#
# 下面这里不太清楚, $(Q)用作前缀,如果$(Q)=@表示不回显,为空表示回显
# A simple variant is to prefix commands with $(Q) - that's useful
# for commands that shall be hidden in non-verbose mode.
#
# $(Q)ln $@ :<
#
# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
# If KBUILD_VERBOSE equals 1 then the above command is displayed.

# 美化编译过程中输出
# 如果$(quiet)为空,则输出原版编译命令
# 如果$(quiet)为quiet_,则输出简化版本的
# 如果$(quiet)为silent_,则任何都不输出,因为slient_cmd_cc_o_cc根本不存在
# 不过有个全局的控制,如果KBUILD_VERBOSE为0,则输出简化版本,如果为1,则输出简化版本
ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif

# If the user is running make -s (silent mode), suppress echoing of
# commands
# 如果用户用户调用make -s,也就是slient模式,设
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值