我的驱动Makefile模板

网上有好多关于驱动的Makefile怎么写,驱动程序怎么运行,为什么驱动会没有main等等问题的问题的问题。下面我也给出我的驱动Makefile模板,这些东东都是在书籍和人家的研究成果上改进而来的,至于如何使用、怎么修改成自己的,大家就随意好了。

驱动测试有两种方式,一为内核树之内,一为内核树以外,前者有点复杂,涉及到将驱动放到合适的内核树目录,修改相应的Makefile以及Kconfig文件,不过,天下无难易之事,为之,难亦不难了;后者所做的劳动就不用那么多了,网上很多是使用这种方法,鄙人也随大流了。这个Makfile只适合于后者,特此说明。此外,内核的Makefile跟一般的应用程序的Makefile不太一样,就像驱动程序跟应用程序,内核头文件跟应用程序头文件等等,没必然关系,或者说是两码事,两者不能混为一谈。再有一点,驱动是跟内核打交道的,你的系统中必须有一个内核源代码,因为驱动的编译过程需要内核代码(或者只是头文件?未调查)。

闲话不多说,下面列出的Makefile在ldd3的基础上添加如下东东:样式输出,各种不同提示信息颜色不同,可自由修改;将模块名称独立出来,可用于单独一个驱动源代码文件,也可用于多个驱动源代码文件;增加另外几个伪目标。下面逐一说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#################################################################

# file name: Makefile

# A simple Makefile for driver

# by Late Lee at [www.latelee.org](http://www.latelee.org/)

# based on LDD3 and other guys works

# copyleft @ 2010

#

#################################################################

############样式输出

### nothing, just for fun

