makefile基本语法
目标文件:依赖文件
[Tab] 命令
- 目标文件是指此规则中想要生成的文件,可以是.o结尾的目标文件,也可以是可执行文件,也可以是个伪目标
- 依赖文件是指要生成此规则的目标文件,需要哪些文件。通常依赖文件不止一个,所以此处是个依赖文件的列表
- 命令是指此规则中要执行的动作,这些动作可以是指各种shell命令。命令可以有多个,但一个命令要独占一行,行首必须以Tab开头。
make程序如何判断文件有过更新呢
- atime,即access time,表示访问文件数据时间,每次读取文件数据时就会更新atime
- ctime,即change time,表示文件属性或数据的改变时间,每当文件的属性或数据被更改时,就会更新ctime
- mtime,即modify time,表示文件数据的修改时间,每次文件的数据被修改时就会更新mtime。
make程序分别获取依赖文件和目标文件的mtime
,对比依赖文件的mtime是否比目标文件的mtime新,就知道是否执行规则中的命令。
makefile的文件也并非固定,可以在执行时用-f参数来指定,如果未指定,默认情况,make会去找名为GNUmakefile
文件,若不存在,再去找makefile
文件,也不存在,最后去找Makefile
文件。
伪目标
规则中的命令并不总是被执行,有时候我们希望make不要考虑mtime,而是总能去执行一些命令。对于这个需求,make规定,当规则中不存在依赖文件时,这个目标文件就称为——伪目标。
all:
@echo "test ok"
- 注意,伪目标不能和真实目标文件同名,为了避免为目标和真实目标同名的情况,可以用关键字
.PHONY
来修饰目标
.PHONY:clean
clean:
rm ./build/*o
伪目标名称 | 功能描述 |
---|---|
all | 通常用来完成所有模块的编译工作 |
clean | 通常用于清空编译完成的所有目标文件,一般用rm命令实现 |
dist | 通常用于将打包文件后的tar文件再压缩成gz文件 |
Install | 通常将编译好的程序复制到安装目录下,此目录是在执行configure脚本通过–prefix参数配置的 |
printf | 通常用于打印已经发生改变的文件 |
tar | 通常用于将文件打包成tar文件,也就所谓的归档文件 |
test | 通常用于测试makefile流程 |
自定义变量与系统变量
- 变量定义的格式:
变量名 = 值(字符串)
,多个值用空格分开。值仅支持字符串类型,即使是数字也被当做字符串来处理。虽然变量的值会被当做字符串来处理,但不能将其用双引号或单引号括起来, 否则双引号或单引号也会被当做变量值的一部分。 - 变量引用的格式:
$(变量名)
test2.o:test2.c
gcc -c -o test2.o test2.c
test1.o:test1.c
gcc -c -o test1.o test1.c
objfiles = test1.o test2.o
test.bin:$(objfiles)
gcc -o test.bin $(objfiles)
all:test.bin
@echo "compile done"
变量名 | 描述 |
---|---|
AR | 打包程序,默认是“ar” |
AS | 汇编语言编译器,默认是“as” |
CC | C 语言编译器,默认是“cc” |
CXX | C++语言编译器,默认是“g++” |
CPP | C 预处理器,默认是“$(CC) –E”,如 gcc -E |
FC | Fortran 的编译器和预处理器,Ratfor 的编译器,默认是“f77” |
GET | 从 SCCS 文件中提取文件程序,默认是“get” |
PC | Pascal 语言编译器,默认是“pc” |
MAKEINFO | 将 texinfo 文件转换为 info 文件,默认是“makeinfo” |
RM | 删除命令,默认是“rm -f” |
TEX | 从 TeX 源文件中创建 TexDVI 文件的程序,默认是“tex” |
WEAVE | 将 Web 转换为 TeX 的程序,默认是“weave” |
YACC | 处理 C 程序的 Yacc 词法分析器,默认是“yacc” |
YACCR | 处理 Ratfor 程序的 Yacc 词法分析器,默认是“yacc -r” |
变量名 | 描述 |
---|---|
ARFLAGS | 打包程序$(AR) 的参数,默认值为 rv |
ASFLAGS | 汇编语言编译器参数 |
CFLAGS | C 语言编译器参数 |
CXXFLAGS | C++编译器参数 |
CPPFLAGS | C 预处理器参数 |
FFLAGS | Fortran 语言编译器参数 |
LDFLAGS | 链接器参数 |
PFLAGS | Pascal 语言编译器参数 |
YFLAGS | Yacc 词法分析器参数 |
隐含规则
- 什么事隐含规则?对于一些使用频率非常高的规则,make把它们当成是默认的,不需要显式地写出来,当用户未在makefile中显式定义规则时,将默认使用隐含规则进行推导。
在编写规则时,若一行写不下,可以在行尾添加反斜杠字符\
,下一行内容也被认为是同一行。用#
来单行注释。
常见的语言程序的隐含规则:
-
c程序:
“x.o”的生成依赖于“x.c”,生成 x.o 的命令为:
$(CC) -c $(CPPFLAGS) $(CFLAGS)
-
C++程序:
“x.o”的生成依赖于“x.cc”或者“x.C”,生成 x.o 的命令为:
“$(CXX) -c $(CPPFLAGS) $(CFLAGS)”
-
Pascal 程序
“x.o”的生成依赖于“x.p”,生成 x.o 的命令为:
“$(PC) -c $(PFLAGS)”
自动化变量
make 还支持一种自动化变量,此变量代表一组文件名,无论是目标文件名,还是依赖文件名,此变量值的范围属于这组文件名集合,也就是说,自动化变量相当于对文件名集合循环遍历一遍。对于不同的文件名集合,有不同的自动化变量名。
- $@,表示规则中的目标文件名集合
- $<,表示规则中依赖文件中的第 1 个文件
- $^,表示规则中所有依赖文件的集合,如果集合中有重复的文件,$^会自动去重。
- $?,表示规则中,所有比目标文件 mtime 新的依赖文件集合。
模式规则
模式,即 pattern,其实就是指字符串模(mú,二声)子,正则表达式中用此概念表示字符或字符串匹配,把符合此模子的字符串找出来,make 中也支持这种字符串匹配用法
-
%用来匹配任意多个非空字符。比如%.o 代表所有以.o 为结尾的文件,g%s.o 是以字符 g 开头的所有以.o为结尾的文件,make 会拿这个字符串模式去文件系统上查找文件,默认为当前路径下。
-
%通常用在规则中的目标文件中,以用来匹配所有目标文件,%也可以用在规则中的依赖文件中,因为目标文件才是要生成的文件,所以当%用在依赖文件中时,其所匹配的文件名要以目标文件为准。拿%.o:%.c 为例,假如用%.o 匹配到了目标文件 a.o 和 b.o,那么依赖文件中的%.c 将分别匹配到 a.c 和 b.c