vmliux 依赖 vmlinux-deps,而 vmlinux-deps=$(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN), KBUILD_LDS是连接脚本,这里不考虑,剩下的 KBUILD_VMLINUX_INIT 和 KBUILD_VMLINUX_MAIN 就是各个子目录下的 built-in.o、 .a 等文件。最终 vmlinux-deps 的值如下:

vmlinux-deps = arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o \
init/built-in.o usr/built-in.o \
arch/arm/vfp/built-in.o arch/arm/vdso/built-in.o \
arch/arm/kernel/built-in.o arch/arm/mm/built-in.o \
arch/arm/common/built-in.o arch/arm/probes/built-in.o \
arch/arm/net/built-in.o arch/arm/crypto/built-in.o \
arch/arm/firmware/built-in.o arch/arm/mach-imx/built-in.o \
kernel/built-in.o mm/built-in.o \
fs/built-in.o ipc/built-in.o \
security/built-in.o crypto/built-in.o\
block/built-in.o arch/arm/lib/lib.a\
lib/lib.a arch/arm/lib/built-in.o\
lib/built-in.o drivers/built-in.o \
sound/built-in.o firmware/built-in.o \
net/built-in.o

除了 arch/arm/kernel/vmlinux.lds 以外,其他都是要编译链接生成的。在顶层 Makefile 中有如下代码:

顶层 Makefile 代码段
937 $(sort $(vmlinux-deps)): $(vmlinux-dirs) ;

sort 是排序函数,用于对 vmlinux-deps 的字符串列表进行排序,并且去掉重复的单词。可以看出 vmlinux-deps 依赖 vmlinux-dirs, vmlinux-dirs 也定义在顶层 Makefile 中,定义如下:

顶层 Makefile 代码段
889 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
890 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
891 $(net-y) $(net-m) $(libs-y) $(libs-m)))

vmlinux-dirs 看名字就知道和目录有关,此变量保存着生成 vmlinux 所需源码文件的目录,值如下:

vmlinux-dirs = init usr arch/arm/vfp \
arch/arm/vdso arch/arm/kernel arch/arm/mm \
arch/arm/common arch/arm/probes arch/arm/net \
arch/arm/crypto arch/arm/firmware arch/arm/mach-imx\
kernel mm fs \
ipc security crypto \
block drivers sound \
firmware net arch/arm/lib \
lib

在顶层 Makefile 中有如下代码:

 顶层 Makefile 代码段
946 $(vmlinux-dirs): prepare scripts
947 $(Q)$(MAKE) $(build)=$@

目标 vmlinux-dirs 依赖 prepare 和 scripts,这两个依赖不去浪费时间了,重点看一下第 947行的命令。 build 前面已经说了,值为“-f ./scripts/Makefile.build obj”,因此将 947 行的命令展开就是:

@ make -f ./scripts/Makefile.build obj=$@
$@表示目标文件,也就是 vmlinux-dirs 的值,将 vmlinux-dirs 中的这些目录全部带入到命
令中,结果如下:
@ make -f ./scripts/Makefile.build obj=init
@ make -f ./scripts/Makefile.build obj=usr
@ make -f ./scripts/Makefile.build obj=arch/arm/vfp
@ make -f ./scripts/Makefile.build obj=arch/arm/vdso
@ make -f ./scripts/Makefile.build obj=arch/arm/kernel
@ make -f ./scripts/Makefile.build obj=arch/arm/mm
@ make -f ./scripts/Makefile.build obj=arch/arm/common
@ make -f ./scripts/Makefile.build obj=arch/arm/probes
@ make -f ./scripts/Makefile.build obj=arch/arm/net
@ make -f ./scripts/Makefile.build obj=arch/arm/crypto
@ make -f ./scripts/Makefile.build obj=arch/arm/firmware
@ make -f ./scripts/Makefile.build obj=arch/arm/mach-imx
@ make -f ./scripts/Makefile.build obj=kernel
@ make -f ./scripts/Makefile.build obj=mm
@ make -f ./scripts/Makefile.build obj=fs
@ make -f ./scripts/Makefile.build obj=ipc
@ make -f ./scripts/Makefile.build obj=security
@ make -f ./scripts/Makefile.build obj=crypto
@ make -f ./scripts/Makefile.build obj=block
@ make -f ./scripts/Makefile.build obj=drivers
@ make -f ./scripts/Makefile.build obj=sound
@ make -f ./scripts/Makefile.build obj=firmware
@ make -f ./scripts/Makefile.build obj=net
@ make -f ./scripts/Makefile.build obj=arch/arm/lib
@ make -f ./scripts/Makefile.build obj=lib

