在上一篇文章中我们编写了一个 Makefile 文件用来编译工程,这个 Makefile 的内容如下:
1 main: main.o input.o calcu.o
2 gcc -o main main.o input.o calcu.o
3 main.o: main.c
4 gcc -c main.c
5 input.o: input.c
6 gcc -c input.c
7 calcu.o: calcu.c
8 gcc -c calcu.c
9 clean:
10 rm *.o
11 rm main
上述 Makefile 中第 3~8 行是将对应的.c 源文件编译为.o 文件,每一个 C 文件都要写一个对应的规则,如果工程中C 文件很多的话显然不能这么做。为此,我们可以使用 Makefile 中的模式规则,通过模式规则我们就可以使用一条规则来将所有的.c 文件编译为对应的.o 文件。
模式规则中,至少在规则的目标定定义中要包涵“%”,否则就是一般规则,目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串,比如“%.c”就是所有的以.c 结尾的文件,类似与通配符,a.%.c 就表示以 a.开头,以.c 结束的所有文件。
当“%”出现在目标中的时候,目标中“%”所代表的值决定了依赖中的“%”值,使用方法如下:
%.o : %.c
命令
因此前面的 Makefile 可以改为如下形式:
1 objects = main.o input.o calcu.o
2 main: $(objects)
3 gcc -o main $(objects)
4 %.o : %.c
5 #命令
6 clean:
7 rm *.o
8 rm main
修改以后的 Makefile 还不能运行,因为第5 行的命令我们还没写呢,第 5 行的命令我们需要借助另外一种强大的变量—自动化变量。
上面讲的模式规则中,目标和依赖都是一系列的文件,每一次对模式规则进行解析的时候都会是不同的目标和依赖文件,而命令只有一行,如何通过一行命令来从不同的依赖文件中生成对应的目标?自动化变量就是完成这个功能的!所谓自动化变量就是这种变量会把模式中所定义的一系列的文件自动的挨个取出,直至所有的符合模式的文件都取完,自动化变量只应该出现在规则的命令中,常用的自动化变量如下图所示:
自动化变量
图中的 7 个自动化变量中,常用的三种:$@、$<和$^,我们使用自动化变量来完成前面的 Makefile,最终的完整代码如下所示:
1 objects = main.o input.o calcu.o
2 main: $(objects)
3 gcc -o main $(objects)
4 %.o : %.c
5 gcc -c $<
6 clean:
7 rm *.o
8 rm main
上述代码代码就是修改后的完成的 Makefile,可以看出相比文章开始的Makefile的要精简了很多,核心就在于第 4、5 这两行,第 4 行使用了模式规则,第 5 行使用了自动化变量。