5.使用自动变量的Makefile
还记得上面出现的 $< 和 $@ 吗?它们是Makefile中的自动变量,分别代表依赖项和目标项。下面是一些常见的自动变量及其含义:
Makefile 中常见的自动变量和含义
变量 含义
- 表示目标文件的名称,不包含目标文件的扩展名
- 表示所有的依赖文件,这些依赖文件之间以空格分开,按照出现的先后为顺序,其中可能包含重复的依赖文件
< 表示依赖项中第一个依赖文件的名称
? 依赖项中,所有目标文件时间戳晚的依赖文件,依赖文件之间以空格分开
@ 目标项中目标文件的名称
^ 依赖项中,所有不重复的依赖文件,这些文件之间以空格分开
6.设置搜索路径
在大的系统中,通常存在很多目录,手动添加目录的方法不仅十分笨拙而且容易造成错误。Make 的目录搜索功能提供了一个解决此问题的方法,指定需要搜索的目录, make 会自动找到指定文件的目录并添加到文件上, VPATH 变量可以实现此目的。VPATH 变量的使用方法如下:
VPATH = path1:path2:…
五、让make自己主动推导
GNU的make非常强大,它能够自己主动推导文件以及文件依赖关系后面的命令,于是我们就不是必需去在每一个[.o]文件后都写上相似的命令,由于,我们的make会自己主动识别,并自己推导命令。
仅仅要make看到一个[.o]文件,它就会自己主动的把[.c]文件加在依赖关系中,假设make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。而且 cc -c whatever.c 也会被推导出来,于是,我们的makefile再也不用写得这么复杂。我们的是新的makefile又出炉了。
我的收获:makefile有一个默认的编译规则。这个规则也是makefile的隐含规则。
7.自动推导规则
使用命令 make 编译扩展名为 .c 的 C 语言文件的时候,源文件的编译规则不用明确地给出。这是因为 make 进行编译的时候会使用一个默认的编译规则,按照默认规则完成对 .c 文件的编译,生成对应的 .o 文件。它执行命令 cc -c 来编译 .c 源文件。在 Makefile 中只需要给出需要重建的目标文件(一个 .o 文件),make 会自动为这个 .o 文件寻找合适的依赖文件(对应的 .c 文件),并且使用默认的命令来构建这个目标文件。
对于上边的例子,默认规则是使用命令cc -c main.c -o main.o来创建文件 main.o 。对一个目标文件是“文件名.o“,依赖文件是”文件名.c“的规则,可以省略其编译规则的命令行,由 make 命令决定如何使用编译命令和选项。此默认规则称为 make 的隐含规则。
这样,在书写 Makefile 时,就可以省略掉描述 .c 文件和 .o 依赖关系的规则,而只需要给出那些特定的规则描述(.o 目标所需要的 .h 文件)。因此上面的例子可以使用更加简单的方式书写, Makefile 文件的内容如下:
CFLAGS = -Iadd -Isub -O2
VPATH = add:sub
OBJS = add_int.o add_float.o sub_int.o sub_float.o main.o
TARGET = cacu
(
T
A
R
G
E
T
)
:
(TARGET):
(TARGET):(OBJS)
$(CC) -o $(TARGET) $(OBJS) $(CFLAGS)
clean:
-$(RM)
(
T
A
R
G
E
T
)
−
(TARGET) -
(TARGET)−(RM) $(OBJS)
我的收获:有一个主makefile,在这个主makefile中调用子makefile.
8.递归 make
对于规模比较大的程序,需要多个人在多个目录下进行开发。如果只用一个 Makefile 来维护就会比较麻烦,因此可以在每个目录下建立自己的 Makefile ,然后在总控 Makefile 中调用子目录的 Makefile 文件。
目录结构如下:
.
├── add
│ ├── add_float.c
│ ├── add.h
│ ├── add_int.c
│ └── Makefile
├── main.c
├── Makefile
└── sub
├── Makefile
├── sub_float.c
├── sub.h
└── sub_int.c