LINUX驱动Makefile模板
网上有好多关于驱动的Makefile怎么写,驱动程序怎么运行,为什么驱动会没有main等等问题的问题的问题。下面我也给出我的驱动Makefile模板,这些东东都是在书籍和人家的研究成果上改进而来的,至于如何使用、怎么修改成自己的,大家就随意好了。
驱动测试有两种方式,一为内核树之内,一为内核树以外,前者有点复杂,涉及到将驱动放到合适的内核树目录,修改相应的Makefile以及Kconfig文件,不过,天下无难易之事,为之,难亦不难了;后者所做的劳动就不用那么多了,网上很多是使用这种方法,鄙人也随大流了。这个Makfile只适合于后者,特此说明。此外,内核的Makefile跟一般的应用程序的Makefile不太一样,就像驱动程序跟应用程序,内核头文件跟应用程序头文件等等,没必然关系,或者说是两码事,两者不能混为一谈。再有一点,驱动是跟内核打交道的,你的系统中必须有一个内核源代码,因为驱动的编译过程需要内核代码(或者只是头文件?未调查)。
闲话不多说,下面列出的Makefile在ldd3的基础上添加如下东东:样式输出,各种不同提示信息颜色不同,可自由修改;将模块名称独立出来,可用于单独一个驱动源代码文件,也可用于多个驱动源代码文件;增加另外几个伪目标。下面逐一说明。
#################################################################
# file name: Makefile
# A simple Makefile for driver
# by Late Lee at 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平台,需要修改的是蓝色黑体部分。网上有资料显示,交叉编译命令为
$make ARCH=arm CROSS_COMPILE=arm-linux-
在实际测试过程,发现只要内核源代码正确指向在开发板中使用的内核源代码目录(当然,该内核的Makefile要修改才能编译出适合开发板的内核),直接输入make就可以了。谁对谁错,大家实地去考察一下便知结果。
后记:在某次实践中,在模块名称后多了一个空格,编译死活通不过。所以要特别注意这些很细节的细节,像shell脚本、C语言中用到的“\”后面也不能有空格。最后附图两张,说明见下方文字。
图1 pc平台,使用fc9升级过的2.6.27.25内核,直接输入make。
![](http://www.latelee.org/images/upload/embedded-linux/makefile-for-driver.jpg)
图2 pc下交叉编译,使用的2.6.30.2内核为移植到开发板中的内核,顶层Makefile已修改体系结构ARCH以及交叉编译器CROSS_COMPILE。
驱动测试有两种方式,一为内核树之内,一为内核树以外,前者有点复杂,涉及到将驱动放到合适的内核树目录,修改相应的Makefile以及Kconfig文件,不过,天下无难易之事,为之,难亦不难了;后者所做的劳动就不用那么多了,网上很多是使用这种方法,鄙人也随大流了。这个Makfile只适合于后者,特此说明。此外,内核的Makefile跟一般的应用程序的Makefile不太一样,就像驱动程序跟应用程序,内核头文件跟应用程序头文件等等,没必然关系,或者说是两码事,两者不能混为一谈。再有一点,驱动是跟内核打交道的,你的系统中必须有一个内核源代码,因为驱动的编译过程需要内核代码(或者只是头文件?未调查)。
闲话不多说,下面列出的Makefile在ldd3的基础上添加如下东东:样式输出,各种不同提示信息颜色不同,可自由修改;将模块名称独立出来,可用于单独一个驱动源代码文件,也可用于多个驱动源代码文件;增加另外几个伪目标。下面逐一说明。
#################################################################
# file name: Makefile
# A simple Makefile for driver
# by Late Lee at 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平台,需要修改的是蓝色黑体部分。网上有资料显示,交叉编译命令为
$make ARCH=arm CROSS_COMPILE=arm-linux-
在实际测试过程,发现只要内核源代码正确指向在开发板中使用的内核源代码目录(当然,该内核的Makefile要修改才能编译出适合开发板的内核),直接输入make就可以了。谁对谁错,大家实地去考察一下便知结果。
后记:在某次实践中,在模块名称后多了一个空格,编译死活通不过。所以要特别注意这些很细节的细节,像shell脚本、C语言中用到的“\”后面也不能有空格。最后附图两张,说明见下方文字。
图1 pc平台,使用fc9升级过的2.6.27.25内核,直接输入make。
![](http://www.latelee.org/images/upload/embedded-linux/makefile-for-driver.jpg)
图2 pc下交叉编译,使用的2.6.30.2内核为移植到开发板中的内核,顶层Makefile已修改体系结构ARCH以及交叉编译器CROSS_COMPILE。