小编读完陈皓大神关于Makefile的博客之后,对Makefile的使用有了更深入的理解,在此附上陈皓大神makefile博客的链接:https://blog.csdn.net/haoel/article/details/2886。博客中针对Makefile的介绍、编译和链接原理、以及规则都做了详细的介绍,因此小编在此仅归纳两种常用的makefile文件的写法,希望可以帮助读者掌握Makefile的写法。(阅读过程中若有不理解之处,可参考陈皓大神的博客,以此来提升理解)
一、初学者和小项目可使用的makefile写法
举例:一个项目有1个头文件(wrap.h),三个源文件(server.c、client.c、wrap.c),要生成可执行目标文件server、client,最简单的写法如下所示:
all:server client //目标文件server和client
server:server.o wrap.o //server的依赖为server.o和wrap.o
gcc server.o wrap.o -o server -Wall //利用gcc编译器生成可执行文件server
client:client.o wrap.o //client的依赖为client.o和wrap.o
gcc client.o wrap.o -o client -Wall //利用gcc编译器生成可执行文件client
server.o:server.c wrap.h //server.o的依赖为server.c和wrap.h
gcc -c server.c -o server.o -Wall //利用gcc编译器生成中间目标文件server.o
client.o:client.c wrap.h //同上
gcc -c client.c -o client.o -Wall
wrap.o:wrap.c wrap.h //同上
gcc -c wrap.c -o wrap.o -Wall
在终端输入命令make,运行makefile文件可得到编译结果如下:
我们可以看到编译成功,成功生成了client.o、wrap.o、server.o等中间目标文件以及client、server等可执行目标文件,并且运行服务器端和客户端可以实现其功能,在此就不演示了。
该方法比较易懂,只需要依次对我们的.c文件形成依赖关系,就可以根据目标文件的需要生成对应的依赖目标,但是当一个项目比较大即有大量的.c文件时,程序员需要编写大量的依赖关系,工作量是非常大的,且容易遗漏出错,因此需要掌握下面的方法
二、大项目必须会使用的makefile写法
举例同上,makefile文件为:
target1=server //服务器运行目标文件server
target2=client //客户端目标文件client
src=$(wildcard *.c) //用wildcard函数找到所有.c文件,server.c、client.c、wrap.c
deps=$(wildcard *.h) //用wildcard函数找到所有的.h文件,wrap.h
obj=$(patsubst %.c,%.o,$(src)) //用patsubst函数将所有.c文件替换成.o文件
all:$(target1) $(target2) //目标文件server和client,多个目标文件一定形成此依赖关系
$(target1):server.o wrap.o //server的依赖为server.o和wrap.o
gcc $^ -o $@ -Wall //利用gcc编译器生成可执行文件server
$(target2):client.o wrap.o //client的依赖为client.o和wrap.o
gcc $^ -o $@ -Wall //利用gcc编译器生成可执行文件client
%.o:%.c $(deps) //任意一个.o中间目标文件的依赖是其对应的.c文件,如:client.o的依赖为client.c
gcc -c $< -o $@ -Wall //根据目标文件编译的需求依次将依赖编译成对应的中间目标文件
.PHONY:clean //伪文件,需要在终端输入make clean才会调用
clean:
-rm -rf $(target1) $(target2) $(obj) //删除所有的目标文件以及中间目标文件,用于重新编译。
在终端输入命令make,运行makefile文件可得到编译结果如下:
我们可以看到编译结果与第一种方法是一样的,但是依赖关系的表示却十分简单,即使有几百个依赖关系也同样适用,所以这种写法对大型项目的开发是非常有好处的
常用的三个自动变量含义:
1、$< 第一个依赖文件,若有多个目标文件,依次编译依赖文件
2、$^ 所有依赖文件的集合
3、$@ 目标文件的集合
三、常用的makefile文件模板
在本例中,因为涉及到服务器端server和客户端client有多个目标文件,但是常规项目中往往只有一个目标文件,这样makefile的写法就更为简单了,可套用以下模板:
target=main //想要生成的可执行文件名称可自定义,此处为main
src=$(wildcard *.c)
deps=$(wildcard *.h)
obj=$(patsubst %.c,%.o,$(src))
$(target):$(obj)
gcc $^ -o $@ -Wall
%.o:%.c $(deps)
gcc -c $< -o $@ -Wall
.PHONY:clean
clean:
-rm -rf $(target) $(obj)
四、总结
常见的生成一个目标文件的makefile,直接套用第三种方法的模板即可,
生成多个目标文件的makefile,可参照第二种方法的案例再稍加修改即可。
若有疑问,可在评论区留言!