一、 Kbuild语法
1、menu/endmenu
menu的作用,可以理解成一个目录,menu可以把其中一部分配置项包含到一个menu中,这样有利于配置的分类显示。menu与endmenu是一组指令,必须同时出现。menu和endmenu中包含的部分就是子目录中的配置项。
比如,在init/Kconfig中24行(可能不同)显示为:
menu "General setup"
这样,就会生成一个目录,特征就是右侧会出现一个箭头,如图1中第一行。当点击确认键时,会进入这个菜单项
图1
2、menuconfig
menuconfig有点类似menu,但区别就在于menu后面多了一个config,这个menu是可以配置的,如图1中的第二行,前面比menu类型多了一个方框,通过空格可以修改这个配置项的选中状态。而且从格式上来看,也是有区别的。格式如init/Kconfig中1131行:
menuconfig MODULES
bool "Enable loadable modulesupport"config
if MODULES
xx
endif
也就是说,配置项是位于if和endif中。其中的部分就是MODULES子目录显示的内容。如果选中了MODULE,那么if和endif中的内容可以显示。如果没有定义,就只能进入一个空目录。
3、config
config是构成Kconfig的最基本单元,其中定义了配置项的详细信息。定义的格式参考arch/arm/Kconfig中的第8行。
config ARM
可知,config需要定义名称,与menuconfig相同。这个名称不但用于裁剪内核中,还用于配置项之间的相互依赖关系中。
config的类型有5种,分别是bool(y/n),tristate(y/m/n),string(字符串),hex(十六进制),integer(整数)。其中,需要特别介绍一下bool和tristate,bool只能表示选中和不选,而tristate还可以配置成模块(m),特别对于驱动程序的开发非常有用。
其他语法如下:
1)
a.
b.
prompt “NetworkingSupport”
2)
一个配置项可以有多个默认值,但是只有第一个被定义的值是有效的。
3)
如果依赖的配置项没有选中,那么就当前项也无法选中。
4)
如果当前项选中,那么也选中select后的选项。
5)
range A B表示当前值不小于A,不大于B
6)
4、choice/endchoice
choice的作用,多选一,有点像MFC中的Radio控件。参考arch/arm/Kconfig第205行。
choice
???????
endchoice
显示的结果如图2,进入这一项后,显示结果如图3.
图2
图3
可见,choice有点类似于menu,是在子窗口里选择,但是不同的是子窗口中只能选择一项。在prompt后会显示当前选择项的名称。
5、
source只是将另外一个Kconfig文件直接复制到当前位置而已。但它的作用也是明显的,可以将这个系统贯穿在一起。从开始位置arch/arm/Kconfig,来将整个系统都作为配置型。
配置分析
make menuconfig
script/Kconfig/mconf arch/arm/Kconfig
显然,在执行make menuconfig时,会自动调用scripts/Kconfig/mconf arch/arm/Kconfig开始系统的配置,那么arch/arm/Kconfig就是配置的起点。这个文件会通过source指令来调用其他目录下的Kconfig文件,从而完成整体配置。这样,arch/arm/Kconfig就可以理解成main函数,而source指令就有点类似于include。可以按照上面的语法,来分析Kconfig文件。
以上参考:http://photo.blog.sina.com.cn/list/blogpic.php?pid=4cd5d2bbtx6C0FdmLVf99&bid=4cd5d2bb0101gx9y&uid=1289081531
以下转自:http://blog.csdn.net/tommy_wxie/article/details/7280463
(注:本文所述内容来自kernel-2.6.30\Documentation\kbuild\makefiles.txt,适用于Linux 2.6内核)
Linux 2.6 内核Makefile
1概述
Makefile由五个部分组成:
- kernel Makefile,又叫top makefile,位于linux内核源代码的顶层目录,通过读取内核配置文件配置编译环境变量,并根据内核配置文件确定访问哪些子目录,用于编译Linux kernel目标文件vmlinux和模块module
- arch/$(ARCH)/Makefile:系统对应平台的Makefile。kernel Makefile会根据此Makefile提取体系结构相关的信息
- kbuild Makefiles:每个子目录都有kbuild Makefile,用来执行从其上层目录传递下来的命令,Kbuild Makefile从.config文件中提取信息,生成Kbuild编译内核需要的文件列表,它们负责生成built-in或模块化目标。(注意:kbuild Makefile是指使用kbuild结构的Makefile,内核中的大多数Makefile都是kbuild Makefile。)
- Scripts/Makefile.*:所有kbuildMakefile的规则,它们包含了定义/规则等。
- .config:内核配置文件(一般由make menuconfig生成)。
2 kbuild文件
2.1 obj-y和obj-m
obj-$(CONFIG_FOO) += foo.o |
2.1.1 obj-y生成built-in.o
$(obj-y)中的文件是有顺序的。联接也是有顺序的,那是因为有些函数(module_init()/__initcall)将会在启动时按照他们出现的顺序进行调用。
2.1.2目标由多个源文件编译得到
|
Kbuild能够识别用于组成目标文件的后缀-objs和后缀-y。这就让Kbuild Makefile可以通过使用 CONFIG_ 符号来判断该对象是否是用来组合对象的。
-objs后面是目标文件,而-y针对复合对象。
|
在这个例子中,如果 $(CONFIG_EXT2_FS_XATTR) 是 'y',xattr.o将是复合对象 ext2.o的一部分。
注意:当然,当你要将其编译进内核时,上面的语法同样适用。
所以,如果你的 CONFIG_EXT2_FS=y,那Kbuild会按你所期望的那样,生成 ext2.o文件,然后将其联接到 built-in.o中,最终连接进内核中。
如果CONFIG_ETX2_FS=m,由balloc.o和bitmap.o两个目标文件最终链接生成ext2.o,直至ext2.ko文件,保存在/lib/modules目录下方便加载。
obj-$(...)+=xxx.o 表示是否编译xxx.o目标文件
xxx.o目标依赖多个源文件的情况就下面两种:
xxx-y+=xxx1.o 复合对象xxx.o目标依赖哪些文件
xxx-$(...)+=xxx2.o xxx3.o 复合对象xxx.o目标依赖哪些文件
或者xxx-objs+=xxx1.o xxx2.o xxx3.o 目标文件xxx.o依赖哪些文件
2.1.3调用子目录Makefile
|
2.2 lib-y和lib-m
2.3编译选项变量
2.3.1 ccflags-y、asflags-y、ldflags-y
这三个变量只在当前Makefile中有效。补充:$(KBUILD_CFLAGS)是定义在根目录Makefile中的变量,它适用于整个内核数。
2.3.2subdir-ccflags-y、subdir-asflags-y
这两个变量作用于当前Makefile及其所有子目录。
2.3.2CFLAGS_$@、AFLAGS_$@
这两个变量只在当前Makefile中有效。$@可以用来指定文件名,让不同文件可以使用不同的编译选项。例如:
|
2.3.3 EXTRA_CFLAGS
有时需要连接内核源代码外部的系统头文件,但Kbuild默认的系统头文件都在内核源代码内部,如何使用外部的头文件需要借助Kbuild系统的特殊规则
EXTRA_CFLAGS+=$(ext_include_path)
另外CFLAGS、EXTRA_CFLAGS、ccflags之间的区别是
ccflags是gcc编译器选项,而CFLAGS、EXTRA_CFLAGS是makefile内部的预定义变量
2.4 $(src)、$(obj)、$(kecho)
|
|
2.5 $(CC)相关功能
2.5.1 as-option、ld-option、cc-option
|
2.5.2 cc-option-yn
|
2.5.3 cc-option-align
|
2.5.4 cc-version、cc-ifversion、cc-fullversion
|
cc-ifversion在版本符合条件的前提下返回最后一个参数。示例如下:
|
如果$(CC)版本低于4.2,那么ccflags-y将等于-O1。
cc-fullversion给出更详细的版本信息,例如:
|
2.5.5 cc-cross-prefix
cc- cross-prefix用于检查是否存在给定前缀的$(CC),如存在,返回第一个匹配的前缀,否则返回空。如有多个前缀需要匹配,各前缀之间使用单个空格隔开。例如:
|
三、模块的编译
编译模块的时候,你可以将模块放在代码树中,用Make modules的方式来编译你的模块,obj-$(CONFIG_EXT2) += ext2.o即可
你也可以将模块相关文件目录放在代码树以外的位置,用如下的命令来编译模块:
make -C <path to kernel src> M=$PWD modules
-C指定代码树的位置,M=$PWD或M='PWD'告诉kbuild回到当前目录来执行build操作