3. Kbuild Makefile

Linux内核源代码是通过Makefile组织编译的,Linux2.6内核Makefile的许多特性和2.4内核差别很大,在内核目录的documention/kbuild/makefiles.txt中有详细的说明。

3.1 Makefile的组织结构

Linux内核的Makefile分为5个部分,如表6所示:

表6 Makefile的5个部分

Makefile

顶层Makefile

.config

内核配置文件

arch/$(ARCH)/Makefile

具体架构的Makefile

scripts/Makefile.*

通用的规则等。面向所有的Kbuild Makefiles。

kbuild Makefiles

内核源代码中大约有500个这样的文件

顶层Makefile阅读的.config文件,而该文件是由内核配置程序生成的。

顶层Makefile负责制作:vmlinux(内核文件)与模块(任何模块文件)。制作的过程主要是

通过递归向下访问子目录的形式完成。并根据内核配置文件确定访问哪些子目录。顶层Makefile要原封不动的包含一具体架构的Makefile,其名字类似于arch/$(ARCH)/Makefile。该架构Makefile向顶层Makefile提供其架构的特别信息。

每一个子目录都有一个Kbuild Makefile文件,用来执行从其上层目录传递下来的命令。

Kbuild Makefile从.config文件中提取信息,生成Kbuild完成内核编译所需的文件列表。

scripts/Makefile.*包含了所有的定义、规则等信息。这些文件被用来编译基于kbuild

Makefile的内核。

3.2 Makefile语言

内核的Makefile使用的是GNU Make。该Makefile只使用GNU Make已注明的功能,并使用了许多GNU 的扩展功能。

GNU Make支持基本的显示处理过程的函数。内核Makefile 使用了一种类似小说的方式,显示"if"语句的构造、处理过程。

GNU Make 有2个赋值操作符,":="和"="。":=",将对右边的表达式求值,并将所求的值赋给左边。"="更像是一个公式定义,只是将右边的值简单的赋值给左边,当左边的表达式被使用时,才求值。

有时使用"="是正确的。但是,一般情况下,推荐使用":="。

3.3 Kbuild 变量

顶层Makefile输出以下变量:

(1)VERSION、PATCHLEVEL、SUBLEVEL和EXTRAVERSION

这些变量定义了当前内核的版本号。只有很少一部分Makefile会直接用到这些变量;可使用 $(KERNELRELEASE)代替。$(VERSION),$(PATCHLEVEL),和$(SUBLEVEL)定义了最初使用的三个数字的版本号,比如"2""4"和"0"。这三个值一般是数字。$(EXTRAVERSION) 为了补丁定义了更小的版本号。一般是非数字的字符串,比如"-pre4" ,或就空着。

(2)KERNELRELEASE

$(KERNELRELEASE) 是一个字符串,类似"2.4.0-pre4",用于安装目录的命名或显示当前的版本号。一部分架构Makefile使用该变量。

(3)ARCH

该变量定义了目标架构,比如"i386","arm" 或"sparc"。有些Kbuild Makefile根据 $(ARCH) 决定编译哪些文件。

默认情况下,顶层Makefile将其设置为本机架构。如果是跨平台编译,用户可以用下面的命令覆盖该值:

make ARCH=m68k ...

(4)INSTALL_PATH

该变量为架构Makefile定义了安装内核镜像与 System.map 文件的目录。主要用来指明架构特殊的安装路径。

(5)INSTALL_MOD_PATH和MODLIB

$(INSTALL_MOD_PATH) 为了安装模块,给 $(MODLIB) 声明了前缀。该变量不能在Makefile中定义,但可以由用户传给Makefile。

$(MODLIB) 具体的模块安装的路径。顶层Makefile将$(MODLIB)定义为

$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)。用户可以通过命令行参数的形式将其覆盖。

(6)INSTALL_MOD_STRIP

如果该变量有定义,模块在安装之前,会被剥出符号表。如果INSTALL_MOD_STRIP 为 "1",就使用默认选项 --strip-debug。否则,INSTALL_MOD_STRIP 将作为命令 strip的选项使用。

