Makefile
Makefile实现项目自动化构建
核心概念
为了提高项目的开发效率,所以GNU组织就在Linux系统中集成了Make工具,而Makefile就属于Make工具的一部分。
Makefile是自动化构建脚本,配合make指令使用,解决多文件编译繁琐问题,核心功能:编译源码、链接可执行文件、清理中间文件。
执行方式
安装:sudo apt install make
执行:输入make指令时,会执行当前目录下的Makefile
make是一个shell命令,执行时依次查找GNUmakefile makefile Makefile
基本规则
|
|
目标是需要生成的程序的名称,可能一开始不存在
先决条件也是文件,用于生成目标用的
一个目标可能依赖多个文件,则每个文件中间使用空格
只有需要执行的命令前可以存在Tab制表符,而且必须使用
伪目标
|
|
伪目标,没有先决条件
一个Makefile文件中,不可以只有伪目标
make的流程
先发现最终目标
准备执行动作时发现目标依赖文件不存在,则会在makefile文件寻找生成该依赖文件的规则。
如果找到则继续执行,如果未找到,则报错,所以可以理解为make会递归在Makefile文件中进行规则执行
variable变量
|
|
调用时$(变量名)
进行赋值时,等号两边有空格
系统内置变量
|
|
自动化变量
|
|
变种变量
在自动化变量后加入“D”或者“F”字符
D:路径
F:文件
用于快速获取文件目录/文件名
| 变量名 | 含义 | 备注 |
|---|---|---|
| @D | 代表目标文件的目录部分(去掉目录部分的最后一个斜杠) | 如果“$@”是“dir/foo.o”,那么“$(@D)”的值为“dir”。如果“$@”不存在斜杠,其值就是“.”(当前目录)。注意它和函数“dir”的区别 |
| @F | 目标文件的完整文件名中除目录以外的部分(实际文件名) | 如果“$@”为“dir/foo.o”,那么“$(@F)”只就是“foo.o”。“$(@F)”等价于函数“$(notdir $@)” |
| *D | 代表目标茎中的目录部分 | |
| *F | 代表目标茎中的文件名部分 | |
| %D | 当以如“archive(member)”形式静态库为目标时,表示库文件成员“member”名中的目录部分 | 仅对“archive(member)”形式的规则目标有效 |
| %F | 当以如“archive(member)”形式静态库为目标时,表示库文件成员“member”名中的文件名部分 | 仅对“archive(member)”形式的规则目标有效 |
| <D | 代表规则中第一个依赖文件的目录部分 | |
| <F | 代表规则中第一个依赖文件的文件名部分 | |
| ^D | 代表所有依赖文件的目录部分 | 同一文件不可重复 |
| ^F | 代表所有依赖文件的文件名部分 | 同一文件不可重复 |
| +D | 代表所有依赖文件的目录部分 | 同一文件可重复 |
| +F | 代表所有依赖文件的文件名部分 | 同一文件可重复 |
| ?D | 代表被更新的依赖文件的目录部分。 | |
| ?F | 代表被更新的依赖文件的文件名部分。 |
静态规则
工作原理是:$(OBJ)被称为原始列表,即(a.o b.o x.o y.o),紧跟在其后的%.o被称为匹配模式,含义是在原始列表中按照这种指定的模式挑选出能匹配得上的单词(在本例中要找出原始列表里所有以.o为后缀的文件)作为规则的目标。
|
|
本例中%.o:%.c的意思就是:每一个匹配出来的目标所对应的依赖文件是同名的.c文件
%可以理解为通配符
积累
ifdef用于判断一个变量是否被定义
+=追加赋值,向已有变量的末尾追加内容,追加时会自动在原有内容和新内容之间加空格
:=简单展开赋值(立即展开),赋值时立即展开右侧内容,将结果存入变量
?=条件赋值,仅当变量未被定义/为空时,才执行赋值。若变量已有值,则赋值语句无效
LDFLAGS给链接器传递参数的环境/自定义变量,先搜索自定义的路径,再搜索默认路径
|
|
$(wildcard *.c)获取工作目录下所有的.c文件
使用wildcard函数可以使通配符生效
patsubst %.c,%.o将所有的.c文件替换为.o