《模块编译Makefile模板 &&Nothing to be done for `modules'.docx》由会员分享,可在线阅读,更多相关《模块编译Makefile模板 &&Nothing to be done for `modules'.docx(4页珍藏版)》请在三一办公上搜索。
1、模块编译Makefile模板 & Nothing to be done for modules最近在linux2.4内核上编译一个动态加载模块时遇到这样一个问题,执行make时编译器不编makefile文件中所指定的目标文件,而是提示一句 Nothing to be done for modules,然后就退出了。 主控Makefile文件中采用的式来编译模块的: $(MAKE) -C $(KERNELPATH) SUBDIRS=$(shell pwd) modules 下面我们来分析一下原因,并寻找解决的方法。 一、先看看执行$(MAKE) -C $(KERNELPATH) SUBDIRS=
2、$(shell pwd) modules后脚本是怎样执行的:1.进入内核目录,执行modules目标 modules: $(patsubst %, _mod_%, $(SUBDIRS) 这里把传入的SUBDIRS变量加上一个_mod_前缀,使modules依赖于他 $(patsubst %, _mod_%, $(SUBDIRS) : include/linux/version.h include/config/MARKER $(MAKE) -C $(patsubst _mod_%, %, $) CFLAGS=$(CFLAGS) $(MODFLAGS) MAKING_MODULES=1 modu
3、les 这里回到SUBDIRS执行modules,但是带入CFLAGS变量 2.回到SUBDIRS执行modules目标,但是Makefile文件中根本就没有这个目标的存在,当然会报Nothing to be done for modules了,那么这个modules目标到底是什么呢? 找个2.4与2.6内核通用的模块编译Makefile文件看看,它通常在目标all之前有这样几行语句: -include $(TOPDIR)/Rules.make all_targets:all 这就是问题的关键所在!TOPDIR变量内核根Makefile文件中定义的 TOPDIR := $(shell /bin
4、/pwd) 就是指内核的路径,所以Include前面的 “-”就显得尤为重要。当我们敲make命令时第一次进入模块的Makefile文件,这时Rules.make文件当然找不到,但由于加了“-”所以脚 本会忽略这个错误,当进入内核然后再出来时TOPDIR得到了赋值,理所当然脚本就把位于内核根目录的Rules.make文件内容插入到语句所在的位 置,到这里我们就知道怎么接着分析上面的编译过程了,请接着看。 3.进入Rules.make文件,果然有modules这个目标 .PHONY: modules modules: $(ALL_MOBJS) dummy $(patsubst %,_modsub
5、dir_%,$(MOD_DIRS) 它依赖于ALL_MOBJS、dummy和$(patsubst %,_modsubdir_%,$(MOD_DIRS) 看看ALL_MOBJS是什么: ALL_MOBJS = $(filter-out $(obj-y), $(obj-m) 它过滤掉obj-m中所有和obj-y中相同 的单词,保留obj-m中独有的单词,实际上就是保留了在自己的makefile文件中定义的obj-m变量,就是我们最终要生成的模块名字。所以 make就会去寻找我们的obj-m目标并执行它。Modules的最后一个依赖条件仅在我们编译的模块还有别的子模块时才需要用,通常这个目标是空的。
6、 4.进入模块自己的makefile文件,找obj-m目标,并执行. = 引用 模块编译Makefile模板 引用 geyingzhen 的 模块编译Makefile模板 ifneq ($(KERNELRELEASE), ) /判断KERNELRELEASE是否定/义,KERNELRELEASE是在linux内核源码中主Makefile中定义的 obj-m:=drive.o /编译生成目标文件 else /若KERNELRELEASE没有否定义, KERNELDIR ?=/lib/modules/$(shell uname -r)/build /KERNELDIR是本Makefile 依赖的l
7、inux内核源码路径 ,如是交叉编译时就取开发板上运行的源码路径 PWD :=$(shell pwd) /取当前的路径, default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules /到linux源码所在的目录执行主Makefile 并当前路径传给主Makefile,告诉主Makefile执行完后返回到当前目录,执行Makefile, /moudules可以省略,加上表示是以模块形式编译. endif KERNELRELEASE 是在内核源码的顶层Makefile中定义的一个变量,在第一次读取执行此Makefile时, KERNELRELEASE没有被定
8、义,所以make将读取执行else之后的内容。如果make的目标是clean,直接执行clean操作,然后结 束。当make的目标为all时,-C $(KDIR) 指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。当从内核源码目录返回时,KERNELRELEASE已被被定义,kbuild也被启动去 解析kbuild语法的语句,make将继续读取else之前的内容。else之前的内容为kbuild语法的语句, 指明模块源码中各文件的依赖关系,以及要生成的目标模块名。mymodule-objs := file1.o file2.o表示mymoudule.o 由file1.o与file2.o 连接生成。 obj-m := mymodule.o表示编译连接后将生成mymodule.o模块。 obj-m := hook_open_exec.o KDIR:=/lib/modules/$(shell uname -r)/build PWD=$(shell pwd) all: make -C $(KDIR) M=$(PWD) modules clean: make -C $(KDIR) M=$(PWD) clean 编译其他的.c文件只要更改obj就行了