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