3.4 Kbuild Makefile的定义

大部分内核中的Makefile都是使用Kbuild组织结构的Kbuild Makefile。这章介绍了

Kbuild Makefile的语法。

Kbuild文件倾向于"Makefile"这个名字,"Kbuild"也是可以用的。但如果"Makefile"

"Kbuild"同时出现的话,使用的将会是"Kbuild"文件。

3.4.1 目标定义

目标定义是Kbuild Makefile的主要部分,也是核心部分。主要是定义了要编

译的文件,所有的选项,以及到哪些子目录去执行递归操作。

最简单的Kbuild makefile 只包含一行,如:

该例子告诉Kbuild在这目录里,有一个名为foo.o的目标文件。foo.o将从foo.c或foo.S文件编译得到。

如果foo.o要编译成一模块,那就要用obj-m了。所采用的形式如下:

$(CONFIG_FOO)可以为y(编译进内核) 或m(编译成模块)。如果CONFIG_FOO不是y和m,那么该文件就不会被编译联接了。

3.4.2 编译进内核 - obj-y

Kbuild Makefile 规定所有编译进内核的目标文件都存在$(obj-y)列表中。而这些列表依赖内核的配置。

Kbuild编译所有的$(obj-y)文件。然后,调用"$(LD) -r"将它们合并到一个build-in.o文件中。稍后,该build-in.o会被其父Makefile联接进vmlinux中。

$(obj-y)中的文件是有顺序的。列表中有重复项是可以的:当第一个文件被联接到built-in.o中后,其余文件就被忽略了。联接也是有顺序的,那是因为有些函数(module_init()/__initcall)将会在启动时按照他们出现的顺序进行调用。所以,记住改变联接的顺序可能改变你SCSI控制器的检测顺序,从而导致你的硬盘数据损害。

举例说明obj-y:

3.4.3 编译可装载模块 - obj-m

$(obj-m) 列举出了哪些文件要编译成可装载模块。

一个模块可以由一个文件或多个文件编译而成。如果是一个源文件,Kbuild Makefile只需简单的将其加到$(obj-m)中去就可以了。例如:

注意:此例中 $(CONFIG_ISDN_PPP_BSDCOMP) 的值为'm'

如果内核模块是由多个源文件编译而成,那你就要采用上面那个例子一样的方法去声明你所要编译的模块。Kbuild需要知道你所编译的模块是基于哪些文件,所以你需要通过变量$(<module_name>-objs)来告诉它。例如:

在这个例子中,模块名将是isdn.o,Kbuild将编译在$(isdn-objs)中列出的所有文件,然后使用"$(LD) -r"生成isdn.o。

Kbuild能够识别用于组成目标文件的后缀-objs和后缀-y。这就让Kbuild Makefile可以通过使用 CONFIG_ 符号来判断该对象是否是用来组合对象的。例如:

在这个例子中,如果 $(CONFIG_EXT2_FS_XATTR) 是 'y',xattr.o将是复合对象ext2.o的一部分。

注意:当然,当你要将其编译进内核时,上面的语法同样适用。所以,如果你的CONFIG_EXT2_FS=y,那Kbuild会按你所期望的那样,生成ext2.o文件,然后将其联接到built-in.o中。

3.4.4目标库文件 - lib-y

在obj-*中所列文件是用来编译模块或者是联接到特定目录中的built-in.o。同样,也可以列出一些将被包含在lib.a库中的文件。在 lib-y 中所列出的文件用来组成该目录下的一个库文件。在obj-y与lib-y中同时列出的文件,因为都是可以访问的,所以该文件是不会被包含在库文件中的。同样的情况,lib-m中的文件就要包含在lib.a库文件中。

注意,一个Kbuild makefile可以同时列出要编译进内核的文件与要编译成库的文件。所以,在一个目录里可以同时存在built-in.o与lib.a两个文件。例如:

这将由 checksum.o 和delay.o 两个文件创建一个库文件 lib.a。为了让Kbuild真正认识到这里要有一个库文件lib.a要创建,其所在的目录要加到libs-y列表中。

3.4.5递归向下访问目录

一个Makefile只对编译所在目录的对象负责。在子目录中的文件的编译要由其所在的子目录的Makefile来管理。只要你让Kbuild知道它应该递归操作,那么该系统就会在其子目录中自动的调用 make 递归操作。

这就是obj-y和obj-m的作用。比如ext2被放的一个单独的目录下,在fs目录下的Makefile会告诉Kbuild使用下面的赋值进行向下递归操作。

如果 CONFIG_EXT2_FS 被设置为 'y'(编译进内核)或是'm'(编译成模块),相应的 obj- 变量就会被设置,并且Kbuild就会递归向下访问 ext2 目录。Kbuild只是用这些信息来决定它是否需要访问该目录,而具体怎么编译由该目录中的Makefile来决定。将 CONFIG_ 变量设置成目录名是一个好的编程习惯。这让Kbuild在完全忽略那些相应的CONFIG_ 值不是'y'和'm'的目录。

3.4.6编辑标志

编辑标记包括:EXTRA_CFLAGS,、EXTRA_AFLAGS、EXTRA_LDFLAGS、EXTRA_ARFLAG。所有的EXTRA_变量只在所定义的Kbuild Makefile中起作用。EXTRA_变量可以在Kbuild Makefile中所有命令中使用。

$(EXTRA_CFLAGS) 是用 $(CC) 编译C源文件时的选项。例如:

该变量是必须的,因为顶层Makefile拥有变量 $(CFLAGS) 并用来作为整个源代码树的编译选项。

$(EXTRA_AFLAGS) 也是一个针对每个目录的选项,只不过它是用来编译汇编源代码的。例如:

$(EXTRA_LDFLAGS)和$(EXTRA_ARFLAGS)分别与$(LD)和$(AR)类似,只不过它们是针对每个目录的。例如:

CFLAGS_$@, AFLSGA_$@

CFLAGS_$@ 和 AFLAGS_$@ 只能在当前Kbuild Makefile中的命令中使用。

$(CFLAGS_$@) 是 $(CC) 针对每个文件的选项。$@ 表明了具体操作的文件。例如:

以上三行分别设置了aha152x.o,gdth.o 和 seagate.o的编辑选项。

$(AFLAGS_$@) 也类似,只不是是针对汇编语言的。例如:

3.4.7依赖跟踪

Kbuild 跟踪在以下方面依赖:

1) 所有要参与编译的文件(所有的.c 和.h文件)

2) 在参与编译文件中所要使用的 CONFIG_ 选项

3) 用于编译目标的命令行

因此,如果你改变了 $(CC) 的选项,所有受影响的文件都要重新编译。

3.4.8特殊规则

特殊规则就是那Kbuild架构不能提供所要求的支持时,所使用的规则。一个典型的例子就是在构建过程中生成的头文件。另一个例子就是那些需要采用特殊规则来准备启动镜像。

特殊规则的写法与普通Make规则一样。Kbuild并不在Makefile所在的目录执行,所以所有的特殊规则都要提供参与编译的文件和目标文件的相对路径。

在定义特殊规则时,要使用以下两个变量:$(src)和$(obj)。$(src) 表明Makefile所在目录的相对路径。经常在定位源代码树中的文件时,使用该变量。$(obj) 表明目标文件所要存储目录的相对路径。经常在定位所生成的文件时,使用该变量。例如:

这就是一个特殊规则,遵守着make所要求的普通语法。