这些命令运行过程其实都是一样的,以“@ make -f ./scripts/Makefile.build obj=init”这个命令为例,讲解一下详细的运行过程。这里又要用到 Makefile.build 这个脚本了,此脚本默认目标为__build,这个在 35.5.2 小节已经讲过了,我们再来看一下, __build 目标对应的规则如下:

94 __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
95 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
96 $(subdir-ym) $(always)
97 @:

当 只 编 译 Linux 内 核 镜 像 文 件 , 也 就 是 使 用 “ make zImage ” 编 译 的 时 候 ,KBUILD_BUILTIN=1, KBUILD_MODULES 为空。“make”命令是会编译所有的东西,包括 Linux内核镜像文件和一些模块文件。如果只编译 Linux 内核镜像的话, __build 目标简化为:

__build: $(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
@:

重点来看一下 builtin-target 这个依赖, builtin-target 同样定义在文件 scripts/Makefile.build中,定义如下:

scripts/Makefile.build 代码段
86 ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(libtarget)),)
87 builtin-target := $(obj)/built-in.o
88 endif

第 87 行就是 builtin-target 变量的值,为“$(obj)/built-in.o”,这就是这些 built-in.o 的来源了。要生成 built-in.o,要求 obj-y、 obj-m、 obj-、 subdir-m 和 lib-target 这些变量不能全部为空。最后一个问题: built-in.o 是怎么生成的?在文件 scripts/Makefile.build 中有如下代码:
顶层 Makefile 代码段

325 #
326 # Rule to compile a set of .o files into one .o file
327 #
328 ifdef builtin-target
329 quiet_cmd_link_o_target = LD $@
330 # If the list of objects to link is empty, just create an emptybuilt-in.o
331 cmd_link_o_target = $(if $(strip $(obj-y)),\
332 $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \
333 $(cmd_secanalysis),\
334 rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@)
335
336 $(builtin-target): $(obj-y) FORCE
337 $(call if_changed,link_o_target)
338
339 targets += $(builtin-target)
340 endif # builtin-target

第 336 行的目标就是 builtin-target,依赖为 obj-y,命令为“KaTeX parse error: Double subscript at position 24: …_changed,link_o_̲target)”,也就是调用函…(1)所对应的命令($(1)就是函数的第 1 个参数),在在这里就是调用cmd_link_o_target 所对应的命令,也就是第 331~334 行的命令。 cmd_link_o_target 就是使用 LD将某个目录下的所有.o 文件链接在一起,最终形成 built-in.o。

