makefile是用来进行工程管理的一个工具;linux下,输入make,会自动执行当前目录下makefile文件/Makefile文件,如果两者均存在,优先执行makefile文件;makefile的书写方式,类似于shell脚本;
makefile简单例子: 以linux系统为例,现在有5个文件,分别为:main.c, fun1.c, fun1.h, fun2.c, fun2.h; 以命令为例:gcc main.c fun1.c fun2.c;
那么编译链接之间的依赖递推关系为:
a.out 依赖于 main.o fun1.o fun2.o
main.o 依赖于 main.c
fun1.o 依赖于 fun1.c
fun2.o 依赖于 fun2.c
按照上述的依赖关系写makefile如下:
即命令:gcc main.c fun1.c fun2.c -o mycase
mycase:main.o fun1.o fun2.o
gcc main.o fun1.o fun2.o -o mycase
main.o:main.c
gcc main.c -c -Wall -g -o main.o
fun1.o:fun1.c
gcc fun1.c -c -Wall -g -o fun1.o
fun2.o:fun2.c
gcc fun2.c -c -Wall -g -o fun2.o
最终我们想执行的是gcc main.o fun1.o fun2.o -o mycase,但是三个.o文件均没有,那么make就会往下去寻找执行,可以将此过程想想成一个倒置的树;想要执行根,但是根所需要的文件在叶子,那么就先去执行叶子,产生根想要的文件,再来执行根;
接下来改写makefile:
一般情况下,习惯于在makefile下面添加上下面这句话来避免重复询问是否要删除所产生的中间文件:
clean:
rm *.o mycase -rf
执行命令: make clean
会删除刚才生成的可执行文件mycase 还有所有的 .o 文件
回过头来看刚才所写的makefile,会发现写了很多重复性话语,显然是可以避免的,可以写的更加简练:
OBJS=main.o fun1.o fun2.o
CC=gcc
CFLAGS+=-c -Wall -g
mycase:$(OBJS)
$(CC) $(OBJS) -o mycase
main.o:main.c
$(CC) main.c $(CFLAGS) -o main.o
fun1.o:fun1.c
$(CC) fun1.c $(CFLAGS) -o fun1.o
fun2.o:fun2.c
$(CC) fun2.c $(CFLAGS) -o fun2.o
clean:
$(RM) *.o mycase -r
makefile写成这样其实还是没有简化太多,写起来依然累的要命,那么可以再进一步简化:
OBJS=main.o fun1.o fun2.o
CC=gcc
CFLAGS+=-c -Wall -g
mycase:$(OBJS)
$(CC) $^ -o $@
main.o:main.c
$(CC) $^ $(CFLAGS) -o $@
fun1.o:fun1.c
$(CC) $^ $(CFLAGS) -o $@
fun2.o:fun2.c
$(CC) $^ $(CFLAGS) -o $@
clean:
$(RM) *.o mycase -r
写成这样似乎简化了一些,但是能不能再写的简化一点儿呢?答案是可以的,观察发现上述代码中存在一种公式,也就是说可以将上述的依赖关系抽象成一种公式:
OBJS=main.o fun1.o fun2.o
CC=gcc
CFLAGS+=-c -Wall -g
mycase:$(OBJS)
$(CC) $^ -o $@
%.o:%.c
$(CC) $^ $(CFLAGS) -o $@
clean:
$(RM) *.o mycase -r
这样就完成了一个基本的makefile的编写。
想要继续进阶makefile,可以参考陈皓的 跟我一起写makefile。