内核版本为linux-2.6.31.14
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 31
EXTRAVERSION = .14
NAME = Man-Eating Seals of Antiquity
# *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
#####################################################################
#控制编译器参数,不用管它
#####################################################################
# 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
ifeq ("$(origin V)", "command line")
KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
KBUILD_VERBOSE = 0
endif
########################################################################################
#函数origin并不操作变量的值,只是告诉你你的这个变量是哪里来的,
#其语法是: $(origin ;)。
#注意,是变量的名字,不应该是引用。所以你最好不要在中使用“$”字符。
#origin 函数会以其返回值来告诉你这个变量的“出生情况”,
#origin函数的返回值有:
#“undefined”从来没有定义过、
#“default”是一个默认的定义、
#“environment”是一个环境变量、
#“file”这个变量被定义在Makefile中、
#“command line”这个变量是来自命令行的、
#“override”是被override指示符重新定义的、
#“automatic”是一个命令运行中的自动化变量
#
#这些信息对于我们编写 Makefile 是非常有用的,例如,在这里我们make命令后跟了一个参数“V”,
#而我们的环境中也有一个环境变量“V”,此时,我们想判断一下,如果变量来源于参数,
#那么我们就把之重定义了,如果来源于非命令行或环境变量,那么我们就不重新定义它。
#
#KBUILD_VERBOSE的值根据在命令行中是否定义了变量V,
#当没有定义时,默认为V=0,输出为short version;
#可以用make V=1 来输出全部的命令。
######################################################################
# 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.
ifeq ("$(origin C)", "command line")
KBUILD_CHECKSRC = $(C)
endif
ifndef KBUILD_CHECKSRC
KBUILD_CHECKSRC = 0
endif
########################################################################################
# make C=1 仅检查被编辑过的文件
# make C=2 强制检查所有文件
########################################################################################
# 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
ifdef SUBDIRS
KBUILD_EXTMOD ?= $(SUBDIRS)
endif
ifeq ("$(origin M)", "command line")
KBUILD_EXTMOD := $(M)
endif
########################################################################################
#编译驱动的时候经常用到的makefile为
#all:
# make -C $(KERN_DIR) M=`pwd` modules
#
# -C $(KERN_DIR) 到内核源码目录下读取那里的Makefile;
# M=$(PWD) 然后返回到当前目录继续读入、执行当前的Makefile。
#这里就是判断make后面是否定义了M
########################################################################################
# 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_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),)
# OK, Make called in directory where kernel src resides
# Do we want to locate output files in a separate directory?
ifeq ("$(origin O)", "command line")
KBUILD_OUTPUT := $(O)
endif
########################################################################################
#可以把Makefele的输出指定到特定的文件夹中
#例如:make O=dir/to/store/output/files/
########################################################################################
# That's our default target when none is given on the command line
PHONY := _all
_all:
########################################################################################
#PHONY里的都是伪目标
#Makefile中同名的目标会被后面的覆盖,这不是最后一个_all,所以这个_all没用
########################################################################################
# Cancel implicit rules on top Makefile
$(CURDIR)/Makefile Makefile: ;
########################################################################################
#取消makefile的隐含规则
#神马是隐含规则呢?不去管了,晕头了
########################################################################################
ifneq ($(KBUILD_OUTPUT),)
########################################################################################
#KBUILD_OUTPUT为空,条件不成立
########################################################################################
# Invoke a second make in the output directory, passing relevant variables
# check that the output directory actually exists
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) sub-make
$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
$(Q)@:
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
skip-makefile := 1
endif # ifneq ($(KBUILD_OUTPUT),)
########################################################################################
#KBUILD_OUTPUT为空,所以以上这段代码不执行
########################################################################################
endif # ifeq ($(KBUILD_SRC),)
# We process the rest of the Makefile if this is the final invocation of make
ifeq ($(skip-makefile),)
# If building an external module we do not care about the all: rule
# but instead _all depend on modules
PHONY += all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif
########################################################################################
#KBUILD_EXTMOD叫做Kbuild扩展模式,如果我们make M=dir,那么会将变量KBUILD_EXTMOD的值设置为dir,
#随后去执行依赖于modules的代码,就相当于执行make modules。
#这个make方法也是用来提高我们的驱动开发效率的,如果你只想编译某个具体的驱动,
#只要指定对应的子目录,就可以只编译这个驱动而不去碰其他的内核代码了。
#
#这里直接跳去执行all的代码了
########################################################################################
我们直接来看看all的代码,在top makefile中搜索all有两个结果
all: vmlinux
ifdef CONFIG_MODULES
all: modules
这下只省一个all了,但是,不要忘了makefile也能包含文件
在第一个all下面include了一个$(srctree)/arch/$(SRCARCH)/Makefile文件,把这个all给覆盖了,所以我们执行的是include文件中的all代码进去看看
# Default kernel to build
all: bzImage
# KBUILD_IMAGE specify target image being built
KBUILD_IMAGE := $(boot)/bzImage
bzImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
$(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot
$(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/$(UTS_MACHINE)/boot/$@
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
ifdef CONFIG_HEADERS_CHECK
$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
endif
ifdef CONFIG_SAMPLES
$(Q)$(MAKE) $(build)=samples
endif
ifdef CONFIG_BUILD_DOCSRC
$(Q)$(MAKE) $(build)=Documentation
endif
$(call vmlinux-modpost)
$(call if_changed_rule,vmlinux__)
$(Q)rm -f .old_version
PHONY += FORCE
FORCE:
定义于makefile的最后,是个命令和依赖都为空的伪目标,作用是尽管vmlinux存在,其他依赖没有更新,命令也会被执行
再来看看vmlinux的其他依赖
vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds
export KBUILD_VMLINUX_OBJS := $(vmlinux-all)
modpost-init := $(filter-out init/built-in.o, $(vmlinux-init))
vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE
$(call if_changed_rule,vmlinux-modpost)
ifdef CONFIG_KALLSYMS_EXTRA_PASS
last_kallsyms := 3
else
last_kallsyms := 2
endif
kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
他们三个都依赖于vmlinux-dirs
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-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
scripts: scripts_basic include/config/auto.conf
$(Q)$(MAKE) $(build)=$(@)
PHONY += scripts_basic
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
再来看prepare
prepare: prepare0
prepare0: archprepare FORCE
$(Q)$(MAKE) $(build)=.
$(Q)$(MAKE) $(build)=. missing-syscalls
archprepare: prepare1 scripts_basic
prepare1: prepare2 include/linux/version.h include/linux/utsrelease.h \
include/asm include/config/auto.conf
$(cmd_crmodverdir)
prepare2: prepare3 outputmakefile
outputmakefile:
ifneq ($(KBUILD_SRC),)
$(Q)ln -fsn $(srctree) source
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
$(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif
prepare3: include/config/kernel.release
ifneq ($(KBUILD_SRC),)
@$(kecho) ' Using $(srctree) as source for kernel'
$(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
echo " $(srctree) is not clean, please run 'make mrproper'";\
echo " in the '$(srctree)' directory.";\
/bin/false; \
fi;
$(Q)if [ ! -d include2 ]; then \
mkdir -p include2; \
ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm; \
fi
endif
include/config/kernel.release: include/config/auto.conf FORCE
$(Q)rm -f $@
$(Q)echo $(kernelrelease) > $@
include/config/auto.conf: ;