Makefile-初探¶
1. 常用预定义变量¶
$* | 不包含扩展名的目标文件名称 |
$+ | 所有的依赖文件,以空格分开,以出现的先后为序 |
$< | 第一个依赖文件的名称 |
$? | 所有的依赖文件,以空格分开,修改日期比目标的创建日期晚 |
$@ | 目标的完整名称 |
$^ | 所有的依赖文件,以空格分开,不包含重复的依赖文件 |
$% | 如果目标是归档成员,则该变量表示目标的归档成员名称 |
2. 预备知识¶
- 链接:将多.o文件,或者.o文件喝库文件链接成为可被操作系统执行的可执行程序
- 静态库:文档文件,多个.o的文件集合;linux中后缀为.a;使用ar工具维护和管理
- 共享库:多个.o文件的集合,由编译器按照特殊方式生成,linux中通常为可执行;动态加载到内存;多个可执行程序可共享库文件的代码段
3. Makefile规则¶
- TARGET:规则的目标,最终文件名&中间过程文件名;可以是make执行的动作名称 - PREREQUISTIES:规则的依赖,生成规则目标需要的文件名列表 - COMMAND:规则的命令行;每个命令必须以[Tab]开始,但不是所有以[Tab]开头的都是命令;make会将第一条规则之哦胡的所有以[Tab]开头的行作为命令行处理4. make执行¶
- 默认执行Make file的第一个规则,此规则的第一个目标成为“最终目的”
- Makefile只会执行终极目标所需要的依赖的编译
5. 书写规则¶
(1). 尽量写为单目标、多依赖¶
(2). Makefile包含的5个内容¶
a. 显示规则¶
- 在何种情况下,如何更新一个或多个目标文件
b. 隐含规则¶
- 根据一类目标文件自动推导出来的规则,根据文件的后缀命,自动产生依赖文件并用默认命令对目标更新
c. 变量定义¶
d. 指示符¶
-
指明在make程序读取makefile文件过程中所需要执行的动作,包括:
-
读取指定文件作为makefile的一部分
-
决定处理或者忽略Makefile中的某一特定部分
-
定义一个多行变量
e. 注释¶
-
字符后的内容作为注释¶
(3). makefile文件的命名¶
- make会按照以下顺序寻找
- GNUmakfile->makefile->Makefile
- 当不是以上文件名时,可通过"-f"或者“--file”指定make读取的makefile文件;多个makefile文件会按照指定的顺序
(4). 包含其他makefile文件¶
- 使用include:
- FILENAMES是shell支持的文件名,可以使用通配符;
- 一定不能用[Tab]开头
- 找不到文件是的默认搜索路径:“. /usr/gnu/include /usr/local/include /usr/include”;make将使用规则创建通过指示符inlcude指定但未找到的文件
(5). makefile文件解析¶
- 第一阶段:读取所有的makefile文件,并简历所有目标和依赖之间的依赖关系结构链表
- 第二阶段:根据第一阶段的关系结构链表,决定那些目标需要更新,并重建
6. 变量取值¶
(1). 变量定义解析规则:¶
IMMEDIATE = DEFERRED
IMMEDIATE ?= DEFERRED
IMMEDIATE := IMMEDIATE
IMMEDIATE += DEFERRED or IMMEDIATE
Define IMMEDIATE
DEFERRED
Endef
规则中目标和依赖如果引用其他的变量,则立即被展开;而规则命令行中的变量则延后展开
7. Makefile规则语法¶
(1). 语法格式:¶
(2). TARGETS可以是空格分开的多个文件名,可以使用通配符¶
(3). A(M)表示档案文件的成员M;¶
(4). 通常目标只有一个目标文件¶
(5). 书写规则¶
- 命令可以和命令在同一行,使用“;”隔开
- 命令在依赖描述的下一行,作为独立命令行是必须以[Tab]开始
- Makefile中\(具有特殊含义(表示变量或者函数的引用),在规则中需要使用符号\),需要书写连续的$$
- 对于较长的行,可以使用\进行分行
(6). 依赖类型¶
a. 常规依赖¶
- 重建目标需要执行规则的顺序
- 按照什么顺序和命令重建依赖文件
b. order-only依赖¶
- 用于更新依赖的依赖
- 使用管道符号"|"开始,作为目标的一个依赖文件:
- 常规依赖文件可以是空;同一个依赖同时出现在常规和order-only会被当做常规的处理
(7). 文件名使用通配符¶
a. 通配符与linux shell的通配符完全相同¶
b. 使用场合¶
- 规则的目标、依赖中
- 出现在规则的命令中,是在shell中执行完成的
c. wildcard函数¶
- $(wildcard *.c)获取.c文件列表
- \((patsubst %.c,%.o,\)(wildcard *.c))--将.c文件列表换为.o
(8). 命令行和搜索目录¶
- 使用自动化变量
-
$^ 表示所有通过目录搜索得到的依赖文件的完整路径名
-
$@ 表示规则的目标
-
$< 通过目录搜索得到的依赖文件列表的第一个依赖文件
(9). 库文件和搜索目录¶
- 指定依赖文件名“-lNAME”
8. 变量¶
(1). 变量规则¶
a. 使用“=”或者“define”定义¶
b. 可用于代表:¶
- 文件名
- 编译选项
- 程序运行选项参数
- 搜索源文件的目录列表
- 编译输出目录
c. 变量名不包括:“:”、“#”、“=”¶
d. 变量名大小写敏感¶
e. 自动化变量¶
(2). 变量引用¶
- 使用“\(()”或者"\){}"
- 需要表示“\(”应用“\)$”表示
(3). 变量定义¶
- 递归展开式变量“=”定义
- 直接展开式变量“:=”定义
- 定义空格“space:=$(nullstring)”
- 条件赋值操作符:“?=”
(4). 高级用法¶
- "$(VAR:A,B)"将其中“A”字符结尾的字换成“B”;同patsubst
(5). 追加变量值¶
- “objects += another.o”
(6). override指示符¶
- “override VARIABLE = VALUE”
(7). 目标指定变量¶
9. 条件判断¶
- 关键字
-
Ifeq
-
Ifned
-
Ifdef
-
Ifndef
10. make的内联函数¶
(1). 文本处理函数¶
1. $(subst FROM,TO,TEXT)把TEXT中的FROM换成TO
2. $(patsubst PATTERN,REPLACEMENT,TEXT)搜索TEXT中空格分开的单词,将符合PATTERN的替换为REPLACEMENT
3. $(strip STRINT)去掉开头结尾空格
4. $(findstring FIND,IN)查找IN中的FIND字符串
5. $(sort LIST)将LIST中的单词按照字母顺序排序
6. $(word N,TEXT)去TEXT中的第N个单词
7. $(wordlist S,E,TEXT)从TEXT中取出S到E的单词串
8. $(words TEXT)统计TEXT中单词数目
9. $(firstword NAMES)取NAMES中的第一个单词
(2). 文件名处理函数¶
1. $(dir NAMES)取文件名目录部分
2. $(notdir NAMES)取文件名非目录部分
3. $(suffix NAMES)取文件名后缀
4. $(addsuffix SUFFIX,NAMES)为NAMES的每一项添加后缀SUFFIX
5. $(addprefix PREFIX,NAMES)为NAMES添加前缀PREFIX
6. $(join LIST1,LIST2)连接两个字串(没个列表之间对应index连接)
7. $(wildcard PATTERN)列出当前目录下符合PATTERN格式的文件名
(3). foreach函数¶
1. $(foreach VAR,LIST,TEXT)将LIST中的单词依次赋值给VAR,然后执行TEXT表达式
(4). if函数¶
1. $(if CONDITION,THEN-PART [,ELSE-PART])
(5). call函数¶
(6). value函数¶
(7). eval函数¶
(8). origin函数¶
(9). shell函数¶
(10). make的控制函数¶
1. $(error TEXT)
2. $(warning TEXT)
11. 执行make¶
(1). 直接执行make¶
(2). 指定makefile文件“make -f MAKEFILE”¶
(3). 指定终极目标¶
1. 第一个规则的第一个目标
2. 命令行指定makefile中目标名为捉急目标“make TARGET_NAME”
3. 替代命令的执行
4. 防止特定文件重建
5. 替换变量定义
6. 使用make进行编译测试:“make -k”
12. make的隐含规则¶
1. 隐含规则的使用
1. make会根据源文件类型启动相应的隐含规则
2. 隐含规则总存在一个目标模式和依赖模式;
3. 同一个目标模式可以对应多个依赖模式
2. 模式的匹配
3. 万用规则
4. 重建内嵌隐含规则
5. 缺省规则
6. 后缀规则
7. 隐含规则搜索算法
8. make自动化变量
$@ | 规则的目标文件名 |
$% | 静态库的一个成员 |
$< | 规则的第一个依赖文件名 |
$? | 所有比目标文件更新的依赖文件列表 |
$^ | 规则的所有依赖文件列表 |
$+ | 与$^类似,保留重复文件 |
$(@D) | 目标文件的目录部分 |
$(@F) | 目标文件除目录部分 |
## 13. makefile基本约定 |
- makefile中应该包含“SHELL=/bin/sh”
- 明确限定可识别的后缀
- 小心处理规则中的路径