makefile文件编写教程
技术交流QQ群:1027579432,欢迎你的加入!
1.make介绍
- gcc:编译器(gcc根据菜谱进行编译)
- make: linux自带的构建器(相当于一个菜谱)
- 构建的规则(菜谱)在makefile中
2.makefile文件的命名
- makefile
- Makefile
3.makefile中的规则
- gcc a.c b.c c.c -o app这种方法在文件很多情况下,利用gcc编译时会有很多参数,不利于整个项目的管理。因此,需要编写makefile文件,便于整个项目的编译。
- makefile中的规则组成:目标,依赖,命令,具体格式如下:
目标:依赖 (tab缩进) 命令
- 将gcc a.c b.c c.c -o app修改为make进行编译。于是,makefile中的规则如下所示:
app:a.c b.c c.c gcc a.c b.c c.c -o app
- makefile中由一条或多条规则组成!
4.makefile的编写
具体实例如下所示,第一个版本:
// gcc编译 cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ ls add.c head.h main.c mul.c sub.c cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ gcc add.c main.c sub.c -o app cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ ./app sum=36 cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ rm app // make编译 cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ vim makefile cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ cat makefile app:add.c main.c sub.c gcc add.c main.c sub.c -o app cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ ls add.c head.h main.c makefile mul.c sub.c cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ make gcc add.c main.c sub.c -o app cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ ./app sum=36
第一个版本的缺点:编译步骤花费时间很长,效率低,修改其中一个文件,所有文件会被重新编译。
具体实例如下所示,第二个版本:
cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ vim makefile cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ cat makefile app:add.o main.o sub.o gcc add.o main.o sub.o -o app add.o:add.c gcc add.c -c main.o:main.c gcc main.c -c sub.o:sub.c gcc sub.c -c cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ rm app cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ make gcc add.c -c gcc main.c -c gcc sub.c -c gcc add.o main.o sub.o -o app cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ ./app sum=36 cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ vim add.c # 仅对add.c文件增加一个空行! cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ make gcc add.c -c gcc add.o main.o sub.o -o app
makefile工作原理:
- 检测依赖(如第二个版本中的add.o main.o sub.o)是否存在:
- 向下搜索下面的规则(如第二个版本中的add.o:add.c gcc add.c -c),如果有规则是用来生成查找的依赖(如第二个版本中的add.o main.o sub.o)的,执行规则中的命令;
- 依赖存在,判断是否需要更新:
- 原则:目标的时间 > 依赖的时间。反之,则更新。(如第二个版本中vim add.c,仅对add.c文件增加一个空行!make时只对add.c进行编译)
- 检测依赖(如第二个版本中的add.o main.o sub.o)是否存在:
第二个版本的缺点:makefile文件中有很多内容是冗余的。
具体实例如下所示,第三个版本:
自定义变量:obj=a.o b.o c.0
- 变量的取值:aa=$(obj)
makefile自带的变量:大写
- CPPFLAGS
- CC
自动变量:自动变量只能在规则的命令中使用!
- $@:规则中的目标
- $<:规则中的第一个依赖
- $^:规则中所有的依赖
dl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ vim makefile cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ cat makefile obj = add.o main.o sub.o target = app $(target):$(obj) gcc $(obj) -o $(target) # 也可以使用自动变量 gcc $^ -o $@
%.o:%.c
gcc -c @
cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile make
cc -c -o add.o add.c
cc -c -o main.o main.c
cc -c -o sub.o sub.c
gcc add.o main.o sub.o -o app
```
模式匹配:%.o:%.c
- 第一次:add.o没有
add.o:add.c gcc -c add.c -o add.o
- 第二次:main.o没有
main.o:main.c gcc -c main.c -o main.o
- 第一次:add.o没有
5.makefile中的函数
第三个版本的缺点:可移植性比较差。
具体实例如下所示,第四个版本:
makefile中的所有函数都是有返回值
wildcard查找指定目录下的指定类型的文件(如 ./.c):src = $(wildcard ./.c)
匹配替换:obj = (src))
cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ vim makefile cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ cat makefile src = $(wildcard ./*.c) obj = $(patsubst %..c, %..o, $(src)) target = app $(target):$(obj) gcc $^ -o $@ %..o:%..c gcc -c $< -o $@ cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ make gcc mul.c main.c add.c sub.c -o app cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ ./app sum=36
6.makefile中添加项目清理功能
第四个版本的缺点:不能清理项目。
具体实例如下所示,第五个版本:
让make生成不是终极目标的目标:make 目标名
编写一个清理项目的规则:
clean: rm *.o app
声明伪目标:
.PHONY:clean
-f:强制执行
命令前加-:忽略执行失败的命令,继续向下执行其余的命令;
cdl@cdl-Inspiron-5421:~/Cpp_Tutorials/Makefile$ cat makefile src = $(wildcard ./*.c) obj = $(patsubst %..c, %..o, $(src)) target = app $(target):$(obj) gcc $^ -o $@ %..o:%..c gcc -c $< -o $@ .PHONY:clean clean: -mkdir /abc -rm $(obj) $(target) -f