module Makefile
第一种形式
在linux上在进行module编译时makefile最简单的形式如下:
obj-m += scull.o #这里就一句话,所以make命令就不能省略 # make -C /usr/src/linux-headers-2.6.31-14-generic/ SUBDIRS=$PWD modules #注意,SUBDIRS是较老的使用方式,与M等效,建议使用M #http://tscsh.blog.163.com/blog/static/2003201032013151544087/ #PWD := $(shell pwd) #clean: # $(MAKE) -C /usr/src/linux-headers-2.6.31-14-generic/ M=$(PWD) modules clean这种形式由于只有一句话,所以不能简单的make,要把make命令全部打出来,如上注释。
第二种形式
稍微复杂的形式如下:
注意,此Makefile文件中有很多变量都是内核树中Makefile文件中定义的,因为module编译必须要链接内核树中的文件,也就要依赖内核树中的Makefile文件:
obj-m := scull.o KERN_DIR := /lib/modules/$(shell uname -r)/build #或者写成 #KERN_DIR := /usr/src/linux-headers-$(shell uname -r) PWD := $(shell pwd) all: #module: $(MAKE) -C $(KERN_DIR) M=$(PWD) modules clean: $(MAKE) -C $(KERN_DIR) M=$(PWD) modules clean #modules_install目标我目前了解到的是会把生成的.ko文件放到/lib/modules/2.6.31-14-generic/extra/文件夹下 modules_install: $(MAKE) -C $(KERN_DIR) M=$(PWD) modules_install
obj-m变量指定了要编译的模块,这里赋值为scull.o,最终生成的模块将是scull.ko,make命令中的modules目标就是讲obj-m变量作为要生成的对象的。如果scull.ko依赖于多个.c文件,可以通过引入变量scull-objs来实现,如果scull.ko的实现在两个源文件中scull.c scull2.c,则Makefile中应该加入以下语句:
scull-objs := scull.o scull2.o
当执行make命令时,默认以all为目标,执行$(MAKE) -C $(KERN_DIR) M=$(PWD) modules,KERN_DIR变量内容为内核树的所在路径,-C指令首先改变目录到-C指定的位置,M为内核Makefile文件中指定的变量,作用是在构造modules目标之前返回到模块源码目录,这样会重新读取一遍该Makefile中的变量,最终生成scull.ko。
第三种形式
由于对该模块源码目录下Makefile文件有双次读取,所以我们也可以使用ifneq语句来保证次Makefile中的变量分两次读取,避免重复读取
ifneq ($(KERNELRELEASE),) obj-m += scull.o else KERN_DIR := /lib/modules/$(shell uname -r)/build #或者写成 #KERN_DIR := /usr/src/linux-headers-$(shell uname -r) PWD := $(shell pwd) all: #module: $(MAKE) -C $(KERN_DIR) M=$(PWD) modules clean: $(MAKE) -C $(KERN_DIR) M=$(PWD) modules clean modules_install: $(MAKE) -C $(KERN_DIR) M=$(PWD) modules_install endifKERNELRELEASE变量是在内核源码目录的Makefile中定义的,所以条件不成立,首次读取直接读取else后的变量,并在首次读取时将modules作为make目标,返回后的第二次读取,设置obj-m变量,然后生成modules目标。