内核编译(五):Makefile解析(二)

    在上节课里,我们对内核源码里的Makefile在总体结构上进行了分析,并发现make uImage所依赖的是vmlinux这个目标。在本节课,我们就开始研究vmlinux是怎么去生成的,我们先把vmlinux这个目标粘贴上来:


    我们看到,这个目标里它依赖的有:$(vmlinux-lds),$(vmlinux-init),$(vmlinux-main),$(kallsyms.o) FORCE。其中,FORCE是一个伪目标,我们可以找到它的定义:


在这里,它既没有依赖,也不执行命令,所以在make过程中,也不会去生成一个叫做FORCE的文件,这样,这个依赖就会总被认为是最新的,被它依赖的规则就会每次都会被执行(如果不理解的话,可以去了解一下Makefile的时间戳)。下面,我们就来探究一下其它三个依赖。

    首先我们探究第一个$(vmlinux-lds),我们搜索一下就可以找到它的值:


我们可以看到,它的值就表示在具体的架构目录下(这里是arm)的kernel/vmlinux.lds这个链接脚本。

    接下来我们探究第二个$(vmlinux-init),从语义我们可以知道,它应该是一些初始化的代码。我们搜索一下它的值:


可以看到,它的值为$(head-y)和 $(init-y),我们再分别搜一下这两个的值,发现找不到,说明它可能在架构目录里的Makefile中定义了。我们搜索一下,还真找到了:


我们可以看到,它的值是arch/arm/kernel/head.o(MMUEXT在这里是没有定义的,如果有的话就是就是head-nommu.o这个文件)和arch/arm/kernel/init_task.o。接着我们看init-y的值。这时我们发现,我们又搜不到它的值了(蛋疼!),我们只能再回顶层的Makefile搜索一下。这时,我们再次搜到了它的值:


可以看到,这里有两个赋值,第一个赋值,init-y则表示init目录下的所有文件,第二个赋值,则是一个Makefile函数,它是一个替换通配符,格式是这样的:

$(patsubst %.c,%.o,$(dir))

其作用是:把$(dir)里的文件符合后缀是.c 的全部替换成.o。这样,我们就可以理解上面一句了,它的意思是把init目录下的所有.c文件最终编译成一个built-in.o的文件。因此,vmlinux-init一共依赖三个文件:head.o,init_task.o,built-in.o,从语义上来看,他们应该都是初始化的代码。

    接下来,我们开始探究第三个$(vmlinux-main),我们在顶层Makefile中进行搜索即可搜到:


我们可以看到,它所依赖的有:core-y,libs-y,drivers-y,net-y,我们分别搜索一下他们的值(这里就不说具体的搜索过程了):

一.core-y

在架构目录下的Makefile:


顶层的Makefile:




可以看到,它和之前的init-y是相似的,结果是把相关目录下的文件编译生成built-in.o

二.libs-y:

架构Makefile:


顶层Makefile:


最终结果是libs-y=lib.a built-in.o。

三.drivers-y:

顶层Makefile:



最终结果也是生成相应的built-in.o。

四.net-y:

顶层Makefile:



最终结果也是生成相应的built-in.o。

    最后一个依赖就是kallsyms了,它是linux内核的符号表,这里我们就暂且不分析它了。

    我们分析完了vmlinux的依赖,就该分析执行它的过程了,它的执行过程就是下面一堆:


如果我们把它一一展开去探究的话,需要花很多经历,这里最简单的办法就是亲自去make vmlinux试一下:

(该图不是作者的,只是借用,侵删 )

从这里我们看到,里面有许多的built-in.o,也就对应了我们之前所探究的那些依赖。而且从这里我们可以知道,它第一个链接的文件是head.o,因此,这应该是内核源码里的开头部分。

    Makefile分析到这里就结束了,接下来,我们就探究内核启动的流程。

猜你喜欢

转载自blog.csdn.net/xiaokangdream/article/details/80200974