3 Kbuild文件

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

对于Kbuild文件名来讲,Kbuild编译系统更倾向于使用"Makefile"这个名字,当然"Kbuild"也是可以用的。但如果"Makefile"和"Kbuild"同时存在的话,Kbuild编译系统使用的将会是"Kbuild"文件。

3.1节将是对目标定义的一个快速介绍,以后的几章会提供更详细的内容以及实例。

3.1 目标定义

目标定义是Kbuild Makefile的主要部分,也是核心部分。主要是定义了要编译的文件,所有的选项,以及到哪些子目录去执行递归操作。

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

例子:

obj-y += foo.o

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

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

例子:

obj-$(CONFIG_FOO) += foo.o

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

3.2 编译进内核 -- obj-y

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

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

$(obj-y)列表中的文件是有顺序讲究的。而且$(obj-y)列表中可以有重复项:但是当第一个文件被链接到built-in.o中后,其余重复的文件就被忽略了。

链接目标这个动作也是有顺序的,因为有些函数,例如module_init()/__initcall,将会在启动时按照他们出现的顺序被调用。所以,记住改变链接的顺序可能改变你SCSI控制器的检测顺序,从而导致你的硬盘数据损害。

例子:

# drivers/isdn/i4l/Makefile

# Makefile for the kernel ISDN subsystem and device drivers.

# Each configuration option enables a list of files.

obj-$(CONFIG_ISDN)        += isdn.o

obj-$(CONFIG_ISDN_PPP_BSDCOMP)    += isdn_bsdcomp.o

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

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

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

例子:

# drivers/isdn/i4l/Makefile

obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

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

如果内核模块是由多个源文件编译而成,那你就要采用上面那个例子一样的方法去声明你所要编译的模块。

Kbuild系统需要知道你所编译的模块是基于哪些文件,所以你需要通过变量:

$(<module_name>-objs)

来告诉它。

例子:

#drivers/isdn/i4l/Makefile

obj-$(CONFIG_ISDN) += isdn.o

 isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o

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

Kbuild recognises objects used for composite objects by the suffix -objs, and the suffix -y。

This allows the Makefiles to use the value of a CONFIG_ symbol to determine if an object is part

of a composite object.

例子:

# fs/ext2/Makefile

obj-$(CONFIG_EXT2_FS)        += ext2.o

 ext2-y                 := balloc.o bitmap.o

ext2-$(CONFIG_EXT2_FS_XATTR)    += xattr.o

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

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

3.4 输出的符号

Makefile对模块输出的符号没有特殊要求。

3.5 目标库文件 -- 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 两种文件。

例子:

# arch/i386/lib/Makefile

lib-y    := chechsum.o delay.o

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

还可参考"6.3 递归向下时要访问的目录列表"。