Linux Kbuild文档 3相关推荐

  1. Linux Kbuild文档 4

    4. 一个使用linux kbuild实现可配置编译的例子 我编写了一个使用Linux kbuild机制实现可配置编译的小例子,工程名为print-example.包括如下如下几个目录: 其中scri ...

  2. Linux Kbuild文档 2

    2. Kconfig linux在2.6版本以后将配置文件由原来的config.in改为Kconfig,对于Kconfig的语法在内核源代码/Documentation/kbuild/kconfig- ...

  3. Linux Kbuild文档 1

    Linux内核配置方式1.1 概述 Linux内核源代码组织了一个配置系统,该配置系统可以生成内核配置菜单,方便内核配置.配置系统主要包含Makefile.Kconfig和配置工具,可以生成配置界面. ...

  4. linux 查看 文档 不显示注释 命令

    原文:http://www.weiruoyu.cn/?p=661 最近发现一个很好的命令,就是linux 查看 文档 不显示注释 的命令 [root@localhost ha.d]# cat ha.c ...

  5. Linux内核官方文档atomic_ops.txt【摘自Linux 内核文档】

    摘自Linux内核文档 Documentation/atomic_ops.txt,不是本人原创 Semantics and Behavior of Atomic and Bitmask Operati ...

  6. linux在文档中查找内容,【Linux】用grep在文档中查找内容

    有时候,我们需要在文档中查找一些内容,常用grep.它在文档查找相关内容并输出匹配行. > 查找某关键字 在system.log中,查找包含keyword的行 grep 'keyword' sy ...

  7. linux开源文档管理系统_Linux中的系统管理员问题 免费和开源软件

    linux开源文档管理系统 根帐号 (Root Account) The "root" account is the most unrestrictive account on a ...

  8. Linux是什么?大牛十年Linux心得文档给你答案

    Linux是什么 Linux就是个操作系统: 它和Windows XP.Windows 7.Windows 10什么的一样就是一个操作系统而已! Linux能干什么: 它能当服务器,服务器上安装者各种 ...

  9. Linux之文档与目录结构 目录的相关操作 Linux的文件系统

    Linux之文档与目录结构 Linux文件系统结构 Linux目录结构的组织形式和Windows有很大的不同.首先Linux没有"盘(C盘.D盘.E盘)"的概念.已经建立文件系统的 ...

最新文章

  1. 国民技术芯片相关产业研发
  2. Clion从入门到精通
  3. jdk与jre的区别(转)
  4. 位域(bit fields)简介
  5. WordPress 3.0十大看点 CMS功能进一步增强
  6. python入门难?几个练习实例 全会就入门了
  7. Python 数据科学入门教程:TensorFlow 聊天机器人
  8. 一个通用的Makefile模板-转
  9. python从入门到精通 pdf 完整超清版-Python从入门到精通PDF高清完整版免费下载|百度云盘...
  10. VB中Excel 2010的导入导出操作
  11. 飞思卡尔芯片k66单片机溢出_飞思卡尔HCS12系列 Flash的加密解密解决方法
  12. STM32——SDIO进行SD卡读写测试
  13. VMware安装虚拟机操作步骤[史上最详细]
  14. 恒生电子招聘,内含内推码
  15. python学员管理系统
  16. docker开放远程服务
  17. 电商订单仓储ERP管理系统软件源码
  18. 说说你平时怎么优化mysql的_面试:给我说说你平时是如何优化MySQL的?
  19. TestCenter测试管理工具功能详解七(L)
  20. 正好配资复盘观点:上证第一支撑位3426

热门文章

  1. 幻读Java_脏读、幻读、不可重复读和丢失更新
  2. 委婉的拒绝offer
  3. (JAVA)Math类
  4. 主机关机后第二天就无法开机_iphone没电自动关机后无法充电和开机的解决办法!(亲身经历)...
  5. 云开发的数据库权限机制解读丨云开发101
  6. babel 用法及其 .babelrc 的配置详解,想做前端架构,拒绝一知半解...
  7. Linux空硬盘从分区到挂载
  8. 阻止页面双击选中文本
  9. HDU 2296 Ring AC自动机 + DP
  10. 炎炎夏日需要一个清凉的地 - 自制水冷系统(十一 指尖的思绪之程序篇)