一、概述
1、make:是一个非常重要的编译命令,本质上它是一个程序。利用make工具,可以将大型的开发项目分解成为多个更易于管理的模块,对于一个包括几百个源文件的应用程序,使用make和makefile工具就可以简洁明快地理顺各个源文件之间纷繁复杂的相互关系。而且如此多的源文件,如果每次都要键入gcc命令进行编译的话,那对程序员来说简直就是一场灾难。而make工具则可自动完成编译工作,并且可以只对程序员在上次编译后修改过的部分进行编译。
2、Makefile文件 :Make工具最主要也是最基本的功能就是通过makefile文件来描述源程序之间的相互关系并自动维护编译工作,本质上makefile文件是个文本文件,用于配置编译过程。makefile 文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。makefile 文件是许多编译器--包括 Windows NT 下的编译器--维护编译信息的常用方法,只是在集成开发环境中,用户通过友好的界面修改 makefile 文件而已。
3、在UNIX系统中,习惯使用 Makefile 作为 makfile 文件。
二、makefile中的规则
gcc a.c b.c c.c -o app
三部分:目标,依赖,命令
目标:依赖
(tab缩进)命令
app:a.c b.c c.c
gcc a.c b.c c.c -o app
三、makefile中的变量
自定义变量:
obj=a.o b.o c.o
obj=10
变量的取值:
aa=$(obj)
makefile自带的变量:大写(有些自带变量已赋值,有的则没赋值,故最好自行赋值)
CPPFLAGS
CC
自动变量:
$@:表示规则中的目标
$<:表示规则中的第一个依赖 例如,app:main.o add.o sub.o mul.o中的main.o
$^:表示规则中的所有依赖 例如,app:main.o add.o sub.o mul.o中的main.o add.o sub.o mul.o
注意:只能在规则的命令中使用
四、简易版本
src = $(wildcard ./*.c)
obj = $(patsubst %.c,%.o,$(src))
target = app
$(target):$(obj)
gcc $^ -o $@
%.o:%.c
gcc -c $< -o $@
.PHONY:clean
-rm $(obj) $(target) -f
makefile所有函数都有返回值
查找指定目录下的指定类型的文件
src=$(wildcard ./*.c)----查找当前目录下的所有.c文件,并赋值给src
匹配替换:(在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o)
obj=$(patsubst %.c,%.o,$(src))
声明伪目标:
.PHONY:clean
目的是为了避免当前目录下有一个同名的clean文件,而不能执行make clean。根据makefile第二个版本中的说法,当前目录下有名为clean的文件,即依赖存在,所以判断是否需要更新,右因为目标:依赖中只有目标而没有依赖,所以目标的最新修改时间>依赖的最新修改时间,故不更新,导致make clean无法执行。
五、Makefile中:=, =, ?=和+=的含义
在Makefile语法中,时不时会见到各种“=”号的赋值语句,除了常见的“=”和“:=”,还有“?=”等
那么这些赋值等号分别表示什么含义呢?
1. “=”
“=”是最普通的等号,然而在Makefile中确实最容易搞错的赋值等号,使用”=”进行赋值,变量的值是整个makefile中最后被指定的值。不太容易理解,举个例子如下:
VIR_A = A
VIR_B = $(VIR_A) B
VIR_A = AA
经过上面的赋值后,最后VIR_B的值是AA B,而不是A B。在make时,会把整个makefile展开,拉通决定变量的值
2. “:=”
相比于前面“最普通”的”=”,”:=”就容易理解多了。”:=”就表示直接赋值,赋予当前位置的值。同样举个例子说明
VIR_A := A
VIR_B := $(VIR_A) B
VIR_A := AA
最后变量VIR_B的值是A B,即根据当前位置进行赋值。因此相比于”=”,”:=”才是真正意义上的直接赋值。
3. “?=”
“?=”表示如果该变量没有被赋值,则赋予等号后的值。举例:
VIR ?= new_value
如果VIR在之前没有被赋值,那么VIR的值就为new_value.
VIR := old_value
VIR ?= new_value
这种情况下,VIR的值就是old_value
4. “+=”
“+=”和平时写代码的理解是一样的,表示将等号后面的值添加到前面的变量上