隐含规则1:编译C语言的隐含规则
.o的目标的依赖目标会自动推导为.c,并且其生成命令是$(CC) -c $(CPPFLAGS) $(CFLAGS)
那么makefile可以简写——去掉.o到.c的依赖也可以,那么makefile内容可以简化如下:
include config.mk
test:$(OBJS)
gcc $(OBJS) -o test
.PHONY:clean
clean:
rm *.o test
隐含规则2:链接Object文件的隐含规则
n目标依赖于n.o,通过运行C语言编译器来运行链接程序生成(一般是“ld”),其命令是:$(CC) $(LDFLAGS) n.o
x : x.o y.o#并且x.c、y.c都存在时,隐含命令如下
cc -c x.c -o x.o
cc -c y.c -o y.o
cc x.o y.o -o x
注意:如果没有一个源文件(如上例中的x.c)和目标名字(如上例中的x)相关联,那么最好写出自己的生成规则,不然,隐含规则会报错。
那么根据此隐含规则,我们又可以将makefile文件进行优化为以下内容:
include config.mk
f1:f1.o f2.o main.o
.PHONY:clean
clean:
rm *.o test
第二行代码中就是应用了规则二,目标文件可以改成f2、main都可以,但是必须是和所依赖的文件相关联,如果不关联(如:test)那么makefile就会报错。
VPATH:虚路径
在一些大的工程中,有大量的源文件,我们通常的做法是把许多的源文件分类,并且存放在不同的目录下。
所以,当make需要找文件依赖关系时,可以在文件前加上路径,最好的办法就是把一个路径告诉make,让make在自动的去找。
makefile文件中的特殊变量VPATH就是完成这么一个功能,如果没有指明这个变量,make只会在当前目录中去寻找依赖文件和目标文件。
如果定义了这个变量,那么,make就会在当前目录找不到的情况下,到指定的目录中去找寻文件了。
VPATH = src:../headers
上面的定义指定两个目录,‘src’和‘…/headers’,make会按照这个顺序进行搜索。目录由‘冒号’分割。当然,当前目录永远是最高优先级搜索的地方。
示例:
新建src1/f1.c、src2/f2.c、main/main.c、include/head.h、include/myinclude.h四个文件,并输入一下内容:
src1/f1.c内容如下:
#include
void print1()
{
printf("Message:f1.c\n");
}
src2/f2.c内容如下:
#include
void print2()
{
printf("Message:f2.c\n");
}
include/head.h内容如下:
#include
void print2()
{
printf("Message:f2.c\n");
}
clude/myinclude.h内容如下:
#include
main/main.c内容如下:
#include
#include "head.h"#调用自己写的头文件用引号
int main()
{
print1();
print2();
printf("end main\n");
return 0;
}
没有使用VPATH的的makefile内容如下:
CFLAGS=-c -Wall -I include
test:src1/f1.o src2/f2.o main/main.o
gcc src1/f1.o src2/f2.o main/main.o -o test
src1/f1.o:src1/f1.c#可以省略
gcc $(CFLAGS) $^ -o $@
src2/f2.o:src2/f2.c
gcc $(CFLAGS) $^ -o $@
main/main.o:main/main.c
gcc $(CFLAGS) $^ -o $@#可以省略
.PHONY:clean
clean:
find ./ -name "*.o" -exec rm {} \;;test#删除当前目录下所有的.o文件
以上代码中根据隐含规则可以简化——第4行~第9行可以省略。
利用VPATH进行优化makefile:
CFLAGS=-c -Wall -I include
VPATH=src1 src2 main
f1:src1/f1.o src2/f2.o main/main.o
.PHONY:clean
clean:
find ./ -name "*.o" -exec rm {} \;;test