Kbuild

Kbuild(Kernel Build System)是Linux内核的构建系统,用于管理和协调内核的编译过程(也被其他开源软件所采用,比如U-Boot、BusyBox等)

它基于GNU Make,但通过预定义一些变量和目标(比如obj-yzImagemenuconfig等)进行了扩展以支持内核特有的需求,如模块化编译、跨平台支持和灵活的配置选项

Kbuild由内核中的所有Makefile、Kconfig以及scripts文件中的一些脚本组成

执行流程

  • 根据用户(内核)的配置生成相应的.config文件
  • 将内核的版本号存入include/linux/version.h
  • 建立指向 include/asm-$(ARCH) 的符号链接,选定平台
  • 更新所有编译所需的文件
  • 顶层Makefile开始,递归地访问各个子目录,对相应的模块编译生成目标文件
  • 链接过程,在源代码的顶层目录链接生成vmlinux
  • 根据具体架构提供的信息添加相应符号,生成最终的启动镜像,往往不同架构之间的启动方式不一致。
    • 这一部分包含启动指令
    • 准备initrd镜像等平台相关的部分

内核中的Makefile文件

在linux中,由于内核代码的分层模型,以及兼容很多平台的特性,Makefile文件分布在各个目录中,对每个模块进行分离编译,降低耦合性,使编译方式更加灵活。

Makefile主要是以下五个部分:

  • 顶层Makefile : 在源代码的根目录有个顶层Makefile,顶层Makefile的作用就是负责生成两个最重要的部分:编译生成vmlinux和各种模块
  • .config文件 : 这个config文件主要是产生自用户对内核模块的配置,有三种配置方式:
    • 编译进内核
    • 编译成可加载模块
    • 不进行编译。
  • arch/$(ARCH)/Makefile : 从目录可以看出,这个 Makefile 主要是根据指定的平台对内核镜像进行相应的配置,提供平台信息给顶层 Makefile
  • scirpts/Makefile. : 这些 Makefile 配置文件包含了构建内核的规则
  • kbuild Makefiles : 每一个模块都是单独被编译然后再链接的,所以这一种 kbiuld Makefile几乎在每个模块中都存在.在这些模块文件(子目录)中,也可以使用 Kbuild 文件代替 Makefile,当两者同时存在时,优先选择 Kbuild 文件进行编译工作,只是用户习惯性地使用 Makefile 来命名

层级关系处理

一个Makefile只负责处理本目录中的编译关系,自然地,其他目录中的文件编译由其他目录的Makefile负责,整个linux内核的Makefile组成一个树状结构,对于上层Makefile的子目录而言,只需要让kbuild知道它应该怎样进行递归地进入目录即可。

kbuild利用目录指定的方式来进行目录指定操作,举个例子:

1
obj-$(CONFIG_FOO) += foo/

当CONFIG_FOO被配置成y或者m时,kbuild就会进入到foo/目录中,但是需要注意的是,这个信息仅仅是告诉kbuild应该进入到哪个目录,而不对其目录中的编译做任何指导

参考链接