http://c.biancheng.net/makefile/
1.makefile文件是什么
Makefile 文件描述了 Linux 系统下 C/C++ 工程的编译规则,它用来自动化编译 C/C++ 项目。 编写好makefile文件后,编译时执行make命令就可以编译整个工程。Makefile文件定义了一系列规则,指明了源文件的编译顺序、依赖关系、是否需要重新编译等。Makefile支持多线程并发操作,会极大的缩短我们的编译时间,并且当我们修改了源文件之后,编译整个工程的时候,make 命令只会编译我们修改过的文件,没有修改的文件不用重新编译,也极大的解决了我们耗费时间的问题。在编写makefile的时候,可以使用的名称有”GNUmakefile“,”Makefile“,”makefile“,推荐使用Makefile作为文件名,较为规范。
2.makefile文件中包含的规则
- makefile文件的结构
targets:prerequisites
command
# 或者
targets:prerequisites;command
command
上述结构说明如下:
- targets:规则的目标,可以是 Object File(一般称它为中间文件),也可以是可执行文件,还可以是一个标签;
- prerequisites:是我们的依赖文件,要生成 targets 需要的文件或者是目标。可以是多个,也可以是没有;
- command:make 需要执行的命令(任意的 shell 命令)。可以有多条命令,每一条命令占一行。
举例如下:
app:main.c
gcc -o app main.c
- makefile文件主要包含的五个主要部分
1) 显式规则
显式规则说明了,如何生成一个或多个目标文件。这是由 Makefile 的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。
2) 隐晦规则
由于我们的 make 命名有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写 Makefile,这是由 make 命令所支持的。
3) 变量的定义
在 Makefile 中我们要定义一系列的变量,变量一般都是字符串,这个有点像C语言中的宏,当 Makefile 被执行时,其中的变量都会被扩展到相应的引用位置上。
4) 文件指示
其包括了三个部分,一个是在一个 Makefile 中引用另一个 Makefile,就像C语言中的 include 一样;另一个是指根据某些情况指定 Makefile 中的有效部分,就像C语言中的预编译 #if 一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。
5) 注释
Makefile 中只有行注释,和 UNIX 的 Shell 脚本一样,其注释是用“#”字符,这个就像 C/C++ 中的“//”一样。如果你要在你的 Makefile 中使用“#”字符,可以用反斜框进行转义,如:“\#”。
3.makefile的工作流程
makefile文件中的第一个目标是终极目标,即要生成的最终文件。一个makefile示例如下:
main:main.o test1.o test2.o
gcc main.o test1.o test2.o -o main
main.o:main.c test.h
gcc -c main.c -o main.o
test1.o:test1.c test.h
gcc -c test1.c -o test1.o
test2.o:test2.c test.h
gcc -c test2.c -o test2.o
清除工作目录下的过程文件:
在Makefile文件中新增伪目标:
# 定义伪目标,防止当前makefile文件所在目录下有与此目标名相同的文件造成歧义
.PHONY:clean
clean:
@rm -rf *.o
@rm -rf result
# @的作用是:再次使用make命令编译的时候不输出没有必要的结果。
4.Makefile中的通配符
- *:匹配零个或者任意多个字符
- ?:匹配任意一个字符
- []:可以将指定匹配的字符放在[]中
test:*.c
gcc -o test *.c
5.Makefile中的变量
- 定义变量的基本语法
变量名 = 值列表
- 变量的使用
# 定义一个变量
var = main.c
# 变量的使用
$(var) 或者${var}
var = main.c
result:${var}
gcc -o result main.c
- Makefile中的四种变量的赋值方式
1.简单赋值::=
x:=foo
y:=$(x)b
x:=new
test:
@echo "y=>$(y)"
@echo "x=>$(x)"
# shell命令行中执行make test输出如下结果
#y=>foob
#x=>new
2.递归赋值
x=foo
y=$(x)b
x=new
test:
@echo "y=>$(y)"
@echo "x=>$(x)"
3.条件赋值:?=,如果变量未定义,则使用符号中的值定义变量。如果该变量已经赋值,则该赋值语句无效。
4.追加赋值:+=,原变量用空格隔开的方式追加一个新值。