此为牛客网Linux C++课程1.10&1.11&1.12 的课程笔记。
0. Makefile介绍
1. Makefile文件命名与规则
示例:
使用vim编写如下名为Makefile的文件:
app:sub.o add.o mult.o div.o main.o
gcc sub.o add.o mult.o div.o main.o -o app
sub.o:sub.c
gcc -c sub.c -o sub.o
add.o:add.c
gcc -c add.c -o add.o
mult.o:mult.c
gcc -c mult.c -o mult.o
div.o:div.c
gcc -c div.c -o div.o
main.o:main.c
gcc -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.c
gcc -c sub.c -o sub.o
add.o:add.c
gcc -c add.c -o add.o
mult.o:mult.c
gcc -c mult.c -o mult.o
div.o:div.c
gcc -c div.c -o div.o
main.o:main.c
gcc -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 $@
可实现与最初的示例程序相同的功能。