在具体移植LINUX之前,我们先来学习一下 Linux 内核的顶层 Makefile 文件,因为顶层 Makefile 控制着 Linux 内核的编译流程。NXP 会从 https://www.kernel.org 下载某个版本的 Linux 内核,然后将其移植到自己的 CPU上,测试成功以后就会将其开放给 NXP 的 CPU 开发者。开发者下载 NXP 提供的 Linux 内核,然后将其移植到自己的产品上。
编译过程
使用命令“make xxx_defconfig”配置好 Linux 内核以后就可以使用“make”或者“make all”命令进行编译,_all 是默认目标,目标 all 依赖 vmlinux,vmlinux 的依赖为:scripts/link-vmlinux.sh、
(
h
e
a
d
−
y
)
、
(head-y) 、
(head−y)、(init-y)、
(
c
o
r
e
−
y
)
、
(core-y) 、
(core−y)、(libs-y) 、
(
d
r
i
v
e
r
s
−
y
)
、
(drivers-y) 、
(drivers−y)、(net-y)、arch/arm/kernel/vmlinux.lds 和 FORCE。这些变量都是一些 built-in.o 或.a 等文件,这个和 uboot 一样,都是将相应目录中的源码文件进行编译,然后在各自目录下生成 built-in.o 文件,有些生成了.a 库文件。最终将这些 built-in.o 和.a 文件进行链接即可形成 ELF 格式的可执行文件,也就是 vmlinux!
但是链接是需要链接脚本的,vmlinux 的依赖 arch/arm/kernel/vmlinux.lds 就是整个 Linux 的链接脚本
这 三 行 代 码 就 是 普 通 的 链 接 操 作 , 连 接 脚 本 为
lds= ./arch/arm/kernel/vmlinux.lds , 需 要 链 接 的 文 件 由 变 量 KBUILD_VMLINUX_INIT 和KBUILD_VMLINUX_MAIN 来决定。
所以make 的过程,重点就是将各个子目录下的 built-in.o、.a 等文件链接在一起,最终生成 vmlinux 这个 ELF 格式的可执行文件。链接脚本为arch/arm/kernel/vmlinux.lds,接下来的问题就是这些子目录下的builtin.o、.a 等文件又是如何编译出来的呢?
built-in.o 文件生成
vmliux 依赖 vmlinux-deps,而 vmlinux-deps=
$(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) KaTeX parse error: Expected group after '_' at position 339: … 这个脚本了,此脚本默认目标为_̲_build,该目标有 bui…(obj)/built-in.o”,这就是这些 built-in.o 的来源了。builtin-target依赖为 obj-y,,命令为“$(call if_changed,link_o_target)”,也就是调用函数 if_changed,参数为 link_o_target,其返回值就是具体的命令。此命令就是使用 LD将某个目录下的所有.o 文件链接在一起,最终形成 built-in.o。
make zImage 过程
vmlinux 是编译出来的最原始的内核文件,是未压缩的ELF 格式的文件。
Image 就是使用 objcopy 取消掉 vmlinux 中的一些其他信息,比如符号表什么的,仅包含可执行的二进制数据。
zImage 是经过 gzip 压缩后的 Image。