@cyysu
2017-10-16T08:27:21.000000Z
字数 6705
阅读 1671
- 时间:2017年10月16日
- 作者:Kali
- 邮箱:cyysu.github.io@gmail.com
- 版本:3.0
- 描述:Makefile-项目三,Linux 4.4 Makefile讲解,同时还可以了解Linux的编译过程
Makefile系列教程
# 在本此项目中先给出前250行内容,我们慢慢分析这个顶层MakefileVERSION = 4PATCHLEVEL = 4SUBLEVEL = 92EXTRAVERSION =NAME = Blurry Fish Butt# *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.# o Do not use make's built-in rules and variables# (this increases performance and avoids hard-to-debug behaviour);# o Look for make include files relative to root of kernel src# 这里-r表示禁止使用隐含规则 -R禁止使用任何作用于变量上的隐含规则MAKEFLAGS += -rR --include-dir=$(CURDIR)# Avoid funny character set dependencies# Makefile中的变量设置,如果不想传递变量到下一级的Makefile就可以采用unexport# 如果想传递所有的变量,直接写export# 但是Makefile中SHELL变量和MAKEFLAGS变量总是会传递到下一级Makefileunexport LC_ALLLC_COLLATE=CLC_NUMERIC=Cexport LC_COLLATE LC_NUMERIC# Avoid interference with shell env settingsunexport GREP_OPTIONS# 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.# 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.## 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.## To put more focus on warnings, be less verbose as default# Use 'make V=1' to see the full commands# 这里时为了控制是否打印信息,我们这个makefile 1000多行,如果那个过程出现了错误肯定需要调试的# origin函数表示判断这个变量的来源ifeq ("$(origin V)", "command line")KBUILD_VERBOSE = $(V)endififndef KBUILD_VERBOSEKBUILD_VERBOSE = 0endif# 这里的Q就表示不回显命令,只会显示结果ifeq ($(KBUILD_VERBOSE),1)quiet =Q =elsequiet=quiet_Q = @endif# If the user is running make -s (silent mode), suppress echoing of# commands# 这个filter函数我们前面就知道了,ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4# firstword为取首单词函数ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)quiet=silent_endifelse # make-3.8xifneq ($(filter s% -s%,$(MAKEFLAGS)),)quiet=silent_endifendifexport quiet Q KBUILD_VERBOSE# 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# That's our default target when none is given on the command linePHONY := _all_all:# Cancel implicit rules on top Makefile# 取消隐式推倒规则$(CURDIR)/Makefile Makefile: ;# 将$(CURDIR)中的:变成空格,然后查看里面的参数个数ifneq ($(words $(subst :, ,$(CURDIR))), 1)$(error main directory cannot contain spaces nor colons)endififneq ($(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 mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \&& /bin/pwd)$(if $(KBUILD_OUTPUT),, \$(error failed to create output directory "$(saved-output)"))# make的环境变量叫MAKECMDGOALS,这个变量会存放你所指定的终极目标的列表。如果在命令行中没有指定目标,那么这个变量是空值PHONY += $(MAKECMDGOALS) sub-make# filter-out为Makefile反过滤函数$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make@:# 这个就是进入子目录进行编译了 $(filter-out _all sub-make,$(MAKECMDGOALS) 这个就是向make传递的参数了sub-make: FORCE$(Q)$(MAKE) -C $(KBUILD_OUTPUT) KBUILD_SRC=$(CURDIR) \-f $(CURDIR)/Makefile $(filter-out _all sub-make,$(MAKECMDGOALS))# Leave processing to above invocation of makeskip-makefile := 1endif # ifneq ($(KBUILD_OUTPUT),)endif # ifeq ($(KBUILD_SRC),)# We process the rest of the Makefile if this is the final invocation of makeifeq ($(skip-makefile),)# Do not print "Entering directory ...",# but we want to display it when entering to the output directory# so that IDEs/editors are able to understand relative filenames.# 设置不打印进入目录和离开目录信息MAKEFLAGS += --no-print-directory# 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_CHECKSRCKBUILD_CHECKSRC = 0endif# 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 SUBDIRSKBUILD_EXTMOD ?= $(SUBDIRS)endififeq ("$(origin M)", "command line")KBUILD_EXTMOD := $(M)endif# 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: modulesendififeq ($(KBUILD_SRC),)# building in the source treesrctree := .elseifeq ($(KBUILD_SRC)/,$(dir $(CURDIR)))# building in a subdirectory of the source treesrctree := ..elsesrctree := $(KBUILD_SRC)endifendifobjtree := .src := $(srctree)obj := $(objtree)# 设置依赖查找路径VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))export srctree objtree VPATH# 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.# uname -m 查看系统的架构,这个函数的作用时如果在编译Linux内核时不指定架构那么顶层Makefile就会自动获取SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \-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[234].*/sh/ -e s/aarch64.*/arm64/ )
支付宝 微信