linux kernel makefile 分析 - 1
背景说明
版本:
5.10.0 - 下面分析中 使用的行号,都是 参考 这个 版本的 Makefile 。
在线浏览: https://lxr.missinglinkelectronics.com/linux/Makefile
使用场景:
在源码文件夹下面建立一个build 文件夹,然后使用 O=build
mkdir build
make O=build
三部分的框架
第一部分:1 ~ 36 行 , 1950 ~ 结束 ; 通用部分,
1、定义 VERSION PATCHLEVEL SUBLEVEL EXTRALEVEL NAME 变量
2、make 命令行中如果指定了以 双下划线 __ 开头的目标,则报错。
3、定义伪目标 __all ;
4、定义 FORCE 伪目标,
6、将 PHONY 变量中的目标,都声明为 phony 。
第二部分:37~ 188 行,使用 sub_make_done 不为 1 时才进入。只有第一次使用 Makefile 时,这个变量才不为 1,因为在 174 行会 设置这个变量为 1 ,并且导出。之后启动的 make 都得到这个变量为 1.
1、让 make 不要使用 内置规则和内置变量。
2、处理 LC_ALL LC_COLLATE LC_NUMERIC。
3、GREP_OPTIONS 置为空,
4、设置 Q quiet KBUILD_VERBOSE 变量。
5、得到 abs_objtree 的值
6、abs_srctree - 源码绝对路径
7、this_makefile 赋值
8、need-sub-make 的赋值
9 need-sub-make 为 1 ,启动 sub make
191 ~ 1948 行,使用 need-sub-make 为空时进入,即 不需要启动 sub make 时使用 191 ~ 1948 之间的内容。
本位不涉及,后面再分析
通用部分
1、定义 VERSION PATCHLEVEL SUBLEVEL EXTRALEVEL NAME 变量
2VERSION = 5 3PATCHLEVEL = 10 4SUBLEVEL = 0 5EXTRAVERSION = 6NAME = Kleptomaniac Octopus
2、make 命令行中如果指定了以 双下划线 __ 开头的目标,则报错。 __开头的目标都作为 内部中间目标使用。
14$(if $(filter __%, $(MAKECMDGOALS)), \ 15 $(error targets prefixed with '__' are only for internal use))
3、定义伪目标 __all ;因为命令行如果没指定目标,则Makefile 中遇到的第一个目标就是默认目标。
17# That's our default target when none is given on the command line 18PHONY := __all 19__all:
4、定义 FORCE 伪目标,依赖FORCE 的目标,都需要 无条件 重新 更新。
1950PHONY += FORCE
1951FORCE:
6、将 PHONY 变量中的目标,都声明为 phony 。 【声明为 phony 目标,make 就不会 把这个目标当作文件目标】
1953# Declare the contents of the PHONY variable as phony. We keep that 1954# information in a variable so we can use it in if_changed and friends. 1955.PHONY: $(PHONY)
首次使用包含内容
1、让 make 不要使用 内置规则和内置变量。39 ~ 41 通过设置 MAKEFLAGS=-rR实现. 154 ~ 161 如果make版本是 3.x ,设置后,不能立即生效,需要启动sub make 才生效。
39# Do not use make's built-in rules and variables 40# (this increases performance and avoids hard-to-debug behaviour) 41MAKEFLAGS += -rR 154ifneq ($(abs_srctree),$(abs_objtree)) 155# Look for make include files relative to root of kernel src 156# 157# This does not become effective immediately because MAKEFLAGS is re-parsed 158# once after the Makefile is read. We need to invoke sub-make. 159MAKEFLAGS += --include-dir=$(abs_srctree) 160need-sub-make := 1 161endif
2、处理 LC_ALL LC_COLLATE LC_NUMERIC。
( 编译机器 本身的 LC 环境可能千差万别,kernel 中代码不能都考虑。换思路:kernel 中的代码默认一个 LC环境,在这儿的Makefile 中,将LC环境设置为kernel 代码需要LC 环境 )
LC_ALL 选择 整体的 C 语言环境; 置为空。
LC_COLLATE 选择 排序(归类)的环境
LC_NUMERIC 选择 数字格式 的环境。 德国数字环境,小数点 使用 逗号。
43# Avoid funny character set dependencies 44unexport LC_ALL 45LC_COLLATE=C 46LC_NUMERIC=C 47export LC_COLLATE LC_NUMERIC
3、GREP_OPTIONS 置为空,因为 这个会影响 grep 工具的输出,kernel 编译会用到 grep 工具。编译机器上面 GREP_OPTIONS 影响了grep 输出,kernel 就得不到自己想要的输出格式或内容了,所以,这儿置为空,保证grep 输出是 kernel 预期的内容。
49# Avoid interference with shell env settings 50unexport GREP_OPTIONS
4、设置 Q quiet KBUILD_VERBOSE 变量。
4.1 82 行 默认为 KBUILD_VERBOSE=0, , 90 91 行也就默认 Q=@ ; quiet=quiet_;
4.2 当命令行指定了 V=1时, KBUILD_VERBOSE=1, Q为空 ; quiet 为空; 会 输出 执行的命令。
4.3 命令行指定 V=2时, KBUILD_VERBOSE=2, Q为@ ; quiet=quiet_ ; 会打印为什么更新这个目标(但不会打印 执行的命令 )
4.2 当命令行指定了 -s 时,为silent mode , 抑制 echo cmd. 强制修改 quiet=silent_ ; ( KBUILD_VERBOSE 和 Q 依然参照 4.1 4.2 4.3 )
72# If KBUILD_VERBOSE equals 0 then the above command will be hidden. 73# If KBUILD_VERBOSE equals 1 then the above command is displayed. 74# If KBUILD_VERBOSE equals 2 then give the reason why each target is rebuilt. 75# 76# To put more focus on warnings, be less verbose as default 77# Use 'make V=1' to see the full commands 78 79ifeq ("$(origin V)", "command line") 80 KBUILD_VERBOSE = $(V) 81endif 82ifndef KBUILD_VERBOSE 83 KBUILD_VERBOSE = 0 84endif 85 86ifeq ($(KBUILD_VERBOSE),1) 87 quiet = 88 Q = 89else 90 quiet=quiet_ 91 Q = @ 92endif 93 94# If the user is running make -s (silent mode), suppress echoing of 95# commands 96 97ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),) 98 quiet=silent_ 99endif 100 101export quiet Q KBUILD_VERBOSE
5、得到 abs_objtree 的值
5.1 138 行,如果命令行 没有使用 O=dir 指定 输出文件存放目录,则 abs_objdir=$(CURDIR)
5.2 如果命令行使用了O=dir指定了,就将abs_objdir 赋值为 指定 dir 的绝对路径(如果dir是符号链接,找到真实路径)。具体如下:
123 ~ 126 判断命令行有O=dir ,设置KBUILD_OUTPUT
128 发现 KBUILD_OUTPUT 不为空,131 行赋值 abs_objtree 为指定的dir的绝对路径
132 ~ 133 检查 abs_objtree 不为空,如果为空(可能原因是文件夹不存在),就报错。
136 ,如果是符号链接,转换为真实路径。
123# Do we want to change the working directory? 124ifeq ("$(origin O)", "command line") 125 KBUILD_OUTPUT := $(O) 126endif 127 128ifneq ($(KBUILD_OUTPUT),) 129# Make's built-in functions such as $(abspath ...), $(realpath ...) cannot 130# expand a shell special character '~'. We use a somewhat tedious way here. 131abs_objtree := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) && pwd) 132$(if $(abs_objtree),, \ 133 $(error failed to create output directory "$(KBUILD_OUTPUT)")) 134 135# $(realpath ...) resolves symlinks 136abs_objtree := $(realpath $(abs_objtree)) 137else 138abs_objtree := $(CURDIR) 139endif # ifneq ($(KBUILD_OUTPUT),)
6、abs_srctree - 源码绝对路径 - 赋值并检查(不包含空格,冒号)
148abs_srctree := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) 149 150ifneq ($(words $(subst :, ,$(abs_srctree))), 1) 151$(error source directory cannot contain spaces or colons) 152endif
7、this_makefile 赋值
163 this-makefile := $(lastword $(MAKEFILE_LIST))
8、need-sub-make 的赋值
这个默认为空。
赋值为 1 的情况有 3 中。
a: make版本是 3.x , 需要让 MAKEFLAGS=-rR 生效。参考 本节 1 。
b: abs_objtree 和 $(CURDIR) 不相同。 144 else 进入,145 行 赋值。
141ifeq ($(abs_objtree),$(CURDIR)) 142# Suppress "Entering directory ..." unless we are changing the work directory. 143MAKEFLAGS += --no-print-directory 144else 145need-sub-make := 1 146endif
c: abs_objtree 和 abs_srctree 不相同。 154 判断,160 赋值。
154ifneq ($(abs_srctree),$(abs_objtree)) 155# Look for make include files relative to root of kernel src 156# 157# This does not become effective immediately because MAKEFLAGS is re-parsed 158# once after the Makefile is read. We need to invoke sub-make. 159MAKEFLAGS += --include-dir=$(abs_srctree) 160need-sub-make := 1 161endif
9 need-sub-make 为 1 ,启动 sub make
176 行判断,进入
178 行 声明 __sub-make 伪目标
180 行,让命令行目标 默认目标 __all 和 $(this-makefile) 目标都依赖 __sub-make 伪目标
184 ·~ 186 定义 __sub-make 伪目标的更新命令,启动 下一个make 并指定makefile ,将 命令行目标也传递给它。
176ifeq ($(need-sub-make),1) 177 178PHONY += $(MAKECMDGOALS) __sub-make 179 180$(filter-out $(this-makefile), $(MAKECMDGOALS)) __all: __sub-make 181 @: 182 183# Invoke a second make in the output directory, passing relevant variables 184__sub-make: 185 $(Q)$(MAKE) -C $(abs_objtree) -f $(abs_srctree)/Makefile $(MAKECMDGOALS) 186 187endif # need-sub-make
最后一次进入包含内容
这部分内容较多,一步步慢慢来分解
下一篇: https://www.cnblogs.com/zhangzhiwei122/p/16025969.html