lib-y 的使用一般限制在 lib/ 和 arch/*/lib 中。

3.6 递归向下访问目录

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

obj-y 和 obj-m 就有这样的作用。

ext2 被放在一个单独的目录下,在fs目录下的Makefile会告诉Kbuild系统使用下面的赋值进行向下递归操作。

例子:

# fs/Makefile

obj-$(CONFIG_EXT2_FS) += ext2/

如果 CONFIG_EXT2_FS 被设置为 'y'(编译进内核)或是'm'(编译成模块),相应的 obj- 变量就会被设置,并且Kbuild就会递归向下访问 ext2 目录。

Kbuild系统只是用这些信息来决定它是否需要访问该目录,而具体怎么编译由该子目录中的Makefile来决定。

It is good practice to use a CONFIG_ variable when assigning directory    names. This allows kbuild to totally skip the directory if the corresponding CONFIG_ option is neither 'y' nor 'm'.

3.7 编辑标志

EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS

所有的EXTRA_ 变量只在其被定义的Kbuild Makefile文件中起作用。而且,EXTRA_ 变量可以在Kbuild Makefile中的所有命令中使用。

l          $(EXTRA_CFLAGS) 是用 $(CC) 编译C源文件时要用到的选项。

例子:

# drivers/sound/emu10kl/Makefile

EXTRA_CFLAGS += -I$(obj)

ifdef DEBUG

EXTRA_CFLAGS += -DEMU10KL_DEBUG

endif

EXTRA_CFLAGS变量是必须的,因为顶层Makefile使用 $(EXTRA_CFLAGS)作为整个源代码树的编译选项。

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

例子:

# arch/x86_64/kernel/Makefile

EXTRA_AFLAGS := -traditional

l          $(EXTRA_LDFLAGS) 和 $(EXTRA_ARFLAGS)分别与 $(LD)和 $(AR)类似,只不过,他们是针对内核的每个目录的编辑标志。

例子:

# arch/m68k/fpsp040/Makefile

EXTRA_LDFLAGS := -x

l          CFLAGS_$@, AFLSGA_$@

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

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

例子:

# drivers/scsi/Makefile

CFLAGS_aha152x.o =  -DAHA152X_STAT -DAUTOCONF

CFLAGS_gdth.o    =  # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ \

-DGDTH_STATISTICS

CFLAGS_seagate.o =  -DARBITRATE -DPARITY -DSEAGATE_USE_ASM

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

l          $(AFLAGS_$@)也类似,只是针对汇编语言的。

例子:

# arch/arm/kernel/Makefile

AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional

AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) –traditional

3.9 跟踪依赖

Kbuild 跟踪以下情况的依赖:

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

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

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

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

3.10 特殊规则

特殊规则就是Kbuild编译系统不能提供所要求的支持时,所使用的规则。一个典型的例子就是在构建过程中生成的头文件。Another example are the architecture-specific Makefiles which need special rules to prepare boot images etc.

Special rules are written as normal Make rules.

Kbuild is not executing in the directory where the Makefile is located, so all special rules shall provide a relative     path to prerequisite files and target files.

Two variables are used when defining special rules:

l          $(src)

$(src) 表明Makefile所在目录的相对路径。需要定位源代码树中的文件时经常使用该变量。

l          $(obj)

$(obj) 表明目标文件所要存储目录的相对路径。经常在定位所生成的目标文件时使用该变量。

例子:

# drivers/scsi/Makefile

$(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl

$(CPP) -DCHIP=810 - < $< | ... $(src)/script_asm.pl

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

目标文件依赖于两个源文件。用$(obj)来定位目标文件,用$(src)来定位源文件。

3.11 $(CC) 支持的函数

内核可能由多个不同版本的$(CC)编译,而每个版本都支持不同的功能集与选项集。Kbuild系统提供了检查 $(CC) 可用选项的基本功能。$(CC)一般情况下是gcc编译器,但也可以使用其它编译器来代替gcc。

l          as-option

as-option,当编译汇编文件(*.S)时,用来检查 $(CC) 是否支持特定选项。如果第一个选项不支持的话,可选的第二个选项就派上用场了。

例子:

# arch/sh/Makefile

cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),)

在上面的例子里,如果 $(CC) 支持选项 -Wa$(comma)-isa=$(isa-y),cflags-y就会被赋予该值。    第二个参数是可选的,当第一个参数不支持时,就会使用该值。

l          ld-option

ld-option,当链接目标文件时,用来检查 $(CC) 是否支持特定选项。如果第一个选项不支持的话,可选的第二个选项可以用来指定。

例子:

#arch/i386/kernel/Makefile

vsyscall-flags += $(call ld-option, -Wl$(comma)--hash-style=sysv)

在上面的例子中,如果 $(CC)支持选项 -Wl$(comma)--hash-style=sysv,ld-option就会被赋予该值。

第二个参数是可选的,当第一个参数不支持时,就会使用该值。

l          cc-option

cc-option,用来检查 $(CC) 是否支持特定选项,并且不支持使用可选的第二项。

例子:

# arch/i386/Makefile

cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)

在上面的例子中,如果 $(CC)支持选项 -march=pentium-mmx,cc-option就会被赋予该值,否则就赋 -march-i586。

cc-option的第二个参数是可选的。如果忽略的话,当第一个选项不支持时,cflags-y 不会被赋值。

l          cc-option-yn

cc-option-yn,用来检查 gcc 是否支持特定选项,返回'y'支持,否则为'n'。

例子:

# arch/ppc/Makefile

biarch  := $(call cc-option-yn, -m32)

aflags-$(biarch) += -a32

cflags-$(biarch) += -m32

在上面的例子里,当 $(CC) 支持 -m32选项时,$(biarch)设置为y。当$(biarch) 为y时,扩展的 $(aflags-y) 和 $(cflags-y)变量就会被赋值为:-a32 和 -m32。

l          cc-option-align

gcc版本大于3.0时,改变了函数,循环等用来声明内存对齐的选项。当用到对齐选项时,$(cc-option-align) 用来选择正确的前缀:

gcc < 3.00

cc-option-align = -malign

gcc >= 3.00

cc-option-align = -falign

例子:

CFLAGS += $(cc-option-align)-functions=4

在上面的例子中,选项 -falign-funcions=4 被用在gcc >= 3.00的时候。对于小于3.00时, 使用 -malign-funcions=4 。

l          cc-version

cc-version以数学形式返回 $(CC) 编译器的版本号。

其格式是:<major><minor>,二者都是数学。比如,gcc 3.41 会返回 0341。 当某版本的 $(CC) 在某方面有缺陷时,cc-version就会很有用。比如,选项-mregparm=3 虽然会被gcc接受,但其实现是有问题的。

例子:

# arch/i386/Makefile

cflags-y += $(shell \

if [ $(call cc-version) -ge 0300 ] ; then \

echo "-meregparm=3"; fi ;)

在上面的例子中,-mregparm=3只会在gcc的版本号大于等于3.0的时候使用。

l          cc-ifversion

cc-ifversion测试 $(CC) 的版本号,如果版本表达式为真,就赋值为最后的参数。

例子:

#fs/reiserfs/Makefile

EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0402, -O1)

在这个例子中,如果 $(CC) 的版本小于4.2,EXTRA_CFLAGS就被赋值 -O1。

cc-ifversion 可使用所有的shell 操作符:-eq,-ne,-lt,-le,-gt,和-ge。

第三个参数可以像上面例子一样是个文本,但也可以是个扩展的变量或宏。

Kbuild文件的更多相关文章

  1. Linux内核Makefile文件(翻译自内核手册)

    --译自Linux3.9.5 Kernel Makefiles(内核目录documention/kbuild/makefiles.txt) kbuild(kernel build) 内核编译器 Thi ...

  2. Linux Kbuild工作原理分析(以DVSDK生成PowerVR显卡内核模块为例)

    一.引文 前篇博文<Makefile之Linux内核模块的Makefile写法分析>,介绍了Linux编译生成内核驱动模块的Makefile的写法,但最近在DVSDK下使用Linux2.6 ...

  3. Linux Kbuild文档(转)

    转载链接:http://blog.chinaunix.net/uid-10221131-id-2943265.html Linux Kbuild文档 Linux Kbuild文档 V 0.1 tang ...

  4. Linux 2.6内核Makefile浅析

    1 概述 Makefile由五个部分组成: Makefile:根目录Makefile,它读取.config文件,并负责创建vmlinux(内核镜像)和modules(模块文件). .config:内核 ...

  5. armv7a-mediatek451_001_vfp-linux-gnueabi-gcc: directory: No such file or directory 编译error

    release/vm_linux/output/hisense_android/mt5399_cn_android_JB/rel/obj/oss/source/arm_mali_ko/mali400- ...

  6. 编译android的linux kernel goldfish

    https://source.android.com/source/building-kernels.html $ export PATH=/home/hzh/oldhome/learn/androi ...

  7. 编译kernel:配置

    韦东山Linux视频第1期_裸板_UBoot_文件系统_驱动初步\第10课第2节 内核启动流程分析之配置.WMV 下面以DM9000的配置为例: 在一个编译好的内核代码里,寻找CONFIG_DM900 ...

  8. Linux源文件夹结构呈现

    1.arch文件夹: - 相关的存储在不同平台上的代码,每个平台都采用了不同的文件夹来区分. ******Alpha平台 ******Arm平台 ******Arv32平台 ******X86平台 2 ...

  9. LINUX设备驱动程序的注意事项(两)建设和执行模块

             <一>:设置測试系统 首先准备好一个内核源代码树,构造一个新内核,然后安装到自己的系统中.           <二>:HelloWorld模块 #inclu ...

随机推荐

  1. Linux下通过ODBC连接sqlserver

    Linux下通过ODBC连接sqlserver 1.需求: 最近有个需求就是要在linux下连接(可以执行sql语句)sqlserver 2.环境 操作系统:  Centos6.5 数据库:     ...

  2. 【收集整理】Linux下的目录讲解

    Linux下的目录介绍:在Linux系统中,一切东西都是存放在一个唯一的“虚拟文件系统”中的,这个“虚拟文件系统”是树状的结构以一个根目录开始.以文件来表示所有逻辑实体和非逻辑实体,逻辑实体指文件和目 ...

  3. main(int argc , char *argv[])

    #include <unistd.h>#include <stdlib.h>#include <stdio.h> int main(int argc, char * ...

  4. PHP对URL设置

    一.URL规则  1.默认是区分大小写的  2.如果我们不想区分大小写可以改配置文件   'URL_CASE_INSENSITIVE'=>true,               //url不区分 ...

  5. php操作memcache的用法、详解和方法介绍

    1.简介 memcache模块是一个高效的守护进程,提供用于内存缓存的过程式程序和面向对象的方便的接口,特别是对于设计动态web程序时减少对数据库的访问. memcache也提供用于通信对话(sess ...

  6. jquery 的新使用用法

    在1.9.1jquery版本中,live 被替换了,现在使用on事件 在动态添加的行中使用下面可响应 $("tbody").on("click","b ...

  7. LeetCode【第一题】Two Sum

    准备刷一刷LeetCode了. 题目: ''' Given an array of integers, return indices of the two numbers such that they ...

  8. Response.Redirect:无法在发送 HTTP 标头之后进行重定向

    URL:http://blog.163.com/asp_neter/blog/static/17510918820107258107558/ 错误出现语句:“Response.Redirect(&qu ...

  9. 第 1 章 策略模式【Strategy Pattern】

    第 1 章 策略模式[Strategy Pattern] 以下内容出自: 24种设计模式介绍与6大设计原则.pdf 刘备要到江东娶老婆了,走之前诸葛亮给赵云(伴郎)三个锦囊妙计,说是按天机拆开解决棘手 ...

  10. QT事件研究的文章

    我始终认为,Windows里最重要的不是API,而是消息.同理,QT里最重要的是事件.然而我对事件的原理和用法至今不是很理解,先放几篇文章在这里,有空回来细细研读: http://m.blog.chi ...