写Makefile粗心的后果

    其实,很多人都想搞嵌入式的驱动开发,也会去买各种各样的书籍来研究;书上的驱动程序讲的有理有据、仅仅有条,说的你心悦诚服然后你就会跟别人说“没错一个led驱动就是这么写的,对不会有错的!“,哎,显然我也是这种人(呵呵....);所以,当我第一次尝试把我原来写好(写好的代码指并未编译;也就是说连Makefile都没写的那种)的认为一定不会有问题的驱动程序搞到我够买的GT2440开发上去运行,之后才让我真正明白学习驱动到底该怎么学。

  好的,让我讲讲接下来发生了什么。首先,”什么驱动程序要和你的开发板所运行的内核目录链接编译!“还好我根据用户手册提示体验了make uIamge的快感,所以这个条件符合了。然后进行Makefile编写,好的下面给出两个版本;

版本一:
KERNELDIR = /linux-2.6.38.6

all:
	make -C $(KERNELDIR) M='pwd' modules

clean:
	make -C $(KERNELDIR) M='pwd' modules clean
	rm -rf modules.order

obj-m	+= frist_drv_new.o
版本二:
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /linux-2.6.38.6
PWD := $(shell pwd)
modules:	
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:	
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:	
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*
.PHONY: modules modules_install clean
else   
	 obj-m := frist_drv_new.o
endif

上述两个版本Makefile要实现的功能完全一样,只是相较于版本一而言版本二拥有更好的保护措施。结果make后,出现:

make -C /linux-2.6.38.6 M='pwd' modules
make[1]: Entering directory `/linux-2.6.38.6'
scripts/Makefile.build:17: /linux-2.6.38.6/pwd/Makefile: No such file or directory
make[2]: *** No rule to make target `/linux-2.6.38.6/pwd/Makefile'.  Stop.
make[1]: *** [_module_pwd] Error 2
make[1]: Leaving directory `/linux-2.6.38.6'
make: *** [all] Error 2

于是开始分析错误信息,第一个信息:scripts/Makefile.build:17:/linux-2.6.38.6/pwd/Makefile: No such file or directory

抓住重点no such file or directory”,好的应该是说内核目录下pwd文件下没有makefile这个文件;好吧,到内核源码下看看是什么情况先;一看我傻了,内核下压根原本就不存在这个文件。我的又天真的认为,嗯,可能是这个内核没有吧;于是我去网上有找了一个与书配套的linux-2.6.22.6版本的内核,解压后还是没有;那好吧,那就跳过算了。

看看下一个错误信息:make[2]: *** No rule to make target `/linux-2.6.38.6/pwd/Makefile'.

其实仔细看后面的错误都是因为上述的“/pwd/Makefile”不存在引起的。没有,那我建一个不就好了吗。就这样我重新建了一个“/pwd/Makefile”问题来了,这个makefile怎么写。这个makefile是用来干嘛的?(当时自己压根不懂上面那两版本的makefile到底是怎么让一个.c文件编译成.ko文件的,-C、M=代表什么)那就根据用的Makefile来推测这个Makefile用来干嘛吧,于是我找到了这句:obj-m := frist_drv_new.o ;既然还没有.o文件那这个makefile一定是用来生成.o文件的;于是我写了一个利用arm-linux-gcc编译.c文件的简单makefile;然后一make;然后no such file or directory”;没了,但是依旧存在make[2]: *** No rule to make target `/linux-2.6.38.6/pwd/Makefile'.

然后,查阅关于驱动程序的makefile详细解释(我手头上的书本只是给出了这个makefile压根就没解释),了解了-C和M="dir"的目的后,再次来看Makefile怎么看怎么没问题;

makefile的详细解释地址如下:http://www.embedu.org/Column/Column310.htm这篇文章讲的相当详细;

怎么看我都觉的makefile肯定没问题,于是我想尽然-C是转到内核目录下编译,那会不会是内核下的顶层makefile被出版这块开发板的工程师给修改了呢;所以使得才会出现这种情况呢。于是我打算去他的网址问问,但是遗憾的是原来我加了他们的Q群没过两天莫名奇妙被踢了,然后我就失去了他们的联系方式;更让人不解的是为什么他们的用户手册上竟然没有任何关于他们网站的信息;于是没办法,打开他们光盘提供的内核的makefile与我官方下载到的内核makefile进行比较;打开后,得到一个结论就现在自身的水平而言这是不可能做到的事;于是,直接把Makefile下内核目录改为下在的内核所在目录,结果还是那个样子。于是,得到最后结论还是makefile有问题。

于是没办法上论坛求助,结果有网友提出了一个办法就是将版本一makefile下的M=‘pwd’改为M=$(pwd),我想这不是一样的吗,好吧试试看看行不行先;一make它成功了,于是我非常激动的回复结贴;但是,当我“ls”我的驱动源码文件夹时,什么文件都没生成;然后,往上看编译信息发现编译的是内核目录下的-M编译的驱动模块;我自己写的驱动压根没编译,到这时已经耗了我将近3天的时间了。

绝望了的我开始找我的一个从事驱动开发的学长问他到底是怎么回事,于是他果断叫我发驱动源码和Makefile给他,再帮我看看。于是,在一分钟后他截了一张图给我;

好的到这里,真想大白;一切原因就是因为makefile中把“first_drv_new”打成了“frist_drv_new”,就是这么一个由粗心大意照成的错误,使得自己花费大量的时间去找寻本没有的错误;也使得自己对驱动makefile理解的更为透彻。(这是这个粗心带来的益处)不过,像这类错误一次就够了啊。

然后,修改Makefile后,一make你将会发现一大堆的错误;不过这些错误解决都比较简单,大多数错误为内核版本更新之后原来老内核下使用的函数或宏定义已经不存在,要找到对应新版本内核下使用的函数与宏,再进行逐一修改即可。

最后,编译完成后,在写一个测试程序编译好后与驱动模块一并拷贝到开发板上;此时你在运行编译好的测试程序发现权限不够,使用下面两句命令中的一个即可解决:

chmod 777 xxxx(测试程序名)

chmod +x  xxxx(测试程序名)

之后再运行(如果你的内核镜像与文件系统镜像都是这个公司原配的话),运行测试程序后不管是点灯还是灭灯都是没有明显现象的,原因是原配内核已经编译了加载led的驱动模块,且内核启动完成后默认执行了操作此模块的操作进程;你要先按照用户手册上关于led驱动模块测试处给出命令,将此占用led端口的进程stop。然后,在运行测试程序此时便可操作开发板上的led了。

你可能感兴趣的:(写Makefile粗心的后果)