Makefile文件类似于一个shell脚本,文件定义了一系列规则来指定项目源文件的编译过程,Linux中的make指令就是执行当前目录下的Makefile文件。
Makefild规则:一个Makefile可以有有多个规则,但是都是为了完成第一条规则。格式为:
[目标]:[依赖]
[命令]
命令执行之前需要检查以来是否存在,如果不存在则向下检查其他规则,寻找有没有一个规则的目标就是这个依赖项,如果找到了就执行该命令并返回检查处。在执行规则中的命令前会比较目标和依赖的更新时间,如果目标的时间比依赖的时间晚,则执行命令从新生成目标,反之则直接跳过不执行。如下为参考代码:
app:add.o div.o mult.o sub.o main.o
gcc add.o div.o mult.o sub.o main.o -o app
add.o:add.c
gcc -c add.c -o add.o
div.o:div.c
gcc -c div.c -o div.o
mult.o:mult.c
gcc -c mult.c -o mult.o
sub.o:sub.c
gcc -c sub.c -o sub.o
main.o:main.c
gcc -c main.c -o main.o
上面是方便理解下写的Makefile文件然而在Makefile制作过程中也有许多语法规则,可以让文件制作和修改更加便捷,下面介绍一些。
- 自定义变量:变量名=变量值 var=hello $(var)
- 预定义变量:
- AR:归档维护程序名称,默认值为ar
- CC:c编译器的名称,默认值为cc
- CXX:c++编译器,默认值为g++
- $@:目标的完整名称
- $<:第一个依赖文件的名称
- $^:所有的依赖名称
- $(wildcard PATTERN....)
- 功能:获取指定目录下指定类型的列表
- 示例:$(wildcard *.c ./sub/*.c) 获取当前目录下和sub子目录下的.c文件列表。
- $(patsubst <pattern>,<replacement>,<text>)
- 功能:查找txet中的单词是否满足pattern满足则以replacement进行替换。
- pattern和replacement可以包含通配符%
- 示例:$(patsubst %.c,%.o,x.c bar.c) 返回格式为 下x.o,bar.o
基于上面的这些规则我们现在对前面的Makefile文件进行改写如下:
#定义变量
src=$(wildcard *.c)
objs=$(patsubst %.c,%.o,$(src))
target=app
$(target):$(objs)
$(CC) $^ -o $@
%.o:%.c
$(CC) -c $< -o $@
.PHONY:
clean:
rm *.o
进行编译测试结果
wjy@wjyUbuntu18:~/Linux/lesson07$ make
cc -c mult.c -o mult.o
cc -c main.c -o main.o
cc -c add.c -o add.o
cc -c div.c -o div.o
cc -c sub.c -o sub.o
cc mult.o main.o add.o div.o sub.o -o app
wjy@wjyUbuntu18:~/Linux/lesson07$ ls
add.c add.o app div.c div.o head.h main.c main.o Makefile mult.c mult.o redis-5.0.10 sub.c sub.o
wjy@wjyUbuntu18:~/Linux/lesson07$ make clean
rm *.o
wjy@wjyUbuntu18:~/Linux/lesson07$ ls
add.c app div.c head.h main.c Makefile mult.c redis-5.0.10 sub.c
wjy@wjyUbuntu18:~/Linux/lesson07$ ./app
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667