参考:
https://github.com/seisman/how-to-write-makefile
https://segmentfault.com/a/1190000012091117
作用: 项目代码编译管理、节省编译项目的时间
命名规则: Makefile、makefile、GNUmakefile
基本规则: Makefile会把规则中的第一个目标作为最终目标
target(目标文件):prerequisites(生成target的依赖文件)
(tab)命令 # Makefile 规则内容里所有的shell命令都要以制表符Tab开头,注意,空格符是不行的
工作原理:
①. 若想生成目标,会检查规则中的依赖条件是否存在,如果不存在,寻找是否有规则用来生成该依赖文件;
②. 检查规则中的目标是否需要更新,必须检查它的所有依赖,依赖中有任意一个被更新,则目标必须更新(依赖文件比目标文件时间晚,则需要更新);
执行:
make
:通过makefile生成目标文件- 直接 make (使用makefile文件)
make -f mm
(指定一个名字不为makefile的文件)
make clean
:清除编译生成的中间.o文件和最终目标文件。
如果当前目录下有同名clean文件,则不执行clean对应的命令;
解决方案:伪目标声明(作用:无视目标是否存在,必然执行 );
# 场景1:make clean
PHONY:clean
claen:
-rm *.o 目标文件 # - 表示此条命令即使出错,make也会继续执行后续的命令
# 2. 一个 make 动作,实际上生成了多个目标
.PHONY: all
all: exe install # 包含了生成目标文件,以及安装动作
注释:
Makefile 里面只有行注释、没有段注释。注释采用 #
开头。如果要使用 #
字符,则需要转义,写成 “\#
”。
变量:
其变量定义的基本语法:
# 注意变量的值是允许空格的
obj = main.o test.o \
test1.o test2.o
GCC = gcc
test : $(obj)
$(GCC) -o $(OBJ)
- 普通变量:
- 变量定义及赋值:
obj = main.o test.o test1.o test2.o
- 变量取值:
foo = $(obj)
- 变量定义及赋值:
- 由 Makefile 维护的一些变量:通常格式都是大写,有些有默认值,有些没有,用户可以修改这些变量的默认值;例如
CC
CPPFLAGS
: 预处理器需要的选项 如:-ICFLAGS
:编译的时候使用的参数 –Wall –g -cLDFLAGS
:链接库使用的选项 –L -l
- 自动变量:
-
$@ : 规则中的目标
-
$< : 规则中的第一个依赖条件
-
$^ : 规则中的所有依赖条件
-
%.o:%.c
$(CC) –c $< -o $@
函数:
makefile中所有的函数必须都有返回值
wildcard:查找指定目录下指定类型的文件,一个参数
# 找到./src 目录下所有后缀为.c的文件,赋给变量src
src = $(wildcard ./src/*.c)
patsubst:匹配替换,从src中找到所有.c 结尾的文件,并将其替换为.o
# 把src变量中所有后缀为.c的文件替换成.o
obj = $(patsubst %.c ,%.o ,$(src))
# 指定.o 文件存放的路径 ./obj/%.o
ob = $(patsubst ./src/%.c, ./obj/%.o, $(src))
引用Makefile:
语法:
include filename ... # 不允许 include 失败
-include filename ... # 允许 include 失败
如果未指定绝对路径或者相对路径,那么 make 会按照以下顺序寻找:
- 当前目录
- 制定 make 时,在 -I 或者 --include-dir 的参数下寻找
<prefix>/include
(一般是/usr/local/bin
或/usr/include
)