Linux内核顶层Makefile的make过程总结

一.    Linux内核源码的make编译

本文对 Linux内核源码的 make时, 顶层Makefile所做的事进行总结。即总结一下 Linux内核源码的 make 过程。

本文续上一篇文章,地址如下:

Linux内核顶层Makefile的make过程说明二_凌肖战的博客-CSDN博客

二.  Linux 的 make过程总结

1.  vmlinux

当执行 "make" 命令编译 Linux 内核源码时,顶层 Makefile会编译 目标 _all,经过上一篇文章的分析,目标_all 最终依赖于 vmlinux,而在 顶层Makfile中的 vmlinux依赖于如下:

vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE
...
+$(call if_changed,link-vmlinux)

这里重点是分析 "scripts/link-vmlinux.sh $(vmlinux-deps) FORCE"。

其中,link-vmlinux.sh 只是个脚本文件,剩下的就是分析 依赖项 vmlinux-deps。

依赖项 vmlinux-deps则 依赖于 $(head-y) $(init-y)$(core-y) $(libs-y) $(drivers-y) $(net-y) 这六个变量。

上一篇文章已经对这六个变量进行了分析。

这些变量都是一些 built-in.o .a 等文件,这个和oubot 一样,都是将相应目录中的源码文件进行编译,然后在各自目录下生成 built-in.o 文件,有些生成了.a 库文件。最终将这些 built-in.o .a 件进行链接即可形成 ELF 格式的可执行文件,也就是 vmlinux

但是链接是需要链接脚本的,vmlinux 的依赖 arch/arm/kernel/vmlinux.lds 就是整个 Linux 的链接脚本。

2.  vmlinux依赖的命令

vmlinux 依赖的 命令如下:
+$(call if_changed,link-vmlinux)

表示将 $(call if_changed,link-vmlinux) 的结果作为最终生成 vmlinux 的命令,前面的+ 表示该命令结果不可忽略。$(call if_changed,link-vmlinux) 是调用函数 if_changedlink-vmlinux 是函数 if_changed 参数。

函数 if_changed 定义在文件 scripts/Kbuild.include 中,如下所示:

247 if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
248 @set -e; \
249 $(echo-cmd) $(cmd_$(1)); \
250 printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)

第247行:any-prereq 用于检查依赖文件是否有变化,如果依赖文件有变化那么 any-prereq 就不为 空,否则就为空。 arg-check 用于检查参数是否有变化,如果没有变化那么 arg-check 就为空。
248 行,“ @set -e ”告诉 bash ,如果任何语句的执行结果不为 true( 也就是执行出错 ) 的话,就直接退出。
249 行, $(echo-cmd) 用于打印命令执行过程,比如在链接 vmlinux 的时候就会输出 
LINK vmlinux ”。 $(cmd_$(1)) 中的 $(1) 表示参数,也就是 link-vmlinux ,因此 $(cmd_$(1)) 表示
执行 cmd_link-vmlinux 的内容。

cmd_link-vmlinux 在顶层 Makefile 中有如下所示定义:
914 # Final link of vmlinux
915 cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS)
$(LDFLAGS_vmlinux)
916 quiet_cmd_link-vmlinux = LINK $@
915 行就是 cmd_link-vmlinux 的值,其中 CONFIG_SHELL=/bin/bash $< 表示目标 vmlinux 的第一个依赖文件, 所以,这个文件为 scripts/link-vmlinux.sh
LD= arm-linux-gnueabihf-ld -EL LDFLAGS 为空。 LDFLAGS_vmlinux 的值由顶层 Makefile
arch/arm/Makefile 这两个文件共同决定,最终 LDFLAGS_vmlinux=-p --no-undefined -X --pic
veneer --build-id 因此 cmd_link-vmlinux 最终的值为:

cmd_link-vmlinux = /bin/bash scripts/link-vmlinux.sh arm-linux-gnueabihf-ld -EL -p --noundefined -X --pic-veneer --build-id

3. vmliux_link 函数

cmd_link-vmlinux 会调用 scripts/link-vmlinux.sh 这个脚本来链接出 vmlinux !在 link- vmlinux.sh 中有如下所示代码:
51 vmlinux_link()
52 {
53 local lds="${objtree}/${KBUILD_LDS}"
54
55 if [ "${SRCARCH}" != "um" ]; then
56 ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
57 -T ${lds} ${KBUILD_VMLINUX_INIT} \
58 --start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1}
59 else
60 ${CC} ${CFLAGS_vmlinux} -o ${2} \
61 -Wl,-T,${lds} ${KBUILD_VMLINUX_INIT} \
62 -Wl,--start-group \
63 ${KBUILD_VMLINUX_MAIN} \
64 -Wl,--end-group \
65 -lutil ${1}
66 rm -f linux
67 fi
68 }
......
216 info LD vmlinux
217 vmlinux_link "${kallsymso}" vmlinux

vmliux_link 就是最终链接出 vmlinux 的函数。
55 行判断 SRCARCH 是否等于“ um ”,如果不相等的话就执行 56~58 行的代码。因为 SRCARCH=arm ,因此条件成立,执行 56~58 行的 代 码 。
56~58 行: 就 是 普 通 的 链 接 操 作 , 连 接 脚 本 为 lds= ./arch/arm/kernel/vmlinux.lds , 需 要 链 接 的 文 件 由 变 量 KBUILD_VMLINUX_INIT KBUILD_VMLINUX_MAIN 来决定。
217 行调用 vmlinux_link 函数来链接出 vmlinux

使用命令 “make V=1” 编译 Linux内核源码时,会有如下的编译信息:

这就是 make 的过程,重点就是将各个子目录下的 built-in.o.a 等文件链接 在一起,最终生成
vmlinux 这个 ELF 格式的可执行文件。链接脚本为 arch/arm/kernel/vmlinux.lds链接过程是
shell脚本 scripts/link-vmlinux.s 来完成的。

猜你喜欢

转载自blog.csdn.net/wojiaxiaohuang2014/article/details/133152056