OFFSET=x1b[21G # 21 col

COLOR1=x1b[0;32m # green

COLOR2=x1b[1;35m #

COLOR3=x1b[1;31m # red

RESET=x1b[0m

CLEAN_BEGIN=@echo -e "$(OFFSET)$(COLOR2)Cleaning up ...$(RESET)"

CLEAN_END=@echo -e "$(OFFSET)$(COLOR2)[Done.]$(RESET)"

MAKE_BEGIN=@echo -ne "$(OFFSET)$(COLOR1)Compiling ...$(RESET)"

MAKE_DONE="$(OFFSET)$(COLOR1)[Job done!]$(RESET)";

MAKE_ERR="$(OFFSET)$(COLOR3)[Oops! Error occurred]$(RESET)";

### nothing end here

**CROSS_COMPILE=arm-linux-**

**CC := $(CROSS_COMPILE)gcc**

**LD := $(CROSS_COMPILE)ld**

######### DEBUG部分

#DEBUG = y

ifeq ($(DEBUG), y)

DEBFLAGS = -O -g

else

DEBFLAGS = -O1

endif

# sth wrong here, don’t know why

#EXTRA_CFLAGS += $(DEBFLAGS) -I$(LDDINCDIR)

#########驱动模块名称以及源文件部分

# module name here

**MODULE = GotoHell**

# obj-m = module

# obj-y = into kernel

# foo.o -> foo.ko

ifneq ($(KERNELRELEASE), )

obj-m := $(MODULE).o

# 驱动源代码文件,.o形式

# your obj file(s) here

**$(MODULE)-objs := foo.o bar.o**

else

**KERNELDIR ?= /lib/modules/$(shell uname -r)/build**

PWD := $(shell pwd)

##########真正编译部分,添加了if语句

all:

$(MAKE_BEGIN)

@echo

@if

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules;

then echo -e $(MAKE_DONE)

else

echo -e $(MAKE_ERR)

exit 1;

fi

endif

#####这个clean把生成的杂七杂八文件都删除,可用ls –al查看

clean:

$(CLEAN_BEGIN)

rm -rf *.cmd *.o *.ko *.mod.c *.symvers *.order *.markers

.tmp_versions .*.cmd *~

$(CLEAN_END)

########伪目标部分

install:

@echo -e "$(COLOR3) Note:"

@echo -e "To install or not install,that is a question.$(RESET)"

modules:

@echo -e "$(COLOR3)Do not need to do this.$(RESET)"

modules_install:

@echo -e "$(COLOR3)Do not need to do this.$(RESET)"

.PHONY: all clean install modules modules_install

############# Makefile end here

1、样式输出:
OFFSET指定了那些提示信息的偏移,本想用个什么方法让它居中的,没找到,就直接指定到第21列了。
COLOR那几个是指提示信息的颜色,这个可以百度一下SHELL颜色,至于前景色,背景色怎么搭配才好看,那是阁下的事情了。
RESET将前面已经设置好的颜色统统还原到系统默认的。
再下来的几个提示信息,也是根据个人喜爱来修改。
本部分完全是optional,如果觉得占太多行不好看,完全可以去掉,省得看得眼花。

2、debug部分
一开始是用CFLAGS,结果不行,提示要使用EXTRA_CFLAGS,结果出了很多看不懂的错误信息,就不理它了,等以后真正用到调试再说,可能要重新配置内核才行。

3、驱动模块名称 网上好多都是obj-m:=hello.o这个形式,我一直想改掉,结果找到方法了。obj-m:=$(MODULE).o中的m是说要将这个驱动做成模块,使用insmod加载、rmmod删除。而在内核很多目录中的Makefile还可以看到另一种形式obj-y,意思是说将这个驱动搞到内核中去,跟着内核一起混,系统启动时它就加载了。关于:=就直接百度了,顺便可以把$@$<$^这几个给一起学习了。注意,$(MODULE).o是.o文件,不是.ko文件,内核会帮你从hello.o创建一个hello.ko模块的。$(MODULE)-objs := foo.o bar.o是说这个模块由两个文件组成,这里也是.o文件。实际使用中需要修改模块名称以及模块源文件(其实算是目标文件)名称。
后面的不用说了,大家都知道的。

在PC平台下编写驱动,需要修改的地方是该Makefile模板中红色黑体部分。如果在ARM平台,需要修改的是蓝色黑体部分。网上有资料显示,交叉编译命令为

1
$make ARCH=arm CROSS_COMPILE=arm-linux-

在实际测试过程,发现只要内核源代码正确指向在开发板中使用的内核源代码目录(当然,该内核的Makefile要修改才能编译出适合开发板的内核),直接输入make就可以了。谁对谁错,大家实地去考察一下便知结果。
关于Makefile是如何进行编译的,我在CSDN上找到一篇文章,来自sumsky的专栏,文章地址是http://blog.csdn.net/abc19842008/archive/2008/02/14/2095836.aspx。大家可以去看一下。下面这话是文章精华部分,现录于此。

当我们敲下make时,我们进入了这个权威的makefile二次。第一次进入makefile,发现KERNELRELEASE没有被设置时,于是她根据build这个符号链接定位内核源代码目录,然后进入default,开始第二个make,-C选项进入内核源代码目录,找到顶层的makefile,然后-M返回当前目录执行makefile文件,这就是第二次进入这个makefile,在这次,由于KERNELRELEASE变量已经定义,因此不需要进入else语言,在这里,obj-m:=hello.o这个语句和我们以前不是驱动程序中的makefile不同,在这里内核会帮你处理一切,这句话是告诉内核,需要从hello.o创建一个驱动模型(module)。

lwn上是这么说的:

The makefile will be read twice; the first time it will simply invoke the kernel build system, while the actual work will get done in the second pass. A makefile written in this way is simple, and it should be robust with regard to kernel build changes.

这个模板显示有点臃肿,但青菜萝卜,各有所爱,看久了就不觉得麻烦啰嗦了,而且能应用于驱动程序绝大部分场合。
本文适合那些喜欢捣鼓且有闲情逸致的人来研究,只追求结果者可以飘过。

后记:在某次实践中,在模块名称后多了一个空格,编译死活通不过。所以要特别注意这些很细节的细节,像shell脚本、C语言中用到的“”后面也不能有空格。最后附图两张,说明见下方文字。

图1 pc平台,使用fc9升级过的2.6.27.25内核,直接输入make。
makefile-for-driver

图2 pc下交叉编译,使用的2.6.30.2内核为移植到开发板中的内核,顶层Makefile已修改体系结构ARCH以及交叉编译器CROSS_COMPILE。
[make-for-arm