linux kernel Makefile编译流程分析

 

博客已迁移,新博客地址:https://www.wxtechblog.com

 

1. 文章说明

 

内核版本号为:4.11.4,针对x86平台,前提是存在.config文件
需要读者有基础Makefile知识
分析只输入make命令时的情形,只分析主要流程,其它的像变量赋值等部分只分析会影响流程执行的内容。
不会讲解Makefile文件中出现的函数,如果不懂,可以bing。

 

分析顺序为:先分析框架,再慢慢细化。分析每个模块时,也是先框架再细化的顺序。

 

2. 先看看哪些主语句块是有效的

 

 

Makefile中存在很长的if语句块,需要确定哪些行的语句是有效的。

 

 (1) line 1 ~ line 117 有效

 

主要是变量的赋值,环境变量的设置

 

(2) line 118 ~ line 158,其中line 137 ~ line 157的语句无效

       由于只输入了make,因此KBUILD_SRC为空,会解析line 118 ~ line 158的语句。这部分中,line 137 ~ line 157的语句无效。原因是编译时只输入了make,导致line 122行条件为假,因此KBUILD_OUTPUT为空值,line 137行的语句为假,所以line 137 ~ line 157的语句无效。
        

(3) line 161 ~ line 1698,其中line 516 ~ line 549、line 1184 ~ line 1245、line 1457 ~ line 1533语句无效

 

       在上述(2)中的line 118 ~ line 158部分中,line 137 ~ line 157的语句无效,而skip-makefile在line 156行赋值,所以skip-makefile为空值,因此line 161行的条件为真,所以line 161 ~ line 1698的语句有效。

 

       在这部分中,line 516 ~ line 549语句无效。原因是编译时只输入了make,因此line 495,line 502,line 510为假,所以config-targets,mixed-targets,dot-config的值不会改变,还是line 491 ~ line 493的初始值,即config-targets = 0,mixed-targets =0,dot-config = 1,因此line 516 ~ line 549无效

 

CONFIG_MODULES未定义,line 1184行条件为假,line 1184 ~ line 1245的语句不会被处理,line 1247 ~ line 1259的会被处理

 

        在line 188行之前,SUBDIRS没有被定义,并且执行Makefile时只输入了make,所以SUBDIRS为空值,后续的line 189,line 193都不会执行,因此KBUILD_EXTMOD为空值,line 926条件为真,而line 1456对应于line 926的ifeq语句,因此从line 1457 ~ line 1533的语句不会被处理

 

 

 

3. 主目标介绍

 

 

 

 

寻找主目标时只需要关注上述2.中介绍的有效的语句块。

 

(1) 源码根目录下Makefile line 128 _all:

 

这是第一目标

 

(2) 源码根目录下Makefile line 200 _all: all 

 

        重载了第一目标。line 200行在ifeq语句中,下面分析为什么line200行会生效。

         在line 188行之前,SUBDIRS没有被定义,执行Makefile时只输入了make,所以SUBDIRS为空值,后续的line 189,line 193都不会执行,因此KBUILD_EXTMOD为空值。KBUILD_EXTMOD为空值,line 200行语句有效会重载目标all 
        
(3) 源码根目录下Makefile line 623 all: vmlinux

 

定义目标all的依赖

 

(4) arch/x86/Makefile line 271 all: bzImage

 

       line 230设置SUBARCH值。SUBARCH值会赋给line 257行的ARCH(若编译时输入了make ARCH=...,则line 257行不会赋值),ARCH值会决定SRCARCH的值,而后续的line 630会根据SRCARCH的值决定引入哪一个架构的Makefile文件。在x86架构下编译内核时,前述的line 230 SUBARCH=x86,line 630行会引入arch/x86/Makefile。

 

       arch/x86/Makefile文件line 271行会重载目标all:bzImage

 

(5) arch/x86/Makefile line 276 bzImage: vmlinux

 

目标bzImage依赖目标vmlinux

 

(6) 源代码根目录下的Makefile line 982 vmlinux: scripts/link-vmlinux.sh vmlinux_prereq $(vmlinux-deps) FORCE

 

目标vmlinux在源代码根目录下Makefile的line 982行声明

 
综上所述,Makefile中第一目标是源代码根目录下Makefile line 200行的 _all:all,
而目标all定义在arch/x86/Makefile line 271 行all: bzImage,
bzImage定义在arch/x86/Makefile line 276 行bzImage: vmlinux,
目标vmlinux定义在源代码根目录下的Makefile line 982行 vmlinux: 

 

4. 生成主目标过程分析

 

 

在前述分析中,目标依赖是

 

 

_all:all
all:bzImage

bzImage:vmlinux

vmlinux:scripts/link-vmlinux.sh vmlinux_prereq $(vmlinux-deps) FORCE

 

 

