一步一步学习 Linux 驱动之驱动模块 MakeFile 解析

时间:2021-07-24 15:48:54

make命令执行时,需要一个 Makefile 文件,以告诉make命令需要怎么样的去编译和链接程序。

一、使用条件判断

    下面的例子,判断$(CC)变量是否“gcc”,如果是的话,则使用GNU函数编译目标。 

libs_for_gcc = -lgnu 
normal_libs = 

foo: $(objects) 
ifeq ($(CC),gcc) 
     $(CC) -o foo $(objects) $(libs_for_gcc) 
else 
     $(CC) -o foo $(objects) $(normal_libs) 
endif 

      可见,在上面示例的这个规则中,目标“foo”可以根据变量“$(CC)”值来选取不同的函数库来编译程序。 

我们可以从上面的示例中看到三个关键字:ifeq、else和endif。ifeq的意思表示条件语句的开始,并指定一个条件表达式,表达式包含两个参数,以逗号分隔,表达式以圆括号括起。else表示条件表达式为假的情况。endif表示一个条件语句的结束,任何一个条件表达式都应该以endif结束。 

libs_for_gcc = -lgnu 
normal_libs = 

ifeq ($(CC),gcc) 
    libs=$(libs_for_gcc) 
else 
    libs=$(normal_libs) 
endif 

foo: $(objects) 
     $(CC) -o foo $(objects) $(libs) 
下面是关于一段arm驱动程序的分析

obj-m :=hello.o

KERNELDIR :=/home/ZP1015/Desktop/linux-2.6.32.2

all:
	 make -C $(KERNELDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
	rm -f *.o *.ko *.mod.o *.mod.c *.symvers modul*

ifneq ($(KERNELRELEASE),)

obj-m :=hello.o

else

KERNELDIR :=/home/ZP1015/Desktop/linux-2.6.32.2

all:
	 make -C $(KERNELDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
	rm -f *.o *.ko *.mod.o *.mod.c *.symvers modul*

endif

1、ifeq”语法是ifeq (<arg1>;, <arg2>;),功能是比较参数“arg1”和“arg2”的值是否相同。ifneq刚好相反,比较两者的值是否不同其中有一些是我们常见或是见过的,第一个ifneq ($(KERNELRELEASE),)目前,有用处,它的由来是指在Linux源码根目录下的Makefile编译内核时,KERNELRELEASE宏会被定义,那么如果是从源码根目录开始的make则会将hello.o模块编译进内核。

KERNELDIR :=/home/ZP1015/Desktop/linux-2.6.32.2  这句是对KERNELDIR进行赋值,这个变量是后面我们用到的指代内核源码目录用的。

2、make -C $(KERNELDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-

这句是Makefile的规则:这里的$(MAKE)就相当于make-C 选项的作用是指将当前工作目录转移到你所指定的位置M=”选项的作用是,当用户需要以某个内核为基础编译一个外部模块的话,需要在make modules 命令中加入“M=dir”,程序会自动到你所指定的dir目录中查找模块源码,将其编译,生成KO文件。M不是makefile的选项,是内核根目录下的Makefile中使用的变量

3、具体编译过程

KERNELRELEASE:由Kernel顶层Makefile中定义。

判断变量KERNELRELEASE与空字符是否相同,即判断变量KERNELRELEASE的值是否为空,为空的话就进入else
第一次运行中,KERNELRELEASE没有被定义,所以进入else
$(MAKE) -C $(KERNELDIR) M=$(PWD)
此处读取KERNELDIR中的顶层Makefile。读取后又返回本目录。继续执行本目录Makefile。
则此时KERNELRELEASE被定义。进入if.
if和else之间的为kbuild语法的语句.

4、两段makefile对比分析

如何内核源码路径设置正确,其实两段makefile没有什么区别,作用完全一致。但是有用ifneq之后,可以确保是从内核构造系统调用的。如果内核源码路径设置错误,KERNELRELEASE没有定义,make就没有对象。所以建议用后面那段makefile