linux内核makefile——寻找第一个target

来源:互联网 发布:apache怎么读 编辑:程序博客网 时间:2024/04/24 12:22

内核版本为linux-2.6.31.14


VERSION = 2PATCHLEVEL = 6SUBLEVEL = 31EXTRAVERSION = .14NAME = 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 commandsifeq ("$(origin V)", "command line")  KBUILD_VERBOSE = $(V)endififndef KBUILD_VERBOSE  KBUILD_VERBOSE = 0endif#########################################################################################函数origin并不操作变量的值,只是告诉你你的这个变量是哪里来的,#其语法是: $(origin <variable>;)。#注意,<variable>是变量的名字,不应该是引用。所以你最好不要在<variable>中使用“$”字符。#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)endififndef KBUILD_CHECKSRC  KBUILD_CHECKSRC = 0endif######################################################################################### 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 precedenceifdef SUBDIRS  KBUILD_EXTMOD ?= $(SUBDIRS)endififeq ("$(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 linePHONY := _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 existssaved-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 makeskip-makefile := 1endif # ifneq ($(KBUILD_OUTPUT),)#########################################################################################KBUILD_OUTPUT为空,所以以上这段代码不执行########################################################################################endif # ifeq ($(KBUILD_SRC),)# We process the rest of the Makefile if this is the final invocation of makeifeq ($(skip-makefile),)# If building an external module we do not care about the all: rule# but instead _all depend on modulesPHONY += allifeq ($(KBUILD_EXTMOD),)_all: allelse_all: modulesendif#########################################################################################KBUILD_EXTMOD叫做Kbuild扩展模式,如果我们make M=dir,那么会将变量KBUILD_EXTMOD的值设置为dir,#随后去执行依赖于modules的代码,就相当于执行make modules。#这个make方法也是用来提高我们的驱动开发效率的,如果你只想编译某个具体的驱动,#只要指定对应的子目录,就可以只编译这个驱动而不去碰其他的内核代码了。##这里直接跳去执行all的代码了########################################################################################

我们直接来看看all的代码,在top makefile中搜索all有两个结果

all: vmlinux

ifdef CONFIG_MODULESall: modules

CONFIG_MODULES为空,第二个被忽略

这下只省一个all了,但是,不要忘了makefile也能包含文件

在第一个all下面include了一个$(srctree)/arch/$(SRCARCH)/Makefile文件,把这个all给覆盖了,所以我们执行的是include文件中的all代码

进去看看

# Default kernel to buildall: bzImage# KBUILD_IMAGE specify target image being builtKBUILD_IMAGE := $(boot)/bzImagebzImage: 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/$@

all依赖于bzImage,bzImage又依赖于vmlinux,我们还是回到top makefile中看看vmlinux吧

vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCEifdef CONFIG_HEADERS_CHECK$(Q)$(MAKE) -f $(srctree)/Makefile headers_checkendififdef CONFIG_SAMPLES$(Q)$(MAKE) $(build)=samplesendififdef CONFIG_BUILD_DOCSRC$(Q)$(MAKE) $(build)=Documentationendif$(call vmlinux-modpost)$(call if_changed_rule,vmlinux__)$(Q)rm -f .old_version

依赖好多......我们先来看看最简单的FORCE
PHONY += FORCEFORCE:
定义于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.ldsexport 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_PASSlast_kallsyms := 3elselast_kallsyms := 2endifkallsyms.o := .tmp_kallsyms$(last_kallsyms).o

所有的依赖文件都找出来了,这样就结束了么?想的太简单了,在makefile中还有这么一行

$(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还有依赖

$(vmlinux-dirs): prepare scripts$(Q)$(MAKE) $(build)=$@


先看scripts吧
scripts: scripts_basic include/config/auto.conf$(Q)$(MAKE) $(build)=$(@)

PHONY += scripts_basicscripts_basic:$(Q)$(MAKE) $(build)=scripts/basic

其中auto.conf是配置时生成的文件


再来看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.releaseifneq ($(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;     \fiendif

include/config/kernel.release: include/config/auto.conf FORCE$(Q)rm -f $@$(Q)echo $(kernelrelease) > $@


include/config/auto.conf: ;

千辛万苦,最终我们终于找到了第一个target。


















0 0