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 

 

posted @ 2022-03-19 11:43  张志伟122  阅读(374)  评论(0编辑  收藏  举报