接第一篇
3.3.可加载模块目标 obj-m (Loadable module goals – obj-m)
obj-m指定将被构建为可加载内核模块的对象文件(object file)。
一个模块可以从一个源文件构建或者从多个源文件构建。如果模块仅仅从一个源文件构建,kbuild makefile仅仅把对象文件加到obj-m。如下:
#drivers/isdn/i4l/Makefile
obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
在这个例子中,$(CONFIG_ISDN_PPP_BSDCOMP)被求值为m.
If a kernel module is built from several source files, you specify that you want to build a module in the same way as above.
如果一个内核模块需要从多个源文件构建,你也是按照刚才提到的那一行指定。不过,除此之外,还要额外地指定,你的内核模块需要哪些对象文件。所以还需要设置<模块名>-objs变量。如下:
#drivers/isdn/i4l/Makefile
obj-$(CONFIG_ISDN) += isdn.o
isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o
在这个例子中,模块名是 isdn 。Kbuild将编译isdn-objs列出的所有对象文件,然后运行$(LD) –r把这些对象文件链接成一个文件isdn.o。
Kbuild用-objs后缀或者-y后缀识别构成复合对象文件(composite objects)的对象文件。这样,Makefile就可以使用CONFIG_* 符号来确定一个对象文件是不是一个复合对象文件的一部分。如下:
#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文件,如你所想,再把这个文件链接到build-in.o。
3.4. 导出符号的对象文件
并不需要在Makefile中为模块使用特殊的标记来导出符号。
3.5. 库文件目标(Library file goals – lib-y)
在obj-*中指定的对象文件列表或者被用来构建内核模块,或者被内建到内核映象文件之中。Makefile还能指定创建库文件的对象文件。所有在lib-y中指定的对象文件会被用来在对应文件夹下创建一个库文件。注意已经在obj-y中列出过的对象文件,如果再在lib-y中列出,则不会被用来创建库文件,因为这些对象文件将是全局可见的。为了一致性,lib-m中列出的对象文件会被包含到lib.a。
注意,同一个kbuild makefile会同时指定被内建到内核映象中的对象文件,也会指定用来创建库文件的对象文件。因此,在同一个文件夹下面有可能同时存在built-in.o和lib.a文件。
#arch/i386/lib/Makefile
lib-y := checksum.o delay.o
上例中,会基于checksum.o和delay.o创建一个库文件lib.a。为了让kbuild意识到该目录下有lib.a库文件被创建,这个目录需要被列入到libs-y。本教程将在6.3节”列出需要遍历的路径”中详述。
lib-y的使用通常受限于 lib/ 和 arch/*/lib。
3.6. 深入遍历子目录夹
每个Makefile文件只负则在当前文件夹下面构建对象。在子目录下面的构建则由子目录下面的对象Makefile负责。不过你需要使用使用obj-y或者obj-m告诉kbuild系统将进入哪些子目录。比如话:当前目录是fs/,ext2/是当前目录下面的一个子目录,为了告诉kbuild进入ext2/目录,使用以下的语句:
#fs/Makefile
obj-$(CONFIG_EXT2_FS) += ext2/
如果CONFIG_EXT2_FS被求值为y(内建)或者m(模块),那么obj-*变量就会告诉kbuild需要进入ext2/子目录继续编译。
Kbuild仅仅使用这个信息来通知是否进入某个子目录,而进入后的子目录下面是用内建方式编译还是编译成模块则是由子目录下面的Makefile文件指定。最好像上例那个使用CONFIG_*变量。这样的好处是,如果CONFIG_*变量的求值既不是y也不是m,那么kbuild就完全可以忽略掉某子目录了。
3.7. 编译选项/标识
EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS
所有的EXTRA_VARIABLES仅仅作用于它们被赋值的kbuild makefile,应用于所有该makefile文件中执行的命令。
$(EXTRA_CFLAGS)指定了编译C文件的C编译器的编译选项。
Example:
# drivers/sound/emu10k1/Makefile
EXTRA_CFLAGS += -I$(obj)
ifdef DEBUG
EXTRA_CFLAGS += -DEMU10K1_DEBUG
endif
变量$( EXTRA_CFLAGS)是必要的,因为最上级的Makefile定义的$(CFLAGS)作用于整个linux内核代码树。
而$(EXTRA_AFLAGS)的作用域则是每个文件夹下面单独的Makefile。
比如下面的例子编译汇编语言程序。
#arch/x86_64/kernel/Makefile
EXTRA_AFLAGS := -traditional
$(EXTRA_LDFLAGS) 用于当前Makefile文件中的$(LD)。
$(EXTRA_ARFLAGS) 则用于当前Makefile文件中的$(AR)。
Example:
#arch/m68k/fpsp040/Makefile
EXTRA_LDFLAGS := -x
未完待续
copyright ykyi.net