此为牛客网Linux C++课程1.10&1.11&1.12 的课程笔记。
0. Makefile介绍
1. Makefile文件命名与规则
示例:
使用vim编写如下名为Makefile的文件:
app:sub.o add.o mult.o div.o main.ogcc sub.o add.o mult.o div.o main.o -o appsub.o:sub.cgcc -c sub.c -o sub.oadd.o:add.cgcc -c add.c -o add.omult.o:mult.cgcc -c mult.c -o mult.odiv.o:div.cgcc -c div.c -o div.omain.o:main.cgcc -c main.c -o main.o
首先看第一行,app是我们的目标文件,冒号后面是生成该目标文件所需要的依赖,第二行是我们要执行的命令。
在使用sub.o add.o mult.o div.o main.o依赖时,发现目录中没有对应的.o文件,则向下寻找其他规则,执行以生成其依赖。注意,如果下面的规则中与第一行所需的依赖无关,则不会被执行,也就是说Makefile中的其他规则都是为第一条规则服务的。
2. 变量
有了变量我们写makefile就方便一些,比如我们之前的makefile就可以如此改写:
src = sub.o add.o mult.o div.o main.o
target = app$(target):$(src)$(CC) $^ -o $(target)sub.o:sub.cgcc -c sub.c -o sub.oadd.o:add.cgcc -c add.c -o add.omult.o:mult.cgcc -c mult.c -o mult.odiv.o:div.cgcc -c div.c -o div.omain.o:main.cgcc -c main.c -o main.o
把所有的依赖定义为src变量,把目标文件名定义为target变量,然后用 $ 取值,其中 $ (CC)是预定义变量,表示C编译器名称;$^ 也是预定义变量,表示所有的依赖文件。
3. 模式匹配
原先是按左边的方式写的,一个个写很麻烦,这里可以使用模式匹配,即通配符%,在同一规则中,%匹配同一个字符串。
如此以来,之前的makefile可如此改写:
src = sub.o add.o mult.o div.o main.o
target = app$(target):$(src)$(CC) $^ -o $(target)%.o:%.c$(CC) -c $< -o $@
src中的每一个依赖都可以匹配下面的这条规则。
4. 函数
现在通过模式匹配,避免了我们反复写规则,但是依赖文件我们还是要一个一个写在src里,有没有办法直接获取这些文件的文件名呢?可以使用$(wildcard PATTERN…)函数。
举例,当前目录如下:
假如我们想让在makefile文件中获得当前目录中所有.c文件的名称,即可执行:
src = $ (wildcard ./*.c )
这样就能获得当前目录下所有.c文件的名称。
但是之前的示例代码中需要的是与.c文件同名的.o文件,而目录中没有.o文件,我们可以使用$(patsubst < pattern>,< replacement>,< text>)函数:
我们现在想要在makefile中获得与目录中.c文件同名的.o文件,便调用patsubst函数把获得的.c文件进行字符串替换即可.
该函数的作用简而言之就是把< text >中的匹配< pattern >的串用< replacement >代替。
其中< text >字段由刚才调用的src = $ (wildcard ./*.c )获得,然后我们想将其中所有的.c都替换成.o,可将原来的makefile文件修改如下:
src = $(wildcard ./*.c)
objs = $(patsubst %.c, %.o, $(src))
target = app$(target):$(objs)$(CC) $^ -o $(target)%.o:%.c$(CC) -c $< -o $@
可实现与最初的示例程序相同的功能。