一、Mekefile文件的命名
系统默认可以自动识别的 Makefile 文件名有三个 分别如下:
①Gunmakefile ②makefile ③Makefile
如果三者有两者或两者以上存在在同一目录下,在执行 make 时优先级是 ①>②>③
也可以自定义文件名为 makefile,此时在 make 时需要加 "-f 文件名"
如果要执行指定目录下的 makefile 文件,使用 "-C 目录" 选项
-f 和 -C 选项可以同时使用
二、Makefile 的书写规则
目标对象:依赖对象
[<tab>命令1]
.....
何为目标,何为依赖?
gcc hello.o -o hello
#可以看到此时 hello 的可执行文件的生成需要依赖 hello.o,不难看出 hello为目标
#hello.o为依赖
目标和依赖也能自己去构建
目标和依赖都可以包含多项,项与项之间用空格分隔
三、Makefile 的执行顺序
规则的顺序不太重要,make 会自动依据依赖关系查找规则执行
但入口规则(即第一个规则)是默认首先执行的规则,
除非在执行 make 时指定了目标,否则就会先执行入口规则
指定目标如:
make clean #执行clean指令
也可以同时指定多个目标编译如:
make clean install ....#目标间用空格隔开
四、伪目标
伪目标是指并不是为了创建那个目标的目标,而是为了执行一些命令。
常见的伪目标有 all, install, uninstall, clean 等。
这些伪目标的规则代码由用户自行定义。
但是伪目标有时会与文件系统中的文件名同名,这会造成那个规则不被执行,
为了解决这个问题,可以使用 .PHONY 声明这个伪目标。
声明伪目标
.PHONY: all clean install uninstall
五、命令行的特殊用法
1.命令行前加 @ 表示,执行命令时不显示命令行,直接显示命令行结果
如下可以简单的测试一下 @ 符号的效果
all:test
test:
echo "abc" # @echo "abc"
===========
2.命令行前加 - 表示如果命令出错不中止 makefile 的执行
如下可以简单的测试一下 - 符号的效果
all:test
test:
123
# -123
@echo "abc"
- 和 @ 也可以组合使用,顺序无关
六、makefile 中的变量
makefile 中的变量有 :自定义变量,预定义变量,自动变量
分别类似于 shell 中的:自定义变量,环境变量 ,系统变量
1.自定义变量方式:
1. 1递归展开方式
VAR = value
value 中的变量会递归展开,特别是如果 value 中又包含 VAR 时,会造成无穷循环展开,最终展开失败
1. 2 简单扩展方式
VAR := value
value 中的变量会展开一次,如果 value 中又包含 VAR 时,则只会展开一次,不会无穷展开
变量赋值时 = 号两边可以加空格,也可以不加空格
1. 3 变量为空时赋值
VAR ?= value
VAR 的值为空才赋值 value
1. 4 追加赋值
VAR += value
在 VAR 原值的基础上追加 value 值,不是算术累加运算
2.预定义变量
常见的预定义变量,有的有默认值,有的没有:
AR 归档维护程序的名称,默认值为 ar。
ARFLAGS 归档维护程序的选项,默认值 rv。
CC C 编译器的名称,默认值为 cc。
CFLAGS C 编译器的选项,无默认值。
LDFLAGS C 链接器的选项,无默认值。
RM 文件删除程序名称,默认值为 rm –f。
CXX C++ 编译器的名称,默认值为 g++。
CXXFLAGS C++ 编译器的选项,无默认值。
可以重新定义预定义变量,即将其变为自定义变量。
对预定义变量重新赋值,覆盖其原有的值
使用 export 可以将新值导出为全局预定义变量,则其可被调用的其他子 makefile使用,否则新值只在本 Makefile 中有效。
父子 Makefile 不是指目录的层次关系,而是调用的关系,a.mk 调用 b.mk,则 a.mk 是 b.mk 的父 Makefile
3.自动变量
对每一条 Makefile 规则,make 维护了一些自动变量:
$< #第一个依赖文件的名称。
$@ #目标的完整名称。
$^ #所有的依赖文件,以空格分开,不包含重复的依赖文件。
$* #不包含扩展名的目标文件名称。
$+ #所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
$? #所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚。
$% #如果目标是归档成员,则该变量表示目标的归档成员名称。
# 例如,如果目标名称为 mytarget.so(image.o),
# 则 $@ 为 mytarget.so,而 $% 为 image.o。
七、变量名替换
变量替换,可以使用 $() 也可以使用 ${}
以 o 结尾的替换为 c 结尾,得到新值,不改变 OBJS 的原值
SRCS = $(OBJS:o=c) # 形式 1
SRCS = $(OBJS:.o=.c) # 形式 2
SRCS = $(OBJS:%.o=%.c) # 形式 3,% 通配符,通配任意字符