linux源码剖析四 built-in.o 文件编译生成过程相关推荐

  1. pymavlink 源码剖析(一)之XML文件的数据解析

    文章目录 1 引言 2 pymavlink 的代码自动生成方法 3 XML 文件的数据解析 3.1 XML 文件预处理 3.2 解析 XML 的数据 3.2.1 依据协议版本初始化一些版本特征变量 3 ...

  2. tcp/ip 协议栈Linux源码分析四 IPv4分片 ip_fragment函数分析

    内核版本:3.4.39 很多项目涉及到IP分片的时候都是绕过去了,感觉分片挺难的.但是老这么做也不行啊,抽空分析了内核的分片处理函数ip_fragment,也不是特别复杂,感觉挺简单的,看来事情只有实 ...

  3. GDAL源码剖析(三)之Swig编译和帮助文档生成

    一.Swig编译 1.Swig介绍 SWIG全称是Simplified Wrapper and Interface Generator,官方网站:http://www.swig.org/.SWIG是个 ...

  4. 源码 状态机_阿里中间件seata源码剖析七:saga模式实现

    saga模式是分布式事务中使用比较多的一种模式,他主要应用在长流程的服务,对一个全局事务,如果某个节点抛出了异常,则从这个节点往前依次回滚或补偿事务.今天我们就来看看它的源码实现. 状态机初始化 在之 ...

  5. 阿里中间件seata源码剖析六:TCC模式中2阶段提交实现

    目录 TM通知TC事务状态 TC通知RM分支事务提交 RM处理TC提交事务请求 总结 上篇文章中,我们以TCC模式的demo为例,讲解了seata中全局事务的开启.在这个demo中,TM作为一个全局事 ...

  6. pymavlink 源码剖析(二)之生成代码

    文章目录 1 引言 2 C 代码生成 3 generate_one 函数分析 4 MAVTemplate 5 头文件生成 相关: pymavlink 源码剖析(一)之XML文件的数据解析 MAVLin ...

  7. GDAL源码剖析(四)之命令行程序说明二

    接博客GDAL源码剖析(四)之命令行程序说明一http://blog.csdn.net/liminlu0314/article/details/6978589 其中有个nearblack,gdalbu ...

  8. GTest源码剖析(四)——TEST_P宏

    GTest源码剖析--TEST_P宏 GTest源码剖析TEST_P宏 TEST_P宏用法 TestWithParam 类 1 TestWithParam 类定义 2 WithParamInterfa ...

  9. Laravel源码剖析之请求的处理上(四)

    上篇讲了make方法-->Laravel源码剖析之make详解(三)_Attitude_do_it的博客-CSDN博客, 根据make方法的分析可以得出: $kernel = $app-> ...

最新文章

  1. 使用VA助手如何快速添加注释(按doxygen注释规范)
  2. DL之FAN:FAN人脸对齐网络(Face Alignment depth Network)的论文简介、案例应用之详细攻略
  3. Linux 文件系统 EXT4 的前世今生
  4. U盘装XP系统(含截图,2012最新原创超简单方法)
  5. 001 初学android开发,从搭建环境开始(jdk+eclipse+android sdk+windows7)
  6. springboot集成mongoDB 异常认证
  7. 客观评价golang的优缺点
  8. iOS开发--字典(NSDictionary)和JSON字符串(NSString)之间互转
  9. wifi的主动扫描和被动扫描
  10. Linux MPLS 初探
  11. 腾讯云服务器ftp部署及文件上传
  12. aliez歌词_【aLIEz】附平假名歌词(完整)
  13. Mysql数据库读写分离的实现
  14. win10通过OneDrive实现办公室的电脑和家里电脑重要数据同步
  15. html设置内外边距,css 内外边距如何使用?
  16. 【MATLAB】铰链四杆机构运动分析(GUI设计)
  17. vivo手机计算机怎么开语音,vivo怎么打开语音助手
  18. python3 爬取半次元cosplay图片
  19. 陈睿提供2009-06-19
  20. 新手如何Reverces(基础ctf教程篇)

热门文章

  1. 美国西北大学计算机研究生录取,2021美国西北大学计算机工程录取案例
  2. Piecewise混沌映射/PWLCM混沌映射(含MATLAB代码)
  3. Ubuntu16.04安装 双显卡安装Nvidia驱动 登录循环 黑屏(通用 终结此类问题)转载
  4. three.js/webgl实现室内模型行走
  5. Multiple Cameras
  6. The Donkey of Gui Zhou
  7. php soap传输xml,通过PHP SoapClient请求发送原始XML
  8. write once , run anywhere
  9. 北汇信息 | 什么是高级驾驶辅助系统:ADAS 概述
  10. 数据结构与算法作业3——约瑟夫环问题(循环链表)