从vmlinux目标所需的依赖可知,依赖生效的顺序是

 

 

[1] scripts/link-vmlinux.sh => 
[2] vmlinux_prereq => 
[3] $(vmlinux-deps) => 
[4] FORCE

 

 

4.1 vmlinux的依赖scripts/link-vmlinux.sh存在于源代码中,不需要分析这一依赖。

 

 

4.2 处理vmlinux的依赖vmlinux_prereq

 

 

vmlinux的依赖vmlinux_prereq是一个目标,定义于源码根目录Makefile的

 

 

line 959 vmlinux_prereq: $(vmlinux-deps) FORCE

 

 

4.2.1 vmlinux_prereq

 

 

vmlinux_prereq的依赖$(vmlinux-deps)的值定义于源码根目录Makefile的

 

line 953 vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)

 

 

而$(vmlinux-deps)目标定义于源码根目录Makefile的

 

 

line 992 $(sort $(vmlinux-deps)): $(vmlinux-dirs)

 

 

这行语句后面没有对应的命令,$(vmlinux-dirs)在后续内容中分析,而目标vmlinux_prereq对应的命令比较简单,不进行分析。对vmlinux_prereq生成过程的分析结束。

 

 

下面分析一下vmlinux-dirs。

                

 

 

4.2.1.1 vmlinux-dirs的值

 

 

vmlinux-deps的依赖是$(vmlinux-dirs),$(vmlinux-dirs)是文件夹,它的值定义于源码根目录Makefile的
 

 

line 929 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
line 930              $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
line 931              $(net-y) $(net-m) $(libs-y) $(libs-m) $(virt-y)))
 
从中可以看出vmlinux-dirs的值依赖于init-y,init-m,core-y,core-m,drivers-y,drivers-m,net-y,net-m,libs-y,libs-m,virt-y的值,这些变量在以下位置处赋值(忽略内核配置项的值y,n,m的影响)

 

源码根目录Makefile:

 

line 565 init-y := init/

line 566 drivers-y := drivers/ sound/ firmware/

line 567 net-y := net/

line 568 libs-y := lib/
line 569 core-y := usr/
line 570 virt-y := virt/
line 927 core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
 
arch/x86/Makefile:
line 248 drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/

line 249 drivers-$(CONFIG_PCI)            += arch/x86/pci/

line 250

line 251 # must be linked after kernel/

line 252 drivers-$(CONFIG_OPROFILE) += arch/x86/oprofile/

line 253 
line 254 # suspend and hibernation support
line 255 drivers-$(CONFIG_PM) += arch/x86/power/
line 256 
line 257 drivers-$(CONFIG_FB) += arch/x86/video/
line 258 
line 259 drivers-$(CONFIG_RAS) += arch/x86/ras/

 

arch/x86/Makefile:

 

line 242 libs-y  += arch/x86/lib/

 

arch/x86/Makefile:

line 245 core-y += arch/x86/

 

不会包括下述内容
arch/x86/Makefile.um:

line 1 core-y += arch/x86/crypto/

原因:

arch/x86/Makefile.um会在文件arch/um/Makefile中引入,位置在line 47 include $(HOST_DIR)/Makefile.um。在arch/um/Makefile中有如下语句:

 

line 34 HEADER_ARCH     := $(SUBARCH)

line 44 HOST_DIR := arch/$(HEADER_ARCH)

 

SUBARCH的值在源码根目录Makefile line 230赋值
 

        而引入arch/um/Makefile的情形是在编译时输入make ARCH=um,此时源码根目录Makefile的line 257 ARCH ?= $(SUBARCH)不会生效,导致后续的源码根目录Makefile的line 262 SRCARCH := $(ARCH)的值为um,进而源码根目录Makefile的line 630 include arch/$(SRCARCH)/Makefile引入了arch/um/Makefile。而在编译时只输入了make的情形下,ARCH!=um,因此不会引入arch/um/Makefile,进而不会引入arch/x86/Makefile.um。

 

注:um指的是User-mode Linux,是一种虚拟化机制。

 

4.2.1.2 $(vmlinux-dirs)处理过程分析

 

$(vmlinux-dirs)目标定义于源码根目录Makefile的

 
line 1001 $(vmlinux-dirs): prepare scripts

line 1002     $(Q)$(MAKE) $(build)=$@

 

在依赖prepare scripts生成后,会执行line 1002行的$(Q)$(MAKE) $(build)=$@
其中
(1) $(Q)的值决定了是否简化make过程中的输出,不需要过多分析。

(2) $(MAKE) MAKE不是Makefile里面的变量,是make命令内置的环境变量,它的值是"make"

(3) $(build) build 定义于scripts/Kbuild.include的

 

line 184 build := -f $(srctree)/scripts/Makefile.build obj

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值