- Makefile基本语法
Makefile基本语法:
目标:依赖
Tab 命令 #注意:一定是要“Tab键”,空格不行
- 通配符
什么是通配符?学过其他编程语言的可能只要什么叫通配符,通配符是一种特殊语句,主要有星号(*)和问号(?),用来模糊搜索文件。当查找文件夹时,可以使用它来代替一个或多个真正字符。
Makefile常见通配符:
%.o或%.c : 该通配符表示任意的.o文件或者.c文件
$@ : 表示目标
$< : 表示第一个依赖文件
$^ : 表示所有依赖文件
目标:一般指的是待编译的目标,也可以是一个动作
依赖:执行当前目标所要依赖的前提条件,包括其他目标、某个具体文件或库(一个目标可以有多个依赖)
命令:达到该目标需要执行的具体命令,可以为空;也可有多条,多条时,每条命令单独一行
- make常用选项
首先,了解一下make命令的基本用法
make [-f file] [options] [target]
执行make命令,默认在当前目录中寻找GUNmakefile、makefile文件,作为make命令的输入文件
- -f 可指定上述文件名之外的文件作为输入文件
- -v 显示版本号
- -n 只输出命令,但并不执行,一般用于调试或测试
- -s 只执行命令,但不显示具体命令,此处可在命令中用@符号抑制命令输出
- -w 显示执行前、后的路径
- -C [dir] 指定makefile的目录
没有指定目标时,默认使用第一目标
如果指定,则执行对应的命令
常见的make命令:
make 按默认配置編译
make -j8 8个进程同时编译,缩短总的时间
make world 编译所有能够编译的(postgresql 经常同时編译文档及附加模块(contrib)
make check 回归测试,用于安装完成后测试功能完整性,不能以 root 身份运行
make install 安装程序
make install-docs 安装文档(info、man手册)
make install-world 安装所有可安装的
make uninstall 删除安装的文件(生成的目录无法删除)
make clean 清除 make 生成的文件,但保留 configure 生成的文件
make distclean 将源码恢复为原始状态,即同时删除 make 与 configure 阶段生成的文件
make -C 指定源文件目录,仅安装程序的特定部分;
如只安装客户端应用和接口:
make -C src/bin install;
make -C src/include install;
make -C src/interfaces install;
make -C doc install
- Makefile变量的引用与赋值
1.自定义变量
Makefile文件中的几种赋值与引用方式:=、:= 、?=、+=,赋值操作一般是针对变量的,Makefile中的变量可以任意命名,原则上尽量见名知意。
(1)= 递归式变量赋值(可以理解为是C语言里的传址),左侧为变量名,右侧为变量的值,优点是变量可以重复多次赋值
xxx@XXX:~/test$ cat Makefile
var1=1
var2=$(var1)
var2=2
print:
echo $(var2)
xxx@XXX:~$ make
echo 2
2
(2):= 展开式变量赋值(可以理解为是C语言里的传值),定义变量时,变量右侧的值立即替换到变量值中,前面的变量不能使用后面的变量,即变量一旦赋值,即使后面再次赋值,也不会覆盖前面定义的变量值
xxx@XXX:~/test$ cat Makefile
var1=012
var2:=$(var1)
var1=345
print:
echo $(var2)
xxx@XXX:~/test$ make
echo 012
012
(3)?= 条件赋值,用于判断左边的变量是否被赋值过,如果是,不会执行此次赋值操作;如果不是,则给该变量赋值:
xxx@XXX:~/test$ cat Makefile
var1=012
var2=$(var1)
var2 ?=345
print:
echo $(var2)
xxx@XXX:~/test$ make
echo 012
012
(4)+= 一般用于新增目标文件编译操作,例如:
#新增目标前
objs=main.o add.o
main=$(objs)
#此时需要新增一个sub.o文件
objs=main.o add.o
objs+=sub.o
main=$(objs)
2.系统变量(自动变量)
自动变量名 | 解释说明 |
$@ | 表示规则的目标文件名。如果目标是一个文档文件(Linux 中,一般成 .a 文件为文档文件,也称为静态的库文件),那么它代表这个文档的文件名;在多目标模式规则中,它代表的是触发规则被执行的文件名 |
$% | 当目标文件是一个静态库文件时,代表静态库的一个成员名;如果目标文件不是静态库文件,其值为空 |
$< | 规则的第一个依赖的文件名。如果是一个目标文件使用隐含的规则来重建,则它代表由隐含规则加入的第一个依赖文件。 |
$? | 所有比目标文件更新的依赖文件列表,空格分隔。如果目标文件时静态库文件,代表的是库文件(.o 文件)。 |
$^ | 代表的是所有依赖文件列表,使用空格分隔。如果目标是静态库文件,它所代表的只能是所有的库成员(.o 文件)名。一个文件可重复的出现在目标的依赖中变量,只记录它的第一次引用的情况。就是说变量“^”会去掉重复的依赖文件。 |
$+ | 类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库的交叉引用场合。 |
$* | 在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“%”所代表的部分(当文件名中存在目录时,“茎”也包含目录部分)。 |
2.系统常量(内置变量)
CURDIR := /home/zht # 记录当前路径
SHELL = /bin/sh
MAKEFILE_LIST := Makefile
.DEFAULT_GOAL := all
MAKEFLAGS = p
HOSTARCH := x86_64
CC = cc # C语言编译器的名称
CPP = $(CC) -E # C语言预处理器的名称 $(CC) -E
CXX = g++ # C++语言的编译器名称
RM = rm -f # 删除文件程序的名称
CFLAGS # C语言编译器的编译选项,无默认值
CPPFLAGS # C语言预处理器的编译选项,无默认值
CXXFLAGS # C++语言编译器的编译选项,无默认值
- Makefile模式规则
1.模式规则
模式规则类似于普通规则,只是在模式规则中,目标名中需要包含有模式字符“%”(一个),包含有模式字符“%”的目标被用来匹配一个文件名,“%”可以匹配任何非空字符串。规则的依赖文件中同样可以使用“%”,依赖文件中模式字符“%”的取值情况由目标中的“%”来决定。
例如:对于模式规则“%.o : %.c”,它表示的含义是:所有的.o文件依赖于对应的.c文件。我们可以使用模式规则来定义隐含规则。要注意的是:模式字符“%”的匹配和替换发生在规则中所有变量和函数引用展开之后,变量和函数的展开一般发生在make读取Makefile时,而模式规则中的“%”的匹配和替换则发生在make执行时。
2.Makefile伪目标
Makefile中存在一种伪目标,我们生成了许多文件编译文件,我们也应该提供一个清除它们的“目标”以备完整地重编译而用。 (以“make clean”来使用该目标) ,调用相应的规则,来清除许多编译的文件(如:*.o文件)因为,我们并不生成“clean”这个文件。“伪目标”并不是一个文件,只是一个标签,由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效。当然,“伪目标”的取名不能和文件名重名,不然其就失去了“伪目标”的意义了。
当然,为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”。
.PHONY : clean
只要有这个声明,不管是否有“clean”文件,要运行“clean”这个目标,只有“make clean”这样。于是整个过程可以这样写:
.PHONY: clean
clean:
rm *.o temp
伪目标一般没有依赖的文件。但是,我们也可以为伪目标指定所依赖的文件。伪目标同样可以作为“默认目标”,只要将其放在第一个。示例,如果你的Makefile需要一口气生成若干个可执行文件,但你只想简单地敲一个make,并且,所有的目标文件都写在一个Makefile中,那么你可以使用“伪目标”这个特性:
all : prog1 prog2 prog3
.PHONY : all
prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o
prog2 : prog2.o
cc -o prog2 prog2.o
prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o utils.o
Comments | NOTHING