忽略点十一:make命令与Makefile文件
在讲make与Makefile之前,我们需要明白为什么它们的作用和优点是什么?
对于C/C++项目,在编译时我们需要把每个模块的代码都生成为目标文件,然后再将目标文件联编生成一个可执行文件。
编译要输入这么多命令,每次修改一点内容就要重新编译整个工程,是不是特别恶心!!!
这时候,上帝就出现了——make
命令,它可以读取当前路径下的Makefile
文件,并根据Makefile
中的规则描述把源文件生成为可执行的程序文件
注意,Makefile文件无后缀名!!
Makefile
文件中包含了一系列形式如下的规则:
目标: 依赖1 依赖2 ...
命令
例如:
a.o: a.c a.h #表示生成a.o文件需要依赖a.c与a.h
gcc -c -o a.o a.c #生成a.o的命令
注意!!!每条规则的命令前,必须有一个制表符’\t‘
这样我们想编译生成a.o文件,只需要执行make a.o
即可。(为了提高效率,该命令只有a.o不存在或者a.c与a.h中至少有一项变化时才会真正执行)
对于Makefile文件中存在多条规则:
main: a.o m.o
gcc -o main a.o m.o
m.o: m.c a.h
gcc -c -o m.o m.c
a.o: a.c a.h
gcc -c -o a.o a.c
我们想生成哪一个,就可以在make
命令后加上需要生成的目标名称。
例如:make a.o
注意!!在我们执行make main
时,make
命令发现a.o
和m.o
不存在,就会自动生成它们(没有a.o
和m.o
的规则也能生成)
为什么没有a.o和m.o规则也能生成呢?因为makefile文件默认生成.o文件格式为:$(CC) $(CFLAGS) -c -o 名.o 名.c
而CC默认值为cc,CFLAGS默认值为空(可通过修改CC和CFLAGS来修改对应的编译环境与参数(如-std -Wall等等))
执行makefile文件中的第一条规则可以在命令行中简写成make!!!
例如上边代码中执行make
相当于执行make main
可以利用makefile规则添加删除功能:
clean:
rm -f a.o m.o main //rm命令表示删除,-f表示强制
以上规则有一个Bug——就是当已经存在clean文件,rm命令就不执行了(而且执行一次make clean
就会产生clean文件,该命令最多只能执行一次)
这时我们可以通过 .PHONY
来声明clean为伪目标来解决上述问题(系统不会检查伪目标是否存在,且不会通过规则生成该目标文件)上代码:
.PHONY: clean
clean:
rm -f array.o main.o main
抛出一个较为完整的Makefile
栗子:
# 井号开头的行是一个注释
# 设置 C 语言的编译器
CC = gcc
# -g 增加调试信息
# -Wall 打开大部分警告信息
CFLAGS = -g -Wall
# 整理一下 main 依赖哪些目标文件
MAINOBJS = main.o array.o
.PHONY: clean
main: $(MAINOBJS)
$(CC) $(CFLAGS) -o main $(MAINOBJS)
#定义的变量可通过$(变量名)使用
array.o: array.c array.h
$(CC) $(CFLAGS) -c -o array.o array.c
main.o: main.c array.h
$(CC) $(CFLAGS) -c -o main.o main.c
clean:
rm -f $(MAINOBJS) main
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢!